Repository: kingToolbox/WindTerm Branch: master Commit: a8336c1d1e3d Files: 521 Total size: 7.0 MB Directory structure: gitextract_tjdsrmql/ ├── README.md ├── benchmark/ │ └── urandom_test.sh ├── images/ │ └── screenshots/ │ └── readme.md └── src/ ├── LICENSE ├── Onigmo/ │ ├── .editorconfig │ ├── .gitignore │ ├── AUTHORS │ ├── COPYING │ ├── HISTORY │ ├── INSTALL │ ├── Makefile.am │ ├── Makefile.in │ ├── README │ ├── README.ja │ ├── aclocal.m4 │ ├── compile │ ├── config.guess │ ├── config.h.in │ ├── config.sub │ ├── configure │ ├── configure.in │ ├── depcomp │ ├── doc/ │ │ ├── API │ │ ├── API.ja │ │ ├── FAQ │ │ ├── FAQ.ja │ │ ├── RE │ │ ├── RE.ja │ │ └── UnicodeProps.txt │ ├── enc/ │ │ ├── ascii.c │ │ ├── big5.c │ │ ├── cp1251.c │ │ ├── cp932.c │ │ ├── euc_jp.c │ │ ├── euc_kr.c │ │ ├── euc_tw.c │ │ ├── gb18030.c │ │ ├── iso8859_1.c │ │ ├── iso8859_10.c │ │ ├── iso8859_11.c │ │ ├── iso8859_13.c │ │ ├── iso8859_14.c │ │ ├── iso8859_15.c │ │ ├── iso8859_16.c │ │ ├── iso8859_2.c │ │ ├── iso8859_3.c │ │ ├── iso8859_4.c │ │ ├── iso8859_5.c │ │ ├── iso8859_6.c │ │ ├── iso8859_7.c │ │ ├── iso8859_8.c │ │ ├── iso8859_9.c │ │ ├── koi8.c │ │ ├── koi8_r.c │ │ ├── mktable.c │ │ ├── sjis.c │ │ ├── unicode/ │ │ │ ├── casefold.h │ │ │ └── name2ctype.h │ │ ├── unicode.c │ │ ├── utf16_be.c │ │ ├── utf16_le.c │ │ ├── utf32_be.c │ │ ├── utf32_le.c │ │ └── utf8.c │ ├── index.html │ ├── index_ja.html │ ├── install-sh │ ├── ltmain.sh │ ├── m4/ │ │ ├── libtool.m4 │ │ ├── ltoptions.m4 │ │ ├── ltsugar.m4 │ │ ├── ltversion.m4 │ │ └── lt~obsolete.m4 │ ├── missing │ ├── onig-config.in │ ├── onig.py │ ├── oniggnu.h │ ├── onigposix.h │ ├── oniguruma.h │ ├── oniguruma.pc.in │ ├── regcomp.c │ ├── regenc.c │ ├── regenc.h │ ├── regerror.c │ ├── regexec.c │ ├── regext.c │ ├── reggnu.c │ ├── regint.h │ ├── regparse.c │ ├── regparse.h │ ├── regposerr.c │ ├── regposix.c │ ├── regsyntax.c │ ├── regtrav.c │ ├── regversion.c │ ├── sample/ │ │ ├── Makefile.am │ │ ├── Makefile.in │ │ ├── crnl.c │ │ ├── encode.c │ │ ├── listcap.c │ │ ├── names.c │ │ ├── posix.c │ │ ├── simple.c │ │ ├── sql.c │ │ └── syntax.c │ ├── st.c │ ├── st.h │ ├── test.rb │ ├── testc.c │ ├── testconv.rb │ ├── testconvu.rb │ ├── testpy.py │ ├── testu.c │ ├── tool/ │ │ ├── .gitignore │ │ ├── CaseFolding.py │ │ ├── convert-name2ctype.sh │ │ └── enc-unicode.rb │ └── win32/ │ ├── Makefile │ ├── config.h │ ├── makedef.py │ ├── onig.rc │ └── testc.c ├── Protocols/ │ ├── Protocol.h │ ├── TelnetProtocol.cpp │ └── TelnetProtocol.h ├── Pty/ │ ├── ConPty.cpp │ ├── ConPty.h │ ├── Pty.cpp │ ├── Pty.h │ ├── UnixPty.cpp │ ├── UnixPty.h │ ├── WinPty.cpp │ ├── WinPty.h │ └── ptyqt LICENSE ├── README.md ├── Utility/ │ ├── CircularBuffer.h │ ├── Cryptographic.cpp │ ├── Cryptographic.h │ ├── MemoryPointer.h │ ├── ScopeGuard.h │ ├── Spin.h │ ├── ThreadLocal.cpp │ └── ThreadLocal.h ├── Widgets/ │ ├── PopupWidget.cpp │ ├── PopupWidget.h │ ├── ScrollBar.cpp │ ├── ScrollBar.h │ ├── Splitter.cpp │ └── Splitter.h └── libssh/ ├── .arcconfig ├── .gitlab-ci.yml ├── AUTHORS ├── BSD ├── CMakeLists.txt ├── COPYING ├── CPackConfig.cmake ├── CTestConfig.cmake ├── ChangeLog ├── CompilerChecks.cmake ├── ConfigureChecks.cmake ├── DefineOptions.cmake ├── INSTALL ├── README ├── README.CodingStyle ├── README.mbedtls ├── README.md ├── SubmittingPatches ├── cmake/ │ ├── Modules/ │ │ ├── AddCCompilerFlag.cmake │ │ ├── AddCMockaTest.cmake │ │ ├── COPYING-CMAKE-SCRIPTS │ │ ├── CheckCCompilerFlagSSP.cmake │ │ ├── DefineCMakeDefaults.cmake │ │ ├── DefineCompilerFlags.cmake │ │ ├── DefinePlatformDefaults.cmake │ │ ├── ExtractSymbols.cmake │ │ ├── FindABIMap.cmake │ │ ├── FindArgp.cmake │ │ ├── FindCMocka.cmake │ │ ├── FindGCrypt.cmake │ │ ├── FindGSSAPI.cmake │ │ ├── FindMbedTLS.cmake │ │ ├── FindNSIS.cmake │ │ ├── FindNaCl.cmake │ │ ├── GenerateMap.cmake │ │ ├── GetFilesList.cmake │ │ └── MacroEnsureOutOfSourceBuild.cmake │ └── Toolchain-cross-m32.cmake ├── config.h.cmake ├── doc/ │ ├── CMakeLists.txt │ ├── authentication.dox │ ├── command.dox │ ├── curve25519-sha256@libssh.org.txt │ ├── forwarding.dox │ ├── guided_tour.dox │ ├── introduction.dox │ ├── linking.dox │ ├── mainpage.dox │ ├── scp.dox │ ├── sftp.dox │ ├── shell.dox │ ├── tbd.dox │ ├── that_style/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── header.html │ │ ├── js/ │ │ │ └── striped_bg.js │ │ └── that_style.css │ └── threading.dox ├── examples/ │ ├── CMakeLists.txt │ ├── authentication.c │ ├── connect_ssh.c │ ├── examples_common.h │ ├── exec.c │ ├── keygen.c │ ├── knownhosts.c │ ├── libssh_scp.c │ ├── libsshpp.cpp │ ├── libsshpp_noexcept.cpp │ ├── proxy.c │ ├── samplesftp.c │ ├── samplesshd-cb.c │ ├── samplesshd-kbdint.c │ ├── scp_download.c │ ├── senddata.c │ ├── ssh_client.c │ ├── ssh_server_fork.c │ ├── sshd_direct-tcpip.c │ └── sshnetcat.c ├── include/ │ ├── CMakeLists.txt │ └── libssh/ │ ├── CMakeLists.txt │ ├── agent.h │ ├── auth.h │ ├── bignum.h │ ├── bind.h │ ├── bind_config.h │ ├── blf.h │ ├── buffer.h │ ├── bytearray.h │ ├── callbacks.h │ ├── chacha.h │ ├── channels.h │ ├── config.h │ ├── config_parser.h │ ├── crypto.h │ ├── curve25519.h │ ├── dh-gex.h │ ├── dh.h │ ├── ecdh.h │ ├── ed25519.h │ ├── fe25519.h │ ├── ge25519.h │ ├── gssapi.h │ ├── kex.h │ ├── keys.h │ ├── knownhosts.h │ ├── legacy.h │ ├── libcrypto.h │ ├── libgcrypt.h │ ├── libmbedcrypto.h │ ├── libssh.h │ ├── libssh_version.h.cmake │ ├── libsshpp.hpp │ ├── messages.h │ ├── misc.h │ ├── options.h │ ├── packet.h │ ├── pcap.h │ ├── pki.h │ ├── pki_priv.h │ ├── poll.h │ ├── poly1305.h │ ├── priv.h │ ├── sc25519.h │ ├── scp.h │ ├── server.h │ ├── session.h │ ├── sftp.h │ ├── sftp_priv.h │ ├── socket.h │ ├── ssh2.h │ ├── string.h │ ├── threads.h │ ├── token.h │ └── wrapper.h ├── libssh.pc.cmake ├── src/ │ ├── ABI/ │ │ ├── current │ │ ├── libssh-4.5.0.symbols │ │ ├── libssh-4.5.1.symbols │ │ ├── libssh-4.6.0.symbols │ │ ├── libssh-4.7.0.symbols │ │ ├── libssh-4.7.1.symbols │ │ ├── libssh-4.7.2.symbols │ │ ├── libssh-4.7.3.symbols │ │ ├── libssh-4.7.4.symbols │ │ ├── libssh-4.8.0.symbols │ │ ├── libssh-4.8.1.symbols │ │ ├── libssh-4.8.2.symbols │ │ ├── libssh-4.8.3.symbols │ │ ├── libssh-4.8.4.symbols │ │ ├── libssh-4.8.5.symbols │ │ └── libssh-4.8.6.symbols │ ├── CMakeLists.txt │ ├── agent.c │ ├── auth.c │ ├── base64.c │ ├── bignum.c │ ├── bind.c │ ├── bind_config.c │ ├── buffer.c │ ├── callbacks.c │ ├── chachapoly.c │ ├── channels.c │ ├── client.c │ ├── config.c │ ├── config_parser.c │ ├── connect.c │ ├── connector.c │ ├── curve25519.c │ ├── dh-gex.c │ ├── dh.c │ ├── dh_crypto.c │ ├── dh_key.c │ ├── ecdh.c │ ├── ecdh_crypto.c │ ├── ecdh_gcrypt.c │ ├── ecdh_mbedcrypto.c │ ├── error.c │ ├── external/ │ │ ├── bcrypt_pbkdf.c │ │ ├── blowfish.c │ │ ├── chacha.c │ │ ├── curve25519_ref.c │ │ ├── ed25519.c │ │ ├── fe25519.c │ │ ├── ge25519.c │ │ ├── ge25519_base.data │ │ ├── poly1305.c │ │ └── sc25519.c │ ├── gcrypt_missing.c │ ├── getpass.c │ ├── gssapi.c │ ├── gzip.c │ ├── init.c │ ├── kdf.c │ ├── kex.c │ ├── known_hosts.c │ ├── knownhosts.c │ ├── legacy.c │ ├── libcrypto-compat.c │ ├── libcrypto-compat.h │ ├── libcrypto.c │ ├── libgcrypt.c │ ├── libmbedcrypto.c │ ├── log.c │ ├── match.c │ ├── mbedcrypto_missing.c │ ├── messages.c │ ├── misc.c │ ├── options.c │ ├── packet.c │ ├── packet_cb.c │ ├── packet_crypt.c │ ├── pcap.c │ ├── pki.c │ ├── pki_container_openssh.c │ ├── pki_crypto.c │ ├── pki_ed25519.c │ ├── pki_ed25519_common.c │ ├── pki_gcrypt.c │ ├── pki_mbedcrypto.c │ ├── poll.c │ ├── scp.c │ ├── server.c │ ├── session.c │ ├── sftp.c │ ├── sftpserver.c │ ├── socket.c │ ├── string.c │ ├── threads/ │ │ ├── libcrypto.c │ │ ├── libgcrypt.c │ │ ├── mbedtls.c │ │ ├── noop.c │ │ ├── pthread.c │ │ └── winlocks.c │ ├── threads.c │ ├── token.c │ └── wrapper.c └── tests/ ├── CMakeLists.txt ├── authentication.c ├── benchmarks/ │ ├── CMakeLists.txt │ ├── bench1.sh │ ├── bench2.sh │ ├── bench_raw.c │ ├── bench_scp.c │ ├── bench_sftp.c │ ├── benchmarks.c │ ├── benchmarks.h │ └── latency.c ├── chmodtest.c ├── chroot_wrapper.c ├── client/ │ ├── CMakeLists.txt │ ├── torture_algorithms.c │ ├── torture_auth.c │ ├── torture_client_config.c │ ├── torture_client_global_requests.c │ ├── torture_connect.c │ ├── torture_forward.c │ ├── torture_hostkey.c │ ├── torture_knownhosts.c │ ├── torture_knownhosts_verify.c │ ├── torture_proxycommand.c │ ├── torture_rekey.c │ ├── torture_request_env.c │ ├── torture_scp.c │ ├── torture_session.c │ ├── torture_sftp_benchmark.c │ ├── torture_sftp_canonicalize_path.c │ ├── torture_sftp_dir.c │ ├── torture_sftp_ext.c │ ├── torture_sftp_fsync.c │ └── torture_sftp_read.c ├── cmdline.c ├── connection.c ├── ctest-default.cmake ├── etc/ │ ├── group.in │ ├── hosts.in │ ├── pam.d/ │ │ └── sshd.in │ ├── pam_matrix_passdb.in │ ├── passwd.in │ └── shadow.in ├── fuzz/ │ ├── CMakeLists.txt │ └── ssh_server_fuzzer.cpp ├── generate.py ├── keys/ │ ├── certauth/ │ │ ├── id_rsa │ │ ├── id_rsa-cert.pub │ │ └── id_rsa.pub │ ├── id_ecdsa │ ├── id_ecdsa.pub │ ├── id_ed25519 │ ├── id_ed25519.pub │ ├── id_rsa │ ├── id_rsa.pub │ ├── ssh_host_dsa_key │ ├── ssh_host_dsa_key.pub │ ├── ssh_host_ecdsa_key │ ├── ssh_host_ecdsa_key.pub │ ├── ssh_host_key │ ├── ssh_host_key.pub │ ├── ssh_host_rsa_key │ ├── ssh_host_rsa_key.pub │ └── user_ca ├── pkd/ │ ├── CMakeLists.txt │ ├── pkd_client.h │ ├── pkd_daemon.c │ ├── pkd_daemon.h │ ├── pkd_hello.c │ ├── pkd_keyutil.c │ ├── pkd_keyutil.h │ ├── pkd_util.c │ └── pkd_util.h ├── server/ │ ├── CMakeLists.txt │ ├── test_server/ │ │ ├── CMakeLists.txt │ │ ├── default_cb.c │ │ ├── default_cb.h │ │ ├── main.c │ │ ├── test_server.c │ │ └── test_server.h │ ├── torture_server.c │ ├── torture_server_auth_kbdint.c │ └── torture_server_config.c ├── sftp_stress/ │ └── main.c ├── ssh_ping.c ├── test_exec.c ├── test_pcap.c ├── test_socket.c ├── test_ssh_bind_accept_fd.c ├── test_tunnel.c ├── tests.h ├── tests_config.h.cmake ├── torture.c ├── torture.h ├── torture_cmocka.c ├── torture_cmocka.h ├── torture_key.c ├── torture_key.h ├── torture_pki.c ├── torture_pki.h ├── unittests/ │ ├── CMakeLists.txt │ ├── torture_bind_config.c │ ├── torture_buffer.c │ ├── torture_bytearray.c │ ├── torture_callbacks.c │ ├── torture_channel.c │ ├── torture_config.c │ ├── torture_crypto.c │ ├── torture_hashes.c │ ├── torture_init.c │ ├── torture_isipaddr.c │ ├── torture_keyfiles.c │ ├── torture_knownhosts_parsing.c │ ├── torture_list.c │ ├── torture_misc.c │ ├── torture_moduli.c │ ├── torture_options.c │ ├── torture_packet.c │ ├── torture_packet_filter.c │ ├── torture_pki.c │ ├── torture_pki_dsa.c │ ├── torture_pki_ecdsa.c │ ├── torture_pki_ed25519.c │ ├── torture_pki_rsa.c │ ├── torture_push_pop_dir.c │ ├── torture_rand.c │ ├── torture_server_x11.c │ ├── torture_session_keys.c │ ├── torture_temp_dir.c │ ├── torture_temp_file.c │ ├── torture_threads_buffer.c │ ├── torture_threads_crypto.c │ ├── torture_threads_init.c │ ├── torture_threads_pki_rsa.c │ └── torture_tokens.c └── valgrind.supp ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ # WindTerm A Quicker and better SSH/Telnet/Serial/Shell/Sftp client for DevOps. _Hello WindTerm :rose:, hello world!_ **We're just beginning! If you want a high performance text editor, you can try [WindEdit](https://www.github.com/kingToolbox/WindEdit/).** # License **Completely FREE for commercial and non-commercial use without limitations.** **All released source codes (except thirdparty directory) are provided under the terms of Apache-2.0 license.** # Introduction See [Intro Videos](https://kingtoolbox.github.io) # Download **Linux binary**, **MacOS binary** and **Windows binary**: https://github.com/kingToolbox/WindTerm/releases # Source Code WindTerm is a **partial** open source project, and the source will be gradually opened. Open source code includes, but is not limited to, the classes that can be used independently, such as functional, algorithms, gui widgets, etc., as well as functional libraries, such as network, protocols, etc., as well as all types that require open source according to the license. # Issues and feature requests Any issues and feature requests are welcome. Please click [issues](https://github.com/kingToolbox/WindTerm/issues) to commit an issue or a feature request. Please click [Discussion](https://github.com/kingToolbox/WindTerm/discussions) to discuss anything about SSH, SFtp, Shell(Linux shell, Windows cmd and powershell), Telnet, Serial and WindTerm. # Screenshots Main Window (zsh): ![MainWindow](https://github.com/kingToolbox/WindTerm/blob/master/images/screenshots/WindTerm.png) Split views: ![SplitView](https://github.com/kingToolbox/WindTerm/blob/master/images/screenshots/SplitView.png) DigeWhite Theme: ![DigeWhite Theme](https://github.com/kingToolbox/WindTerm/blob/master/images/screenshots/WindTerm_DigeWhite_Theme.png) # Features ### SSH, Telnet, Tcp, Shell, Serial, Tmux - SSH v2, Telnet, Raw Tcp, Serial, Shell protocols implemented. [Intro Video](https://kingtoolbox.github.io/2020/01/22/new-session/) - Supports SSH auto execution when session authenticated. - Supports SSH ControlMaster. - Supports SSH ProxyCommand or ProxyJump. [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxycommand/) - Supports SSH agent. [Intro Video](https://kingtoolbox.github.io/2020/08/22/ssh_agent/) - Supports SSH agent forwarding. - Supports SSH auto login with password, public-key, keyboard-interactive, gssapi-with-mic. [Intro Video](https://kingtoolbox.github.io/2020/01/23/auto-login/) - Supports X11 forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/x11_forwarding/) - Supports direct/local port forwarding, reverse/remote port forwarding and dynamic port forwarding. [Intro Video](https://kingtoolbox.github.io/2020/07/21/port_forwarding/) - Supports XModem, YModem and ZModem. [Intro Video](https://kingtoolbox.github.io/tags/modem/) - Integrated sftp, scp client, supports download, upload, remove, rename, make new file/directory and so on. [Intro Video](https://kingtoolbox.github.io/tags/transfer/) - Integrated local file manager, supports move to, copy to, copy from, remove, rename, make new file/directory and so on. - Supports Windows Cmd, PowerShell and Cmd, PowerShell as administrator. - Supports Linux bash, zsh, powershell core and so on. - Supports MacOS bash, zsh, powershell core and so on. - **Supports `tmux integration`**. [Intro Video](https://kingtoolbox.github.io/2025/01/05/tmux-integration/) ### GUI - **Supports Windows, MacOS and Linux.** - **Supports Multilingual User Interface.** - Supports Unicode 13. - Session dialog and session tree. [Intro Video](https://kingtoolbox.github.io/2020/01/22/manage-sessions/) - **Auto Completion.** [Intro Video](https://kingtoolbox.github.io/tags/auto-completion/) - **Free Type Mode.** [Intro Video](https://kingtoolbox.github.io/2022/04/12/free_type_mode/) - **Focus Mode.** [Intro Video](https://kingtoolbox.github.io/2021/06/28/ui_focus_mode/) - **Sync Input.** [Intro Video](https://kingtoolbox.github.io/2021/05/27/sync-input/) - **Enhanced protection of the session username and password.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/protection-username-password/) - **Command palette.** [Intro Video](https://kingtoolbox.github.io/tags/command-palette/) - **Command sender.** [Intro Video](https://kingtoolbox.github.io/tags/sender/) - **Explorer Pane.** [Intro Video](https://kingtoolbox.github.io/2021/05/27/explorer/) - **Shell Pane.** - **Quick Bar.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/quickbar/) - **Paste Dialog.** [Intro Video](https://kingtoolbox.github.io/2020/08/22/paste_dialog/) - **Local and remote modes with vim keybindings. (Using Shift+Enter key to switch between remote and local mode**) [Intro Video](https://kingtoolbox.github.io/2020/06/21/keyboard-modes/) - Supports time stamp, folding, outlining, split views. - **Supports powerline in Linux and PowerShell, e.g. Oh-My-Zsh, Oh-My-Posh.** [Intro Image](https://github.com/kingToolbox/WindTerm#screenshots) - Supports color schemes like vscode. [Intro Video](https://kingtoolbox.github.io/2020/01/23/highlight/) - Supports searching and previewing. [Intro Video](https://kingtoolbox.github.io/2020/01/22/search-and-mark/) - Supports highlighting the opening and closing delimiter, such as (), [], {} and the customed delimiters. [Intro Video](https://kingtoolbox.github.io/2020/06/28/pair/) - Supports changing the UI theme. [Intro Video](https://kingtoolbox.github.io/2020/09/18/theme/) - Supports setting the tab color. [Intro Video](https://kingtoolbox.github.io/2020/09/18/tabbar-change-tabcolor/) - Supports searching over the opened tabs. [Intro Video](https://kingtoolbox.github.io/2021/03/11/tabbar-search-tab/) - Supports closing tabs to the right. - Supports setting the windows transparency. [Intro video](https://kingtoolbox.github.io/2020/11/13/windows-opacity/) - Supports select-to-copy, right-click-to-paste or middle-click-to-paste. - Supports searching text online with Google, Bing, Github, Stackoverflow, Wikipedia and DuckDuckGo. [Intro video](https://kingtoolbox.github.io/2020/11/13/search-online/) - Supports hiding mouse cursor while typing. - **Supports locking screen.** [Intro video](https://kingtoolbox.github.io/2021/04/23/lock-screen/) ### Term - Supports vt100, vt220, vt340, vt420, vt520, xterm, xterm-256-colors. - Supports unicode, emojis, true-color, mouse protocol, etc. - Supports auto wrap mode. [Intro Video](https://kingtoolbox.github.io/2020/01/22/auto-wrap/) - Protocols and terms can be customed. - All vttest tests have passed except Tektronix 4014. ### Session - **Supports HTTP and SOCKS5 proxy.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxy-http-socks5/) - **Supports Jump Server proxy.** [Intro Video](https://kingtoolbox.github.io/2021/03/11/proxy-jump-server/) - Supports manual and automated session logging. [Intro Video](https://kingtoolbox.github.io/tags/logging/) - Rename and duplicate session. [Intro Video](https://kingtoolbox.github.io/tags/tabbar/) - Restore last sessions and layouts when restart. [Intro Video](https://kingtoolbox.github.io/2020/01/22/restore-sessions/) - Supports opening a specific session or set of sessions on startup. ### Performance - Dynamic memory compression, typically `20%` to `90%` of the working memory load can be reduced. - High performance, low memory, low latency. [Intro Video](https://kingtoolbox.github.io/2020/01/23/windterm-putty-performance/) # Sftp Performance The hardware used for generating the data in these benchmarks was windows 10 - 2.3 GHz Intel Core i5 and 8GB memory. **WindTerm1.72, WindTerm 1.2, FileZilla 3.48.1, WinSCP 5.17.2 (Build 10278)** tests are performed on WSL(Ubuntu 18.04.2). The version of clients: | Application | Version | Release Date | | --- | --- | --- | | windterm | v1.72 | 2020-10-25 | | windterm | v1.2 | 2020-06-15 | | FileZilla | v3.48.1 | 2020-05-19 | | WinScp | v5.17.2 (Build 10278) | 2020-03-09 | **All test data is for reference only.** ### 5GB huge file (5,154,830 KB), generated by random data | | Download Time | Download Rate | Upload Time | Upload Rate | | --- | --- | --- | --- | --- | | WindTerm 1.72 (Use high speed transfer) | **23s** | **216.3 MB/s** | **20s** | **247.0 MB/s** | | WindTerm 1.72 | **23s** | **214.7 MB/s** | **20s** | **244.0 MB/s** | | WindTerm 1.2 | 37s | 139.3 MB/s | 43s | 119.9 MB/s | | FileZilla | 32s | 161.1 MB/s | 30s | 171.8 MB/s | | WinSCP | 81s | 63.7 MB/s | 91s | 56.7 MB/s | ### 4400 files, 16 folders (107,042 KB), unzipped from [vim-7.4.1049.zip](https://github.com/vim/vim/archive/v7.4.1049.zip) | | Download Time | Download Rate | Upload Time | Upload Rate | | --- | --- | --- | --- | --- | | WindTerm 1.7 | **26s** | **3.9 MB/s** | 13s | 8.1 MB/s | | WindTerm 1.2 | 32s | 3.4 MB/s | **10s** | **10.7 MB/s** | | FileZilla | 48s | 2.2 MB/s | 35s | 3.1 MB/s | | WinSCP | 42s | 2.6 MB/s | 12s | 8.9 MB/s | # Terminal Performance The hardware used for generating the data in these benchmarks was windows 10 - 2.3 GHz Intel Core i5 and 8GB memory. MacOs 10.13 - 2.3 GHz Intel Core i5 and 8GB memory. **WindTerm 1.72, rxvt, putty, xterm, Windows Terminal** tests are performed on WSL(Ubuntu 18.04.2). **Iterm2, kitty, Alacritty** tests are performed on MacOS shell, For WindTerm: No color scheme used in windterm. Color scheme will result in approximately 2% loss and more memory usage. For Alacritty: Only supports up to 100,000 scrollback lines, so every test use "history: 100000" setting and no memory usage measured. For Windows Terminal: Only supports up to 65,535 scrollback lines, so every test use "historySize: 65535" setting and no memory usage measured. The version of terminals: | Application | Version | Release Date | | --- | --- | --- | | windterm | v1.72 | 2020-10-25 | | rxvt-unicode | v9.2.2 | 2016-05-14 | | putty | v0.71 | 2019-03-16 | | xterm | v3.30 | 2017-06-20 | | iterm2 | v3.3.6 | 2019-10-09 | | alacritty | v0.5.0 | 2020-07-21 | | kitty | v0.14.6 | 2019-09-25 | | Windows Terminal | v1.3.2651.0 | 2020-09-22 | **All test data is for reference only.** ## Test Command: "cat ./benchmark_randomdata" The benchmark_randomdata contains 97.6MB random text (102,401,504 bytes, 1,329,878 lines, generated and tested by [random_test.sh](https://github.com/kingToolbox/WindTerm/blob/master/benchmark/urandom_test.sh)) In all cases, three runs were made to warm system caches. The reported numbers are the median of five runs. 1. Telnet: | | Lines of scrollback | Data Rate(MB/sec) | Memory Usage(MB) | | --- | --- | --- | --- | | WindTerm | unlimited | **52.1** | **106.6** | | rxvt | 1,350,000 | 37.8 | 842.2 | | Putty | 1,350,000 | 4.9 | 733.4 | | xterm | 1,350,000 | 2.2 | 3328.4 | | Windows Terminal + telnet.exe | 65,535 | 0.1 | Not measured, use 65,535 scrollback lines setting | 2. SSH: | | Lines of scrollback | Data Rate(MB/sec) | Memory Usage(MB) | | --- | --- | --- | --- | | WindTerm | unlimited | **41.8** | **108.5** | | rxvt | 1,350,000 | 40.2 | 842.2 | | Putty | 1,350,000 | 4.8 | 734.9 | | xterm | 1,350,000 | 2.3 | 3328.4 | | Windows Terminal + ssh.exe | 65,535 | 2.1 | Not measured, use 65,535 scrollback lines setting | 3. Shell: | | Lines of scrollback | Data Rate(MB/sec) | Memory Usage(MB) | | --- | --- | --- | --- | | iterm2 | unlimited | - (Take too long time) | more than 1300 | | kitty | unlimited | 17.2 | 2655 | | Alacritty | 100,000 | 41.3 | - | ## Test command: "time seq 1 n" (n = [1000000, 2000000, 5000000, 10000000], scrollback lines: unlimited) ### n = 1,000,000 | | Time(sec) | Memory Usage(MB) | | --- | --- | --- | | WindTerm | 1.236 | **16.1** | | rxvt | 5.082 | 633.3 | | putty | 4.161 | 551.1 | | xterm | 40.421 | 2500.7 | | iterm2 | 2.116 | 146.3 | | Kitty | 2.535 | 2376.5 | | Alacritty | **1.162** | Not measured, use 100,000 scrollback lines setting | | Windows Terminal + ssh.exe | 23.246 | Not measured, use 65,535 scrollback lines setting | ### n = 2,000,000 | | Time(sec) | Memory Usage(MB) | | --- | --- | --- | | WindTerm | **2.287** | **24.1** | | rxvt | 10.896 | 1266.6 | | putty | 16.045 | 1102.6 | | xterm | 68.154 | 5005.5 | | iterm2 | 4.181 | 383.2 | | Kitty | 5.620 | 4749.9 | | Alacritty | 2.322 | Not measured, use 100,000 scrollback lines setting | | Windows Terminal + ssh.exe | 50.381 | Not measured, use 65,535 scrollback lines setting | ### n = 5,000,000 | | Time(sec) | Memory Usage(MB) | | --- | --- | --- | | WindTerm | **5.520** | **68.2** | | rxvt | 27.533 | 3166.2 | | putty | 45.911 | 2757.1 | | xterm | - | Out of memory | | iterm2 | 10.805 | 1048.3 | | Kitty | - | Out of memory | | Alacritty | 5.799 | Not measured, use 100,000 scrollback lines setting | | Windows Terminal + ssh.exe | 130.371 | Not measured, use 65,535 scrollback lines setting | ### n = 10,000,000 | | Time(sec) | Memory Usage(MB) | | --- | --- | --- | | WindTerm | **10.674** | **133.3** | | rxvt | - | Out of memory | | putty | - | Out of memory | | xterm | - | Out of memory | | iterm2 | 20.468 | 2231.3 | | Kitty | - | Out of memory | | Alacritty | 11.598 | Not measured, use 100,000 scrollback lines setting | | Windows Terminal + ssh.exe | 264.739 | Not measured, use 65,535 scrollback lines setting | ### n = 10,000,000 scrollback = 30 Lines | | Time(sec) | Memory Usage(MB) | | --- | --- | --- | | WindTerm | 10.167 | 0.7 | | rxvt | **9.687** | **0.1** | | putty | 95.382 | 0.4 | | xterm | 286.510 | **0.1** | | iterm2 | 25.448 | 7.4 | | Kitty | 16.104 | 0.5 | | Alacritty | 11.798 | Not measured, use zero scrollback lines setting | | Windows Terminal + ssh.exe | 261.096 | Not measured, use zero scrollback lines setting | # Linux Terminal Performance The hardware used for generating the data in these benchmarks was Debian 10 Vm - 4cpu and 4GB memory. For WindTerm: No color scheme used in windterm. Color scheme will result in approximately 2% loss and more memory usage. For other terminals: No memory usage measured because most of them write the history to disk or only support a limited number of lines in memory.. The version of terminals: | Application | Version | Release Date | | --- | --- | --- | | Windterm | v1.9 | 2020-12-22 | | Gnome | v3.30.2 | 2018-10-22 | | Mate Terminal | v1.20.2 | 2019-02-11 | | Konsole | v18.04.0 | 2019-04-12 | | Xfce4 Terminal | v0.8.7.4 | 2018-5-15 | | QTerminal | v0.14.1 | 2019-01-26 | **All test data is for reference only.** ## Test Command: "cat ./benchmark_randomdata" The benchmark_randomdata contains 97.6MB random text (102,401,504 bytes, 1,329,878 lines, generated and tested by [random_test.sh](https://github.com/kingToolbox/WindTerm/blob/master/benchmark/urandom_test.sh)) In all cases, three runs were made to warm system caches. The reported numbers are the median of five runs. | | Cost Time | | --- | --- | | WindTerm | **1.976s** | | Gnome Terminal | 9.781s | | Mate Terminal | 9.841s | | Konsole | 25.050s | | xfce4 Terminal | 10.520s | | QTerminal | 20.763s | ## Test command: "time seq 1 n" (n = [1000000, 2000000, 5000000, 10000000], scrollback lines: unlimited) | n | 1,000,000 | 2,000,000 | 5,000,000 | 10,000,000 | 10,000,000
(scrollback lines: 100) | | --- | --- | --- | --- | --- | --- | | WindTerm | 0.846s (18.6MB) | **1.574s** (26.6MB) | **4.046s** (56.4MB) | **8.232s** (102.2MB) | **7.748s** (3.4MB) | | Gnome Terminal | 0.920s | 2.152s | 5.271s | 11.111s | 13.109s | | Mate Terminal | **0.822s** | 1.698s | 5.943s | 10.920s | 12.290s | | Konsole | 1.612s | 3.199s | 8.157s | 16.029s | 15.650s | | xfce4 Terminal | 0.870s | 2.160s | 5.866s | 12.089s | 13.304s | | QTerminal | 9.272s | 18.391s | 45.999s | 104.277s | 17.208s | # Latency Considering the network influence on the latency, the following data is from [WindEdit](https://github.com/kingToolbox/digedit). DIGEdit is the text component of WindTerm. | | Min | Max | Avg | SD | | --- | --- | --- | --- | --- | |WindEdit| 1.9 | 7.6 | 2.9 | 0.8 | |Windows Notepad | 0.9 | 16.5 | 7.8 | 1.8 | |GVim | 0.9 | 10.4 | 2.8 | 1.2 | # Shortcuts [Shortcut Keys List](https://kingtoolbox.github.io/tags/keyboard/) # Roadmap **Release cycle:** 2-3 months. **Prerelease cycle:** 4~6 weeks # Roadmap of v2.7 (February 2025, for reference only) - **Resolve issues as much as possible** - SSH Agent Forwaring - Tmux integration - Command Snippet [Description](https://github.com/kingToolbox/WindTerm/issues/239#issuecomment-951934488) (Postponed to a later version ) - SSH GSSAPI Authentication (Postponed to a later version ) - Search in sessions (Postponed to a later version ) Download: [WindTerm 2.7.0 Prerelease 3](https://github.com/kingToolbox/WindTerm/releases/tag/2.7-prerelease-3) (2025-2-10) **Roadmap of version 2.x:** - External tools - Protocols: - Mosh - Rlogin - Session: - Auto Complete - Chat mode - Log viewer - File transfer: - ftp, ftps - Script, macro and plugin stystem - More ... **Release Schedule:** Version | Level | Target | Status | Timeline ------------ | ------------- | -------------- | ---------- | ----------- v0.x | Basic | Basic framework and basic features, but complete a high-performance text editor ([WindEdit](https://github.com/kingToolbox/WindEdit)) as the base, and be able to use them normally. | Finished | Long long ago ~ Sprint of 2020 v1.x | Manual | Perfect features and can be used by most developers in their daily work | Finished | Spring of 2020 ~ Winter of 2020 **v2.x** | **Semi automatic** | **Through triggers, macros, events, notifications and so on, developers can be assisted to complete some operations.** | **Developing** | **Spring of 2021 ~ Summer of 2022** v3.x | Fully automatic | Through plugins, scripts, machine learning and so on, automatically operating with achieving non-attended | Planning | Summer of 2022 ~ Winter of 2023 # Acknowledgement | | Contribution | | ---------- | ------------- | | [EvoWebFrance](https://github.com/EvoWebFrance) | French translation | | [kvnklk](https://github.com/kvnklk) | German translation | | [Lemonawa](https://github.com/Lemonawa) | Simplified Chinese translation | | [LuxNegra](https://github.com/LuxNegra) | French translation | | [MosamXu](https://github.com/MosamXu) | Simplified Chinese translation | ================================================ FILE: benchmark/urandom_test.sh ================================================ # Generate 100MB data. if [ ! -f "./benchmark_randomdata" ];then cat /dev/urandom | base64 | dd of=./benchmark_randomdata bs=1024 count=100KB fi echo "Benchmark Result:" { time dd if=./benchmark_randomdata bs=10240; } ================================================ FILE: images/screenshots/readme.md ================================================ Screenshots of WSL and SplitView. ================================================ FILE: src/LICENSE ================================================ 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. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: src/Onigmo/.editorconfig ================================================ ; see: http://editorconfig.org/ root = true [*] end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [**.[ch]] indent_style = tab indent_size = 2 tab_width = 8 [**.py] indent_style = space indent_size = 4 [**.rb] indent_style = space indent_size = 2 tab_width = 8 [win32/*] end_of_line = crlf [win32/*.py] end_of_line = lf ================================================ FILE: src/Onigmo/.gitignore ================================================ # ignore dot-files, binary files and backup files .* *.o *.lo *.so *.a *.la *.obj *.def *.dll *.exe *.exp *.lib *.pyc *.bak *.BAK *~ *.swp *.orig *.rej *.RES *.res # don't want to ignore !.gitignore !.editorconfig # working dirs .deps .libs # autotools generated files /autom4te.cache /config.h /config.log /config.status /libtool /onig-config /oniguruma.pc /Makefile /sample/Makefile /stamp-h1 # generated executable files /enc/mktable /sample/crnl /sample/encode /sample/listcap /sample/names /sample/posix /sample/simple /sample/sql /sample/syntax /testc /testcu /testp # tag files tags TAGS # GNU global files GPATH GRTAGS GSYMS GTAGS ================================================ FILE: src/Onigmo/AUTHORS ================================================ kentkt AT csc DOT jp (K.Takata) sndgk393 AT ybb DOT ne DOT jp (K.Kosako) ================================================ FILE: src/Onigmo/COPYING ================================================ Onigmo (Oniguruma-mod) LICENSE ------------------------------ /*- * Copyright (c) 2002-2009 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ Oniguruma LICENSE ----------------- /*- * Copyright (c) 2002-2009 K.Kosako * 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. */ Ruby BSDL --------- Copyright (C) 1993-2013 Yukihiro Matsumoto. 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. ================================================ FILE: src/Onigmo/HISTORY ================================================ History of Onigmo (Oniguruma-mod) 2013/07/03: Version 5.13.5 2013/07/03: [dist] update LTVERSION to "5:0:5". 2013/07/02: [bug] (thanks Akinori MUSHA and Ippei Obayashi) Fix a renumbering bug in condition regexp with a named capture. see: https://bugs.ruby-lang.org/issues/8583 2013/05/30: [dist] Merge Oniguruma 5.9.3 and 5.9.4. Also change the version of autotools. (automake 1.11.1, autoconf 2.65, libtool 2.2.6b) 2013/05/29: [spec] (thanks Akinori MUSHA) Allow ENCLOSE_OPTION in look-behind. 2013/04/10: [bug] fix problem with optimization of \z. see: http://bugs.ruby-lang.org/issues/8210 2013/03/17: Version 5.13.4 2013/03/17: [dist] update LTVERSION to "5:0:4". 2013/03/10: [bug] fix lookbehind assertion fails with /m mode enabled. see: http://bugs.ruby-lang.org/issues/8023 2013/03/05: [bug] fix \Z matches where it shouldn't. see: http://bugs.ruby-lang.org/issues/8001 2013/03/02: [dist] add .editorconfig (see: http://editorconfig.org/) 2013/03/01: [bug] fix character class with ASCII flag. see: http://bugs.ruby-lang.org/issues/7972 2013/02/27: [bug] fix case-insensitive group. see: http://bugs.ruby-lang.org/issues/7974 2012/11/03: Version 5.13.3 2012/11/03: [dist] update LTVERSION to "5:0:1". 2012/10/18: [dist] Win32: add batch-mode inference rules. 2012/10/17: [bug] merge Ruby r37175. should match with a hyphen after a range in a character class. 2012/09/02: [impl] merge Ruby r36440. remove "found" indirect flag to suppress warnings by gcc 4.7. 2012/07/11: [dist] tool/enc-unicode.rb: suppress warning of Hash#index on Ruby 1.9. 2012/07/10: [dist] testpy.py: return the result of test. 2012/07/10: [dist] testpy.py: simplify the method of setting output encoding. 2012/07/03: [dist] testpy.py: error messages are not displayed. 2012/06/16: [impl] merge Ruby r36072 partially. regparse.c (is_onechar_cclass): restructured to clarify that c is used if found == 1. 2012/06/16: [dist] merge Ruby r36070. tool/enc-unicode.rb: add comment why it uses Hash#index. 2012/05/22: [impl] merge Ruby r35724. enc/sjis.c (code_to_mbclen): return ONIGERR_INVALID_CODE_POINT_VALUE if the code is invalid. 2012/05/11: [dist] update .gitignore. 2012/04/30: [dist] configure.in: add 'foreign' option in AM_INIT_AUTOMAKE. 2012/04/18: [dist] fix samples to support x64. NOTE: This is a preliminary fix. It is needed that additional support for the LLP64 data model such as Visual C++ x64. 2012/04/14: [dist] update Makefile.{am,in}. Add new files. Enable making test[cu].c from test*.rb. 2012/04/14: [dist] update tests. (testc.c, testu.c, etc.) 2012/03/29: Version 5.13.2 2012/03/24: [impl] suppress warnings. 2012/03/24: [impl] remove unnecessary casts. 2012/03/23: [impl] merge Ruby r35107. suppress warnings. 2012/03/21: [bug] memory leak occurs when char class contains only one char. 2012/03/21: [impl] use actual type to get the size. see: http://bugs.ruby-lang.org/issues/6144 2012/03/15: [impl] check the return code of add_ctype_to_cc(). see: http://bugs.ruby-lang.org/issues/6145 2012/03/15: [impl] fix error message. 2012/03/15: [bug] broken conditional expressions are allowed. see: http://bugs.ruby-lang.org/issues/6143 2012/03/15: [impl] merge Ruby r35027. adjust style. 2012/03/06: [impl] merge Ruby r34905. Remove unused variables. 2012/02/29: [bug] unexpected match occurs when a char class contains no char. 2012/02/25: [impl] CaseFolding.py: fix regexp. 2012/02/25: [impl] define the sizes of case folding tables in casefold.h. 2012/02/24: [dist] fix samples to support x64. NOTE: This is a preliminary fix. 2012/02/23: [impl] merge Ruby r34730. don't use // comment. 2012/02/20: [impl] merge Ruby r34684, r34688 and r34692. fix-up warnings. 2012/02/17: [dist] (thanks NARUSE, Yui) tool/enc-unicode.rb: Don't use \h to work with Ruby 1.8. 2012/02/14: [spec] relative group reference in back reference with nest level is allowed. 2012/02/05: Version 5.13.1 2012/02/04: [spec] allow \b and \B in look-behind. 2012/02/01: [new] support for Unicode 6.1. 2012/01/20: Version 5.13.0 2012/01/20: [dist] update LTVERSION to "5:0:0". 2012/01/17: [bug] memory leak occurs when xrealloc fails. 2012/01/15: [bug] Calling function "add_code_range" without checking return value. 2012/01/12: [bug] testpy.py: error messages are not displayed when Python 2.x is used. 2012/01/11: [bug] memory leak occurs when history_tree_add_child fails. 2012/01/11: [bug] (thanks Masashi Tsuji) OnigCaptureTreeNode memory leak. 2012/01/09: [spec] ONIG_OPTION_ASCII_RANGE should be enabled in ONIG_SYNTAX_JAVA. 2012/01/09: [new] support for Ruby 1.9.3 compatible \b, \B and POSIX brackets. add ONIG_OPTION_WORD_BOUND_ALL_RANGE and ONIG_OPTION_POSIX_BRACKET_ALL_RANGE. remove ONIG_SYN_POSIX_BRACKET_ALWAYS_ALL_RANGE. 2011/12/31: [bug] /^ss$/i doesn't match "\x{DF}". 2011/12/30: [new] add ONIG_SYN_POSIX_BRACKET_ALWAYS_ALL_RANGE option. 2011/12/29: [bug] (thanks Nobuyoshi Nakada) C standard requires va_end() to be placed before return. quote macro expansions. 2011/12/28: Version 5.12.1 2011/12/24: [new] merge Ruby r23714, r28980 and r34050. add onig_memsize() and onig_region_memsize(). 2011/12/24: [new] support for Python 3.x. (onig.py and testpy.py) 2011/12/14: [bug] testpy.py doesn't work on Ubuntu. 2011/12/12: Version 5.12.0 2011/12/12: [dist] update LTVERSION to "4:0:0". 2011/12/11: [impl] use ONIGENC_IS_UNICODE to check if the encoding is Unicode encoding. 2011/12/10: [new] support for Unicode 6.0. new scripts, ages, blocks (\p{In_XXX}) and case foldings. tool/enc-unicode.rb is imported from Ruby 1.9.3. 2011/12/10: [spec] \p{Print} shouldn't include newlines. \p{Print} = \p{Graph} + \p{Space_Separator} 2011/12/10: [bug] \p{NEWLINE} should not be allowed. 2011/12/05: [new] support for PyPy 1.7. (onig.py and testpy.py) 2011/12/01: [bug] /a{2}/i doesn't match 'AA'. 2011/11/21: [impl] use ONIG_LAST_CODE_POINT instead of ~((OnigCodePoint )0). 2011/11/17: [bug] code ranges are not merged properly. 2011/11/17: [bug] /[\x{0}-X]/i doesn't match properly when UTF-16/32 is used. 2011/10/16: Version 5.11.4 2011/10/16: [dist] update LTVERSION to "3:0:2". 2011/10/15: [tune] optimize Sunday's quick search. 2011/10/07: [API] add ONIG_OPTION_DOTALL option as an alias of ONIG_OPTION_MULTILINE. 2011/10/04: [impl] add Sunday's quick search. add config USE_SUNDAY_QUICK_SEARCH. 2011/10/04: [impl] add case-insensitive Boyer-Moore-Horspool search. 2011/10/03: [spec] check minimum digits of hexadecimal numbers. \uHHHH should be exactly four digits. 2011/10/03: [API] rename ONIG_SYN_OP2_QMARK_BAR_BRANCH_RESET to ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET. 2011/09/18: Version 5.11.3 2011/09/18: [dist] update LTVERSION to "3:0:1". 2011/09/18: [spec] \R matches \x85, \x2028 and \x2029 in Unicode encodings. 2011/09/18: [new] add ONIG_OPTION_NEWLINE_CRLF. 2011/09/18: [tune] optimize \x{}. 2011/09/17: [tune] expand a{n,m} to 'a...a' + a{0,m-n}. 2011/09/12: [bug] /.*\Z/ doesn't match properly. 2011/09/10: Version 5.11.2 2011/09/09: [bug] merge Ruby r24546. fix the first character bigger than sb_out was dropped. 2011/09/09: [bug] merge Ruby r19864. CCV_SB is only for single byte. 2011/09/09: [bug] merge Ruby r24550. fix memory leaks. 2011/09/08: Version 5.11.1 2011/09/08: [impl] merge some part of Ruby r29928. (update debug log.) 2011/09/08: [impl] merge Ruby r32544. Power PC does not allow unaligned word access. 2011/09/07: [bug] \g<0> doesn't work when USE_PERL_SUBEXP_CALL isn't defined. 2011/09/07: [tune] optimize character class. 2011/09/06: [tune] optimize (?a). 2011/09/06: [tune] optimize \R. 2011/09/03: Version 5.11.0 2011/09/03: [dist] update LTVERSION to "3:0:0". 2011/09/01: [new] add OnigPosition. 2011/09/01: [new] (thanks h-tom) support for x64. 2011/09/01: [new] add ONIG_SYNTAX_PYTHON (onig.py). 2011/08/30: [dist] check _MSC_VER instead of _NMAKE_VER when LTCG is used. 2011/08/25: [tune] reduce conditional branches. use ONIGENC_IS_IN_RANGE macro to check the code range. 2011/08/18: [dist] add a resource script for onig.dll (win32/onig.rc). 2011/08/09: Version 5.10.6 2011/08/09: [dist] a .def file can be used to export APIs. 2011/08/08: [dist] update win32/Makefile to support LTCG optimization. 2011/08/07: [new] add new test scripts: testpy.py and onig.py 2011/08/07: [new] add a new syntax: ONIG_SYNTAX_PYTHON 2011/08/03: Version 5.10.5 2011/08/03: [dist] update win32/Makefile. 2011/08/03: [dist] update tests to support ONIG_OPTION_ASCII_RANGE option. 2011/07/30: [new] EUC-JP: support for JIS X 0212 (Supplemental Kanji). 2011/07/30: [impl] not to use ONIG_ENCODING_SJIS inside ONIG_ENCODING_CP932. 2011/07/29: [new] Add support for EUC-JIS-2004. (This feature is not enabled by default.) 2011/07/29: [impl] EUC-JP: check the length more strictly. 2011/07/29: [dist] translate Japanese comments to English. 2011/07/29: [bug] \p{Katakana} doesn't match JIS X 0201 Katakana when EUC-JP is used. 2011/07/28: [dist] change the encoding of Japanese documents to UTF-8. 2011/07/26: [bug] [^x]*x causes invalid pointer access. 2011/07/19: [spec] allow (?au) in Ruby syntax mode. 2011/07/16: [new] add \g<0> and \g<+n>. 2011/07/11: Version 5.10.4 2011/07/11: [dist] update autotools. use automake 1.10.3, autoconf 2.68 and libtool 2.4. 2011/07/11: [impl] add typedefs of intptr_t/uintptr_t for old VC++ compilers. 2011/07/11: [impl] include stdint.h and stddef.h for intptr_t/uintptr_t. 2011/07/04: [tune] implicit-anchor optimization 2011/07/04: [bug] onig_search_gpos() may return wrong OnigRegion. 2011/07/04: [bug] fix typo in debug log. 2011/07/04: [tune] enable optimization for .* except look-behind. 2011/07/04: [bug] Revert "enable optimization for .* except look-behind" 2011/07/03: Version 5.10.3 2011/07/01: [tune] implicit-anchor optimization 2011/06/30: [bug] Revert "[tune] implicit-anchor optimization" 2011/06/30: [bug] (?a) doesn't work properly 2011/06/29: Version 5.10.2 2011/06/29: [tune] implicit-anchor optimization 2011/06/28: [impl] remove duplicated debug log. 2011/06/28: [bug] (?a) doesn't work for \d, \h and \s. 2011/06/28: [bug] should not backtrack in \X. 2011/06/24: Version 5.10.1 2011/06/24: [new] add (?(cond)yes) and (?(cond)yes|no). 2011/06/24: [bug] double free in \R and \X. 2011/06/24: [tune] enable optimization for .* except look-behind. 2011/06/21: [spec] number is not allowed in (?&name) and (?P>name). 2011/06/18: Version 5.10.0 2011/06/18: [impl] export onig_new_without_alloc() API. 2011/06/15: [spec] change Ruby syntax options. add \K, \R and \X. 2011/06/15: [spec] change Perl syntax options. Rename ONIG_SYNTAX_PERL to ONIG_SYNTAX_PERL58. Rename ONIG_SYNTAX_PERL_NG to ONIG_SYNTAX_PERL58_NG. Add ONIG_SYNTAX_PERL as Perl 5.10+ compatible syntax. 2011/06/14: [new] add (?R), (?0) and (?+n). 2011/06/14: [new] add new character properties in EUC-JP: Han, Latin, Greek and Cyrillic. 2011/06/14: [new] add new encoding: CP932. 2011/06/14: [new] add new character properties in Shift_JIS: Han, Latin, Greek and Cyrillic. 2011/06/13: [bug] (?-n) doesn't work 2011/06/13: [new] add ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL 2011/06/13: [impl] remove unused ONIG_SYN_CAPTURE_LEFT_MOST_NAMED_GROUP flag. 2011/06/13: [bug] (?a) doesn't work with Unicode encodings. 2011/06/12: [new] add EUC-JP case folding. 2011/06/12: [new] add Shift_JIS case folding. 2011/06/12: [spec] add ONIG_OPTION_ASCII_RANGE option to OnigSyntaxRuby. 2011/06/12: [new] add Python/PCRE compatible named group: (?P...), (?P=name) and (?P>name). 2011/06/11: [new] add \g{n}, \g{-n} and \g{name}. 2011/06/10: [bug] char class may cause memory leak http://redmine.ruby-lang.org/issues/show/4061 2011/06/10: [bug] invalid backref number/name http://redmine.ruby-lang.org/issues/show/2759 2011/06/10: [bug] /(?<=a).*b/ =~ "aab" doesn't match http://redmine.ruby-lang.org/issues/show/3568 2011/06/10: [bug] Case Sensitivity in Regular Expressions with Lookbehind http://redmine.ruby-lang.org/issues/show/4088 2011/06/10: [spec] allow any target for quantifiers. add USE_NO_INVALID_QUANTIFIER. 2011/06/10: [new] add Perl 5.14 compatible character set modifier: (?adlu) and (?^alu). 2011/06/10: [new] add (?&name), (?n) and (?-n). add USE_PERL_SUBEXP_CALL. 2011/06/10: [new] add \R, \X and \K. 2011/06/10: [spec] allow negative look behind in look behind. 2011/06/10: [new] add: onig_search_gpos(). 2011/06/10: fork from Oniguruma 5.9.2. ====================================================================== History of Oniguruma 2013/04/04: Version 5.9.4 2013/04/04: [dev] remove Makefile.in from git repository. 2013/04/04: [dist] add oniguruma.pc.in file. (for pkg-config) (thanks Giulio Paci) 2012/10/26: Version 5.9.3 2012/10/15: remove warnings "test: =: unary operator expected" in ./configure. (thanks t_okazaki) 2012/10/15: fix print_tree ENCLOSE_OPTION bug. (thanks Suraj N. Kurapati) 2010/01/09: Version 5.9.2 2010/01/05: [bug] fix utf16be_code_to_mbc() and utf16le_code_to_mbc(). 2008/09/16: [bug] fix memory leaks in parse_exp(). 2008/08/01: [bug] fix memory leaks. 2008/06/17: [bug] invalid type of argument was used in onig_st_lookup_strend(). 2008/06/16: [bug] invalid CaseFoldMap entry in ISO-8859-5. 0xdf -> 0xde 2008/02/19: [new] add: onig_reg_init(). 2008/02/19: [new] add: onig_free_body(). 2008/02/19: [new] add: onig_new_without_alloc(). 2008/02/19: [API] rename onig_alloc_init() to onig_reg_init(), and argument type changed. 2008/01/31: [impl] move UTF16_IS_SURROGATE_XXX() to regenc.h. 2008/01/30: [bug] (thanks akr) fix euctw_islead(). 2008/01/23: [bug] update enc/koi8.c. 2007/12/22: Version 5.9.1 2007/12/21: [impl] add sprint_byte(). 2007/11/28: [bug] (thanks Andy Armstrong) don't overwrite error code in fetch_name(). 2007/11/12: [bug] utf8 mbc length of code 0xfe, 0xff are not 1, 2007/10/23: [spec] onig_enc_len() takes three arguments. (not used) 2007/10/15: [impl] (thanks Rui Hirokawa) add check HAVE_STDARG_H. 2007/09/07: [API] rename enc_len() to onig_enc_len() in oniguruma.h. 2007/09/04: [API] remove ONIGENC_ERR_XXXXX. 2007/09/03: [API] add error ONIGERR_INVALID_CODE_POINT_VALUE. 2007/09/03: [impl] change error message to "invaid code point value" for ONIGERR_INVALID_WIDE_CHAR_VALUE. 2007/09/03: [bug] xxx_code_to_mbclen() should return ONIGERR_INVALID_WIDE_CHAR_VALUE for invalid code point. ex. /[\x{7fffffff}]/ for ASCII encoding. 2007/08/28: [impl] remove "warning: no previous declaration ...". 2007/08/21: [impl] remove warnings in enc/mktable.c. 2007/08/20: [impl] remove "warning: unused parameter" 2007/08/20: [impl] remove "warning: comparison between signed and unsigned". 2007/08/06: [impl] remove clear_not_flag_cclass(). 2007/08/03: [bug] fix the case of undefined USE_NAMED_GROUP. 2007/08/02: [spec] add backref by number. 2007/08/01: [API] add OnigCtype. 2007/07/27: [spec] add USE_CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS. 2007/07/24: [impl] define PLATFORM_UNALIGNED_WORD_ACCESS. 2007/07/23: [dist] fix doc/FAQ.ja. 2007/07/14: Version 5.9.0 2007/07/13: [bug] add check into onig_reduce_nested_quantifier(). 2007/06/26: [spec] (thanks K.Takata) ONIG_OPTION_SINGLELINE: '$' -> '\Z' (as Perl) 2007/06/26: [dist] (thanks K.Takata) fix documents API and API.ja. 2007/06/19: [impl] remove IS_NOT_NULL() check before onig_node_free(). 2007/06/18: [bug] (thanks KUBO Takehiro) WORD_ALIGNMENT_SIZE must be sizeof(OnigCodePoint). 2007/06/18: [impl] rename CClassNode flags. 2007/06/18: [bug] initialization miss. 2007/06/13: [impl] change node type reference NXXXX. 2007/06/11: [impl] add node type bit. 2007/06/11: [spec] allow anchor in enclosed repeater. /(\z)*/ 2007/06/11: [impl] rename node types. 2007/06/08: [impl] remove OP_SET_OPTION_PUSH and OP_SET_OPTION from match_at(). 2007/06/07: [impl] use xvsnprintf(). 2007/06/06: [tune] don't set qn->next_head_exact for string first byte is zero. 2007/06/06: [impl] remove unused variables. 2007/06/04: Version 5.8.0 2007/06/04: [impl] add #ifndef vsnprintf into regint.h. 2007/05/31: [dist] add configure option '--enable-crnl-as-line-terminator'. 2007/05/30: [dist] add sample/crnl.c. 2007/05/30: [bug] should check USE_CRNL_AS_LINE_TERMINATOR case in onig_search(). 2007/05/29: [impl] move USE_CRNL_AS_LINE_TERMINATOR into regenc.h. 2007/05/29: [impl] should check USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE in forward_search_range() and backward_search_range(). 2007/04/27: Version 5.7.0 2007/04/20: [spec] add config USE_MATCH_RANGE_IS_COMPLETE_RANGE. 2007/04/20: [impl] refactoring in match_at(). 2007/04/12: Version 5.6.1 2007/04/12: [bug] must not use UChar in oniguruma.h. 2007/04/09: [impl] change STATE_CHECK_BUFF_MAX_SIZE value from 0x8000 to 0x4000. [ruby-core:10883] 2007/04/04: Version 5.6.0 (mourning for Hideo Takamatsu) 2007/04/03: [spec] add new notation (?'name'), \k'name', \g'name'. 2007/04/03: [impl] remove unused variable. 2007/03/26: [impl] add 'void' to function declarations. 2007/03/06: Version 5.5.3 2007/03/06: [bug] add #include for bcc32. (In bcc32, alloca() is declared in malloc.h.) 2007/03/02: [bug] invalid optimization for semi-end-buf in onig_search(). ex. /\n\Z/.match("aaaaaaaaaa\n") 2007/03/02: [impl] move range > start check position in end_buf process. 2007/01/09: Version 5.5.2 2007/01/09: [impl] rename USE_EXTERNAL_LOWER_CASE_CONV_TABLE. 2007/01/05: [tune] select_opt_exact_info() didn't work for empty info. ex. /.a/ make MAP info instead of EXACT info. 2006/12/28: [impl] add print_enc_string() for ONIG_DEBUG mode. 2006/12/22: Version 5.5.1 2006/12/22: [impl] rename ADD_PAD_TO_SHORT_BYTE_STRING . to USE_PAD_TO_SHORT_BYTE_CHAR. 2006/12/21: [spec] should check too short multibyte char in parse_exp(). add ADD_PAD_TO_SHORT_BYTE_STRING. ex. /\x00/ in UTF16 should be error. 2006/12/06: Version 5.5.0 2006/12/05: [bug] should add unfold-1 codes from folded code into onigenc_unicode_get_case_fold_codes_by_str(). (ex. "S" -> "s" -> 0x017f) 2006/12/05: [new] add flag ONIGENC_CASE_FOLD_TURKISH_AZERI and USE_UNICODE_CASE_FOLD_TURKISH_AZERI. (disabled in default) 2006/12/04: [spec] remove ONIGENC_CASE_FOLD_FULL. 2006/11/30: [impl] remove unnecessary check in xxx_mbc_case_fold(). 2006/11/29: Version 5.4.0 2006/11/28: [spec] INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR is enabled in default case fold status. 2006/11/28: [spec] rename ONIGENC_CASE_FOLD_MULTI_CHAR to INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR. 2006/11/28: [impl] remove USE_UNICODE_CASE_FOLD_MULTI_CHAR. 2006/11/28: [impl] remove Fold[123]Table and add FoldTable. 2006/11/27: [impl] change tool/unicode_fc.rb to see CaseFolding.txt. 2006/11/24: [bug] should call callback for to[j] <-> to[k] in onigenc_unicode_apply_all_case_fold(). 2006/11/22: Version 5.3.0 2006/11/22: [dist] add index_ja.html. 2006/11/22: [impl] undef ONIG_ESCAPE_UCHAR_COLLISION in regint.h and regenc.h. 2006/11/21: [bug] invalid array access. 2006/11/21: [impl] escape UChar collision from config.h. 2006/11/20: [new] add Hiragana/Katakana properties into Shift_JIS. 2006/11/20: [impl] fix CR_Katakana[] values in EUC-JP. 2006/11/17: [impl] declare strend hash table functions in regint.h. 2006/11/17: [impl] move property list functions to regenc.c. 2006/11/17: [new] add Hiragana/Katakana properties into EUC-JP. 2006/11/15: [impl] remove NOT_RUBY from AM_CFLAGS. 2006/11/14: Version 5.2.0 2006/11/14: [impl] remove program codes for Ruby. 2006/11/14: [impl] reduce program codes for Ruby. 2006/11/10: [bug] 0x24, 0x2b, 0x3c, 0x3d, 0x3e, 0x5e, 0x60, 0x7c, 0x7e should be [:punct:]. 2006/11/09: [new] (thanks Byte) add new character encoding CP1251. 2006/11/08: [impl] rename QUALIFIER -> QUANTIFIER. 2006/11/07: Version 5.1.0 2006/11/07: [dist] remove test.rb, testconv.rb and testconvu.rb. 2006/11/07: [bug] get_case_fold_codes_by_str() should handle 'Ss' and 'sS' combination for ess-tsett. 2006/11/07: [impl] apply_all_case_fold() doesn't need to return all case character combination for multi-character folding. (ONIGENC_CASE_FOLD_MULTI_CHAR) 2006/11/07: [bug] (thanks Byte) add { 0xa3, 0xb3 } to CaseFoldMap[] for KOI8-R. 2006/11/06: [spec] change ONIG_OPTION_FIND_LONGEST to search all of the string range. add USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE. 2006/11/02: [impl] re-implement expand_case_fold_string() for ONIGENC_CASE_FOLD_MULTI_CHAR. 2006/10/30: [impl] add NSTR_DONT_GET_OPTINFO flag. 2006/10/30: [impl] (thanks K.Takata) add THREAD_SYSTEM_INIT and THREAD_SYSTEM_END. 2006/10/30: [bug] (thanks Wolfgang Nadasi-Donner) invalid offset value was used in STATE_CHECK_BUFF_INIT(). 2006/10/27: [tune] speed up ONIGENC_MBC_CASE_FOLD() for UTF-16, UTF-32. (ASCII code check) 2006/10/27: [tune] (thanks Kornelius Kalnbach) String#scan for long string needs long time compare with old Ruby by initialization time for combination explosion check ex. ("test " * 100_000).scan(/\w*\s?/) change STATE_CHECK_BUFF_MAX_SIZE from 0x8000000 to 0x8000. reduce initialization area of state_check_buff. 2006/10/25: [impl] add DISABLE_CASE_FOLD_MULTI_CHAR(). 2006/10/23: Version 5.0.1 2006/10/23: [bug] should fold string in expand_case_fold_string(). 2006/10/23: [bug] (thanks Km) too many case fold/unfold expansion problem. don't expand and set ambig flag to the string node. (except ONIGENC_CASE_FOLD_MULTI_CHAR). 2006/10/23: [bug] (thanks K.Takata) invalid \p{Alnum}, \p{ASCII}, [:alnum:], [:ascii:]. fix OnigEncAsciiCtypeTable[] etc... 2006/10/23: [spec] (thanks K.Takata) add [:word:] POSIX bracket. 2006/10/23: [bug] (thanks K.Takata) \p{Word} doesn't work. 2006/10/20: [impl] don't expand for AMBIG_FLAG string in expand_case_fold_string(). 2006/10/19: Version 5.0.0 2006/10/18: [bug] ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM should be 13. 2006/10/18: [impl] remove unused functions. 2006/10/18: [dist] update documents. 2006/10/18: [API] move OnigMetaCharTableType to OnigSyntaxType. 2006/10/18: [dev] add too/unicode_fc.rb, unicode_pc.rb. 2006/10/18: [dist] remove MANIFEST-RUBY from distribution. 2006/10/18: [bug] return duplicated code in onigenc_unicode_get_case_fold_codes_by_str(). 2006/10/18 [API] remove ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS. 2006/10/18: [dev] add tool/19. 2006/10/18: [dist] remove target 19 from Makefile.am. 2006/10/17: [dist] add enc/unicode.c to target 19 of win32/Makefile. 2006/10/17: [impl] change type for escape VC++ warning. 2006/10/17: [API] rename ONIGENC_CASE_FOLD_NONE to ONIGENC_CASE_FOLD_MIN. 2006/10/17: [dist] remove INSTALL-RUBY from distribution. 2006/10/17: [dist] update LTVERSION to "2:0:0". 2006/10/17: [impl] remove warnings for [make CFLAGS="-g -O2 -Wall"] in the case USE_UNICODE_PROPERTIES and USE_UNICODE_CASE_FOLD_MULTI_CHAR are undefined. 2006/10/17: [impl] remove warnings for [make CFLAGS="-g -O2 -Wall"]. 2006/10/17: [impl] re-implement onigenc_unicode_apply_all_case_fold(). multi-char by case folded char-class is treated as caseless-string (ambig flag on). enable OP_EXACT1_IC and OP_EXACTN_IC. 2006/10/16: [bug] unfold expand for 1->2, 1->3 folding in onigenc_unicode_apply_all_case_fold(). add CaseFoldExpand_12[], CaseFoldExpand_13[]. 2006/10/16: [bug] (thanks Akinori Musha) first argument of rb_warn() should be format string. 2006/10/16: [impl] add msa.state_check_buff_size initialization in onig_search(). 2006/10/16: [spec] re-implement Unicode Caseless Match codes. 2006/10/10: [bug] should call onig_st_free_table() in onig_free_shared_cclass_table(). 2006/10/10: [impl] remove OnigCompCaseFoldCodes. 2006/10/10: [impl] remove onigenc_ascii_is_mbc_ambiguous() and onigenc_mbn_is_mbc_ambiguous(). 2006/10/10: [API] remove is_mbc_ambiguous() member from OnigEncodingType. 2006/10/10: [API] rename onig_set_default_ambig_flag() to onig_set_default_case_fold_flag(), onig_get_default_ambig_flag() to onig_get_default_case_fold_flag(), onig_get_ambig_flag() to onig_get_case_fold_flag(). 2006/10/10: [API] rename ambig_flag to case_fold_flag. 2006/10/10: [API] rename OnigAmbigType to OnigCaseFoldType. 2006/10/10: [impl] rename ONIGENC_IS_CODE_SB_WORD() to IS_CODE_SB_WORD() and move to regint.h. 2006/10/10: [impl] remove OP_WORD_SB and OP_WORD_MB. 2006/10/10: [impl] remove OP_EXACT1_IC and OP_EXACTN_IC from match_at(). 2006/10/10: [impl] should free new_str in expand_case_fold_string(). 2006/10/06: [dist] add test entries to sample/encode.c. 2006/10/06: [impl] re-implement caseless match (case-fold). 2006/10/06: [impl] expand string node by case fold variations. add expand_case_fold_string(). 2006/10/05: [spec] rename OnigCompAmbigCodeItem to OnigCaseFoldCodeItem. 2006/10/05: [spec] add apply_all_case_fold() and get_case_fold_codes_by_str() to OnigEncodingType. 2006/10/05: [spec] remove ambig_flag, get_all_pair_ambig_codes() and get_all_comp_ambig_codes() member from OnigEncodingType. 2006/10/03: [impl] rename mbc_to_normalize() to mbc_case_fold(). 2006/10/03: [spec] rename ONIGENC_AMBIGUOUS_MATCH_XXX to ONIGENC_CASE_FOLD_XXX. rename ONIGENC_CASE_FOLD_COMPOUND to ONIGENC_CASE_FOLD_MULTI_CHAR. 2006/10/02: [impl] remove all ONIG_RUBY_M17N part. 2006/09/29: [impl] initialize state_check_buff_size in STATE_CHECK_BUFF_INIT(). make valgrind happy. 2006/09/22: [impl] remove parse time ctype values (CTYPE_WORD etc...) 2006/09/22: [ruby] enable USE_BACKREF_AT_LEVEL for Ruby mode. 2006/09/22: [spec] (thanks Allan Odgaard) allow upper case letter as the first character of group name. fetch_name() and fetch_name_with_level() 2006/09/21: [impl] convert to ascii for parameter string in onig_error_code_to_str(). add enc member into OnigErrorInfo. 2006/09/21: [dist] update documents for Unicode Property. 2006/09/21: [new] add Unicode Properties. (enc/unicode.c) Any, Assigned, C, Cc, L, Lm, Arabic, Greek etc... 2006/09/21: [impl] add USE_UNICODE_PROPERTIES into regenc.h. 2006/09/21: [impl] remove USE_UNICODE_FULL_RANGE_CTYPE. 2006/09/20: [impl] change ONIGENC_CTYPE_XXXX to sequencial values. add BIT_CTYPE_XXXX bit flags to regenc.h. update XXXX_CtypeTable[] for BIT_CTYPE_ALNUM. 2006/09/19: [memo] move from CVS to Subversion (1.3.2). 2006/09/19: [impl] (thanks KOYAMA Tetsuji) HAVE_STDARG_PROTOTYPES was not defined in Mac OS X by Xcode 2.4(gcc 4.0.1) problem. [php-dev 1312] etc... 2006/09/15: [bug] (thanks Allan Odgaard) out of range access in bm_search_notrev(). (p < s) 2006/09/13: [impl] add ONIGENC_CTYPE_ENC_EXT flag. 2006/09/13: [spec] remove 'Is' prefix check for property name from fetch_char_property_to_ctype(). 2006/09/13: [API] add property_name_to_ctype member to OnigEncodingType. 2006/09/12: [spec][ruby] add ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY and ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT to OnigSyntaxRuby. 2006/09/08: Version 4.4.2 2006/09/08: [test] success in ruby 1.9.0 (2006-08-22) [i686-linux]. 2006/09/08: [bug] (thanks K.Takata) out of range access in bm_search_notrev(). 2006/09/04: [spec] (thanks K.Takata) allow look-behind in negative look-behind. ex. /(? (?:a*){n,n}, (?:a+){n,n} 2006/09/21: [impl] reduce (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} if backreference is not used. 2006/08/17: [bug] should check scan_env.num_call > 0 for backrefed pattern in combination explosion check. 2006/08/17: Version 4.3.0 2006/08/17: [test] success in ruby 1.9.0 (2006-07-28) [i686-linux]. 2006/08/17: [new] add config USE_COMBINATION_EXPLOSION_CHECK. check /(.+)*/, /(\s*foo\s*)*/ etc... [API] add num_comb_exp_check member in regex_t. [dist] change LTVERSION value to "1:0:0" in configure.in. 2006/08/15: [bug] OP_REPEAT_INC process in match_at(). should check repeat-count >= range-upper and range-upper may be infinite. 2006/08/11: Version 4.2.3 2006/08/11: [test] success in ruby 1.9.0 (2006-07-28) [i686-linux]. 2006/08/10: [impl] remove double call in set_qualifier(). 2006/08/10: [impl] remove by_number member in QualifierNode. 2006/08/09: [impl] remove a comma at the end of enum ReduceType for escape warning on Mac OS X. 2006/08/07: [impl] remove warning in regcomp.c. 2006/08/07: [spec] move definition of USE_BACKREF_AT_LEVEL into NOT_RUBY. 2006/08/03: Version 4.2.2 2006/08/03: [test] success in ruby 1.9.0 (2006-07-28) [i686-linux]. 2006/08/03: [bug] (thanks Hiroyuki Yamamoto) segmentation fault in regexec(). (POSIX API) 2006/08/02: [bug] combination of \G in look-ahead/look-behind and other anchors(\A, \z, \Z) cause invalid result. ex. /(?!\G)a\z/.match("ba") start arg. of MATCH_ARG_INIT() should be original arg. of onig_search(). 2006/07/31: Version 4.2.1 2006/07/31: [test] success in ruby 1.9.0 (2006-07-28) [i686-linux]. 2006/07/31: [bug] (thanks Kimura Minoru) re-implement bm_search_notrev(). 2006/07/31: [impl] bm_search_notrev() refactoring. 2006/07/31: [bug] (thanks Kimura Minoru) fix incomplete multibyte string in exact info. 2006/07/31: [impl] (thanks Seiji Masugata) remove cast in va_init_list() for Intel C Compiler. 2006/07/18: Version 4.2.0 2006/07/18: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/07/18: [new] (thanks Wolfgang Nadasi-Donner) add back reference with nest level. \k, \k 2006/07/11: [impl] change long to unsigned long for ONIG_OPTION_XXX and ONIG_SYN_XXX number literals. 2006/07/03: Version 4.1.2 2006/07/03: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/07/03: [spec] (thanks Wolfgang Nadasi-Donner) allow \G in look-behind. add ANCHOR_BEGIN_POSITION flag in setup_tree(). 2006/06/12: [impl] (thanks matz) fix cast from char* to const char* in onig_snprintf_with_pattern(). fix cast from char* to const char* for PopularQStr[] and ReduceQStr[]. 2006/05/22: Version 4.1.1 2006/05/22: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/05/22: [impl] add position string argument to STACK_BASE_CHECK(). 2006/05/22: [bug] (thanks NARUSE, Yui) add STK_NULL_CHECK_END to IS_TO_VOID_TARGET(). ex. core dump in /(?\(([^\(\)]++|\g)*+\))/.match('((a))') 2006/05/15: Version 4.1.0 2006/05/15: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/05/15: [impl] thread atomic changes for onig_end() and onig_free_node_list(). 2006/05/15: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2005/05/15: [dist] update API, API.ja, FAQ, FAQ.ja. 2006/05/15: [spec] remove onig_recompile(), onig_recompile_deluxe() and re_recompile_pattern(). add config USE_RECOMPILE_API. 2006/05/15: [impl] improved thread safe implementation of onig_search() and onig_match(). 2006/05/11: Version 4.0.4 2006/05/11: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/05/11: [bug] (thanks Yuji Kaneda) dead-lock in onig_end(). 2006/05/11: [dist] update index.html. 2006/05/08: Version 4.0.3 2006/05/08: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/05/08: [bug] (thanks Allan Odgaard) Segmentation fault in backward search. ex. /^\t.*$/ 2006/04/18: [dist] update index.html. 2006/04/05: [dist] update index.html. 2006/03/24: [dist] update doc/RE, doc/RE.ja. 2006/03/23: Version 4.0.2 2006/03/22: [test] success in ruby 1.9.0 (2006-03-01) [i686-linux]. 2006/03/22: [impl] add both of ONIG_OPTION_DONT_CAPTURE_GROUP and ONIG_OPTION_CAPTURE_GROUP check. 2006/03/22: [spec] add error code ONIGERR_INVALID_COMBINATION_OF_OPTIONS. 2006/03/22: [impl] remove USE_NAMED_GROUP condition from ONIG_OPTION_DONT_CAPTURE_GROUP check in parse_effect(). 2006/03/22: [new] add API onig_noname_group_capture_is_active(). 2006/03/01: [spec] rename regex object type from regex_t to OnigRegexType. add typedef OnigRegexType regex_t unless ONIG_ESCAPE_REGEX_T_COLLISION is defined. 2006/02/27: [spec] change ONIG_MAX_MULTI_BYTE_RANGES_NUM from 1000 to 10000. (for docdiff program) 2006/02/17: [dist] change COPYING year 2005 -> 2006. 2006/02/07: Version 4.0.1 2006/02/07: [test] success in ruby 1.9.0 (2005-11-28) [i686-linux]. 2006/02/07: [bug] memory leaks in onig_free_shared_cclass_table(). 2006/02/03: [ruby] add -m 0644 option to install command in "make 19". 2006/02/03: [impl] rename ANCHOR_ANYCHAR_STAR_PL to ANCHOR_ANYCHAR_STAR_ML. change from IS_POSIXLINE() to IS_MULTILINE() for ANCHOR_ANYCHAR_START/_ML decision in optimize_node_left(). 2006/01/26: [dist] update index.html for Oniguruma 2.5.3. 2006/01/25: [dist] update URL in index.html. 2006/01/24: Version 4.0.0 2006/01/24: [test] success in ruby 1.9.0 (2005-11-28) [i386-cygwin]. 2006/01/24: [test] success in ruby 1.9.0 (2005-11-28) [i686-linux]. 2006/01/24: [dist] remove warnings from sample/encode.c. 2006/01/24: [dist] change install description in README(.ja). 2006/01/24: [dist] remove re.c.XXX.patch from distribution and CVS. 2006/01/24: [dist] --- support shared library --- use GNU libtool/automake. change configure.in and add Makefile.am, sample/Makefile.am. add AUTHORS file. 2006/01/24: [dist] test programs return exit code -1 when test fails. 2006/01/24: [bug] (thanks KIMURA Koichi) invalid syntax definition in ONIG_SYNTAX_GREP. ONIG_SYN_OP_BRACE_INTERVAL -> ONIG_SYN_OP_ESC_BRACE_INTERVAL 2006/01/23: [dist] fix configure.in for onig-config. 2006/01/19: [new] add new config USE_UNICODE_ALL_LINE_TERMINATORS. (U+000d, U+0085, U+2028, U+2029) 2005/12/29: [dist] change pmatch array size to 25 in testconv.rb. 2005/12/26: [dist] fix name in test.rb. 2005/12/26: [dist] update index.html for 2.5.1. 2005/11/29: Version 3.9.1 2005/11/29: [test] success in ruby 1.9.0 (2005-11-28) [i686-linux]. 2005/11/24: [test] success in ruby 1.9.0 (2005-08-09) [i686-linux]. 2005/11/21: [test] success in ruby 1.9.0 (2005-11-20) [i386-cygwin]. 2005/11/21: [bug] (thanks Allan Odgaard) utf-8 character comments in extended mode leads invalid result. ex. /(?x)(?<= # o\n~) / fix onigenc_unicode_is_code_ctype() and utf8_is_code_ctype(). 2005/11/20: [bug] (thanks MATSUMOTO Satoshi) (thanks Isao Sonobe) begin-line anchor and BM search optimization leads invalid result in UTF-16/32. fix in set_optimize_exact_info(). 2005/11/20: Version 3.9.0 2005/11/20: [test] success in ruby 1.9.0 (2005-11-20) [i386-cygwin]. 2005/11/20: [test] success in ruby 1.9.0 (2005-10-18) [i386-cygwin]. 2005/11/20: [new] add new config USE_CRNL_AS_LINE_TERMINATOR. (!!! NO SUPPORT experimental option !!!) 2005/11/15: [bug] (thanks Allan Odgaard) tok->escape was not cleared in fetch_token_in_cc(). ex. [\s&&[^\n]] makes wrong result. 2005/10/18: [impl] (thanks nobu) change sjis_mbc_enc_len() and node_new_cclass_by_codepoint_range() scope to static. 2005/09/05: [dist] remove link to MultiFind. 2005/09/01: [dist] add link to yagrep. 2005/08/23: Version 3.8.9 2005/08/23: [test] success in ruby 1.9.0 (2005-08-09) [i686-linux]. 2005/08/23: [inst] fix Makefile.in for make ctest/ptest. 2005/08/23: Version 3.8.8 2005/08/23: [test] success in ruby 1.9.0 (2005-08-09) [i686-linux]. 2005/08/23: [impl] split is_code_in_cc() from onig_is_code_in_cc(). 2005/08/23: [impl] should check DATA_ENSURE() at OP_CCLASS_NODE in match_at(). 2005/08/23: [impl] (thanks akr) add ONIG_OPTION_MAXBIT for escape conflict with Ruby's option. 2005/08/22: [impl] escape GCC 4.0 warnings for testc.c. 2005/08/22: [bug] (thanks nobu, matz) [ruby-dev:26840] UTF-8 0xFE, 0xFF handling bug in code_is_in_cclass_node(). abort on /\S*/ =~ "\xfe" 2005/08/22: [impl] escape GCC 4.0 warnings for sample/*.c. 2005/08/22: [impl] fix testconvu.rb. 2005/08/22: [impl] escape GCC 4.0 warnings. 2005/08/09: Version 3.8.7 2005/08/09: [test] success in ruby 1.9.0 (2005-08-09) [i686-linux]. 2005/08/09: [bug] (thanks Allan Odgaard) should not call enc_len() for s == range in onig_search(). 2005/08/01: [dist] add mkdir $prefix, mkdir $exec_prefix to make install. 2005/07/27: Version 3.8.6 2005/07/27: [test] success in ruby 1.9.0 (2005-07-26) [i686-linux]. 2005/07/27: [impl] update onig-config.in. 2005/07/26: [new] (thanks Yen-Ju Chen) add Oniguruma configuration check program. (onig-config.in) 2005/07/14: Version 3.8.5 2005/07/14: [test] success in ruby 1.9.0 (2005-07-14) [i686-linux]. 2005/07/11: [test] success in ruby 1.9.0 (2005-07-04) [i686-linux]. 2005/07/11: [bug] (thanks nobu) [ruby-dev:26505] invalid handling for /\c\x/ and /\C-\x/. fix fetch_escaped_value(). 2005/07/05: [impl] (thanks Alexey Zakhlestine) escape GCC 4.0 warnings. 2005/07/01: Version 3.8.4 2005/07/01: [test] success in ruby 1.9.0 (2005-07-01) [i686-linux]. 2005/06/30: [test] success in ruby 1.9.0 (2005-06-28) [i686-linux]. 2005/06/30: [dist] add GB 18030 test to sample/encode.c. 2005/06/30: [impl] escape warning of gb18030_left_adjust_char_head(). 2005/06/30: [new] (contributed by KUBO Takehiro) add new character encoding ONIG_ENCODING_GB18030. 2005/06/30: [bug] invalid ctype check for multibyte encodings. ("graph", "print") fix onigenc_mb2/4_is_code_ctype(), eucjp_is_code_ctype() and sjis_is_code_ctype(). 2005/06/30: [bug] invalid conversion from code point to mbc in onigenc_mb4_code_to_mbc(). 2005/06/28: Version 3.8.3 2005/06/28: [test] success in ruby 1.9.0 (2005-06-28) [i686-linux]. 2005/06/27: [test] success in ruby 1.9.0 (2005-05-31) [i686-linux]. 2005/06/27: [bug] (thanks Wolfgang Nadasi-Donner) invalid check for never ending recursion. lower zero quantifier should be treated as a non-recursive call alternative. ex. /(?[^()]*(\(\g\)[^()]*)*)/ 2005/06/15: [impl] add divide_ambig_string_node_sub(). 2005/06/15: [dist] add a test to sample/encode.c. 2005/06/10: [new] add ONIG_SYNTAX_PERL_NG. (Perl + named group) 2005/06/01: Version 3.8.2 2005/06/01: [test] success in ruby 1.9.0 (2005-05-31) [i686-linux]. 2005/05/31: [dist] add doc/FAQ and doc/FAQ.ja. 2005/05/31: [impl] minor change in node_new(). 2005/05/30: [test] success in ruby 1.9.0 (2005-05-11) [i686-linux]. 2005/05/30: [bug] (thanks Allan Odgaard) FreeNodeList null check should be on thread-atomic in node_new(). 2005/05/11: Version 3.8.1 2005/05/11: [test] success in ruby 1.9.0 (2005-05-11) [i386-mswin32]. 2005/05/11: [dist] update win32/Makefile (make 19). 2005/05/11: [test] success in ruby 1.9.0 (2005-05-11) [i686-linux]. 2005/05/06: [test] success in ruby 1.9.0 (2005-05-06) [i686-linux]. 2005/05/06: [impl] (thanks nobu) [ruby-core:4815] add #ifdef USE_VARIABLE_META_CHARS to goto label. 2005/04/25: [test] success in ruby 1.9.0 (2005-04-25) [i686-linux]. 2005/04/25: [impl] change DEFAULT_WARN_FUNCTION and DEFAULT_VERB_WARN_FUNCTION to onig_rb_warn() and onig_rb_warning(). 2005/04/15: Version 3.8.0 2005/04/15: [test] success in ruby 1.9.0 (2005-04-14) [i686-linux]. 2005/04/01: [test] success in ruby 1.9.0 (2005-03-24) [i686-linux]. 2005/04/01: [impl] (thanks Joe Orton) (thanks Moriyoshi Koizumi) many const-ification to many *.[ch] files. 2005/03/25: Version 3.7.2 2005/03/25: [test] success in ruby 1.9.0 (2005-03-24) [i686-linux]. 2005/03/23: [test] success in ruby 1.9.0 (2005-03-20) [i686-linux]. 2005/03/23: [test] success in ruby 1.9.0 (2005-03-08) [i686-linux]. 2005/03/23: [new] add ONIG_SYNTAX_ASIS. 2005/03/23: [new] add ONIG_SYN_OP2_INEFFECTIVE_ESCAPE. 2005/03/09: [spec] rename MBCTYPE_XXX to RE_MBCTYPE_XXX. (GNU API) 2005/03/08: [test] success in ruby 1.9.0 (2005-03-08) [i686-linux]. 2005/03/08: [impl] (thanks matz) [ruby-dev:25783] should not allocate memory for key data in st.c. move st_*_strend() functions from st.c. fixed some potential memory leaks. (imported from Ruby 1.9 2005-03-08) 2005/03/07: Version 3.7.1 2005/03/07: [test] success in ruby 1.9.0 (2005-03-07) [i686-linux]. 2005/03/07: [impl] (thanks Rui Hirokawa) add ONIG_ESCAPE_UCHAR_COLLISION. rename UChar to OnigUChar in oniguruma.h. 2005/03/07: [impl] remove declarations for Ruby in oniggnu.h. 2005/03/05: [bug] ANCHOR_ANYCHAR_STAR didn't work in onig_search(). 2005/03/01: [dist] remove oniggnu.h from MANIFEST-RUBY. remove oniggnu.h from make 19. 2005/03/01: [bug] (thanks matz) [ruby-dev:25778] uninitialized member (OptEnv.backrefed_status) was used. 2005/02/19: Version 3.7.0 2005/02/19: [test] success in ruby 1.9.0 (2005-02-19) [i386-cygwin]. 2005/02/19: [new] (thanks Minero Aoki) add onig_region_set(). 2005/02/19: [API] change onig_region_init() to extern. 2005/02/19: [dist] remove reggnu.c from MANIFEST-RUBY. remove reggnu.c from make 19. 2005/02/19: [dist] update doc/API and doc/API.ja. 2005/02/19: [test] success in ruby 1.9.0 (2005-02-19) [i386-cygwin]. 2005/02/19: [impl] (thanks Alexey Zakhlestine) change UChar* to const UChar* in oniguruma.h, regenc.h and regparse.h. 2005/02/13: [impl] change UChar* to const UChar* in oniguruma.h and onigposix.h and st.h. 2005/02/12: [test] success in ruby 1.9.0 (2005-02-11) [i386-cygwin]. 2005/02/12: [bug] (thanks nobu) [ruby-dev:25676] type_cclass_hash() fix overrun. 2005/02/09: [test] success in ruby 1.9.0 (2005-02-09) [i686-linux]. 2005/02/09: [spec] add RE_OPTION_FIND_NOT_EMPTY etc.. to oniggnu.h. 2005/02/09: [dist] remove hash.c.patch. 2005/02/07: [impl] remove re_mbctab, mbctab_ascii etc... (USE_COMPATIBILITY_FOR_RUBY_EXTENSION_LIBRARY) 2005/02/04: Version 3.6.0 2005/02/04: [test] success in ruby 1.9.0 (2005-02-04) [i686-linux]. 2005/02/01: [bug] add key_free() call to st_free_table(). 2005/02/01: [new] add onig_get_default_ambig_flag() and onig_set_default_ambig_flag(). 2005/02/01: [dist] update MANIFEST-RUBY. 2005/01/31: [test] success in ruby 1.9.0 (2005-01-29) [i686-linux]. 2005/01/31: [spec] remove ONIGENC_AMBIGUOUS_MATCH_COMPOUND from ONIGENC_AMBIGUOUS_MATCH_DEFAULT. 2005/01/31: [dist] update Makefile.in (make 19). 2005/01/29: [memo] (thanks Kazuo Saito) Oniguruma 3.5.4 was merged to Ruby 1.9.0. 2005/01/28: [impl] (thanks UK-taniyama) add extern "C" { } directive to oniguruma.h, oniggnu.h and onigposix.h for C++. 2005/01/25: [impl] remove nested function call for xxx_code_to_mbclen(). (euc_kr.c, euc_tw.c, big5.c) 2005/01/19: Version 3.5.4 2005/01/19: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. 2005/01/19: [bug] (thanks Isao Sonobe) callback function argument name_end of onig_foreach_name() was wrong. name key of name table should be null terminated for character encoding length. add strdup_with_null(), rename onig_strdup() to k_strdup(). use e->name_len in i_names(). 2005/01/17: [impl] (thanks UK-taniyama) add HAVE_SYS_TYPES_H to config.h.in. 2005/01/13: Version 3.5.3 2005/01/13: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. 2005/01/13: [bug] ignore case match bug. ex. /s+/iu.match("SSSSS") ==> [4..5] fix OP_EXACT1_IC, OP_EXACTN_IC process. 2005/01/13: [bug] (thanks Isao Sonobe) ignore case match bug. ex. /is/iu.match("ss") fail. fix str_lower_case_match() etc. 2005/01/05: Version 3.5.2 2005/01/05: [test] success in ruby 1.9.0 (2005-01-05) [i686-linux]. 2005/01/05: [test] success in ruby 1.9.0 (2004-12-16) [i686-linux]. 2005/01/05: [bug] (thanks Isao Sonobe) ignore case match bug. ex. /s+/iu.match("sssss") ==> [4..5] fix OP_EXACT1_IC, OP_EXACTN_IC process. 2005/01/05: [bug] (thanks Isao Sonobe) group name table should be renumbered. add onig_renumber_name_table(). 2004/12/24: [dist] remove file onigcmpt200.h. 2004/12/17: Version 3.5.1 2004/12/17: [dist] add INSTALL-RUBY to archive. 2004/12/16: [test] success in ruby 1.9.0 (2004-12-16) [i686-linux]. 2004/12/16: [dist] update hash.c.patch. 2004/12/15: [bug] (thanks matz) char > 127 should be casted to unsigned char. (utf8.c) 2004/12/13: [impl] add HAVE_PROTOTYPES and HAVE_STDARG_PROTOTYPES definition to oniguruma.h in the case __cplusplus. 2004/12/06: [dist] update doc/RE and doc/RE.ja. 2004/12/03: [impl] (thanks nobu) st.h fix prototype for C++. 2004/12/03: Version 3.5.0 2004/12/02: [test] success in ruby 1.9.0 (2004-12-02) [i686-linux]. 2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i386-mswin32]. 2004/12/01: [dist] add make targets 19 and 19up to win32/Makefile. 2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i386-cygwin]. 2004/12/01: [test] success in ruby 1.9.0 (2004-12-01) [i686-linux]. 2004/12/01: [impl] double cast for escape warning in Cygwin. (HashDataType* )((void* )(&e)) in regparse.c 2004/12/01: [test] success in ruby 1.9.0 (2004-11-30) [i686-linux]. 2004/12/01: [tune] change implementation of clear_opt_map_info(). (which was 10-16% cost in gprof result for my test program) 2004/12/01: [dist] remove regex.c from distribution files. 2004/11/30: [memo] remove targets 16 and 18 from Makefile.in. 2004/11/30: [test] success in ruby 1.9.0 (2004-11-30) [i686-linux]. 2004/11/30: [inst] add "cp -p st.[ch] st.[ch].ruby_orig" to "make 19". 2004/11/30: [tune] map_position_value() return 20 if code is 0 and minimum enclen > 1. 2004/11/30: [test] success in ruby 1.9.0 (2004-11-29) [i686-linux]. 2004/11/30: [impl] minor changes for multi-thread in regexec.c and regcomp.c. 2004/11/30: [impl] change THREAD_PASS_LIMIT_COUNT value from 10 to 8. 2004/11/30: [impl] add THREAD_ATOMIC_XXX to FreeNodeList access in regparse.c 2004/11/29: [impl] add USE_MULTI_THREAD_SYSTEM. 2004/11/29: [memo] add hash.c.patch to CVS. 2004/11/29: [dist] change mail address to 'sndgk393 AT ...' 2004/11/29: [dist] add -s option (silent mode) to test.rb. 2004/11/29: [tune] change THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS value from 20 to 8. 2004/11/29: [inst] add make target "19up". 2004/11/29: [dist] change Oniguruma Home Page URL. 2004/11/29: [impl] remove onig_is_in_code_range_array(). 2004/11/29: [dist] fix doc/RE and RE.ja (character types). 2004/11/26: [dist] fix win32/Makefile. 2004/11/26: [dist] fix doc/RE and RE.ja (multibyte character types). 2004/11/26: [impl] add onig_free_shared_cclass_table(). 2004/11/26: [impl] move definition USE_UNICODE_FULL_RANGE_CTYPE to regenc.h. 2004/11/26: [impl] add opcode OP_CCLASS_NODE. 2004/11/26: [impl] move definition of CClassNode to regint.h. 2004/11/26: [impl] add type PointerType in regint.h. 2004/11/25: [impl] remove ONIGENC_CTYPE_MOD_NOT. 2004/11/25: [impl] rename onig_node_new_cclass_by_codepoint_range to node_new_cclass_by_codepoint_range. 2004/11/25: [impl] remove get_type_cc_node method from OnigEncodingType. 2004/11/25: [impl] move implementation of shared char-class from enc/*.c to regparse.c. 2004/11/25: [dist] add hash.c.patch for Ruby 1.9 hash.c change. 2004/11/22: [impl] change utf8_get_type_node(). 2004/11/22: [impl] add ONIGENC_CTYPE_MOD_NOT. 2004/11/22: [bug] (thanks MIYAMUKO Katsuyuki) ruby make test fail in HP-UX B.11.23 ia64. should use tok->u.code instead of tok->u.c in the case of TK_CODE_POINT. 2004/11/19: [bug] (thanks Yoshida Masato) invalid multibyte code causes segmentation fault. ex. /[\xFF-\xFF]/u 2004/11/19: [bug] (thanks Yoshida Masato) illegal check in char-class range in UTF-8. ex. s = "[\xC2\xA0-\xC3\xBE]" p(Regexp.new(s, nil, "u") =~ "\xC3\xBE") 2004/11/18: [impl] add onig_node_new_cclass_by_codepoint_range(). 2004/11/18: [impl] remove OnigCodePointRange type. (use OnigCodePoint[].) 2004/11/17: [bug] (thanks nobu) abort in "a".gsub(/a\Z/, "") fix ONIGENC_STEP_BACK() argument in onig_search(). 2004/11/16: [impl] add key2 member to st_table_entry in st.[ch]. change API of st for non-null terminated string key. 2004/11/16: [impl] add get_type_cc_node method to OnigEncodingType. 2004/11/15: [impl] add st.h and st.c from Ruby 1.9. use st-hash always. 2004/11/12: [impl] change member 'not' of CClassNode to 'flags'. add flags FLAG_CCLASS_NOT and FLAG_CCLASS_SHARE. 2004/11/12: [impl] add onig_is_in_code_range_array() to enc/unicode.c. 2004/11/12: [impl] fix CRWord in enc/unicode.c and MBWord in enc/utf8.c. 2004/11/11: [bug] fix enc/utf8.c. size 0 array initializer was compile error in VC++. 2004/11/09: [inst] (thanks Hiroki YAGITA) change installed file mode to 0644. 2004/11/09: [bug] (thanks UK-taniyama) wrong definitions GET_RELADDR_INC(), GET_ABSADDR_INC() etc... (NOT PLATFORM_UNALIGNED_WORD_ACCESS) 2004/11/09: [impl] type cast in regexec() for remove compile time warning. (WIN32, regposix.c) 2004/11/08: [spec] fix Unicode character types. 0x00ad (soft hyphen) should be [:cntrl:] and [:space:] type. [0x0009..0x000d], 0x0085 should be [:print:] type. 0x00ad should not be [:punct:] type. 2004/11/08: [inst] fix Makefile.in. (for make ctest/ptest/testcu) 2004/11/06: [impl] (thanks Kazuo Saito) too many alternatives pattern causes core dump. change implementation of onig_node_free(). 2004/11/05: [spec] rename ONIGERR_END_PATTERN_AT_BACKSLASH to ONIGERR_END_PATTERN_AT_ESCAPE. 2004/11/05: [impl] (thanks matz) escape compile time warnings for x86-64 Linux. StackIndex type int -> long 2004/11/05: [memo] (thanks Kazuo Saito) Oniguruma 3.4.0 was merged to Ruby 1.9.0. 2004/10/30: Version 3.4.0 2004/10/30: [test] success in ruby 1.9.0 (2004-09-24) [i686-linux]. 2004/10/30: [new] add hexadecimal digit char type. (\h, \H) syntax: ONIG_SYN_OP2_ESC_H_XDIGIT 2004/10/30: [bug] (thanks Guy Decoux) reluctant infinite repeat bug. ex. /^[a-z]{2,}?$/.match("aaa") fail. fix OP_REPEAT_INC_NG process in match_at(). 2004/10/18: Version 3.3.1 2004/10/18: [test] success in ruby 1.9.0 (2004-09-24) [i686-linux]. 2004/10/18: [impl] (thanks Imai Yasumasa) enclose #include by #ifndef __BORLANDC__. 2004/10/18: [bug] (thanks Imai Yasumasa) memory access violation in select_opt_exact_info(). 2004/09/25: [dist] fix doc/API and doc/API.ja. 2004/09/25: [bug] fix OP_SEMI_END_BUF process in match_at() for the case USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE is not defined. 2004/09/17: Version 3.3.0 2004/09/17: [dist] add COPYING to program source files. 2004/09/17: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. 2004/09/17: [bug] (thanks Isao Sonobe) memory access violations in xxx_mbc_enc_len(), and xxx_mbc_to_normalize() and xxx_left_adjust_char_head(). add string range check in match_at() and onig_search(). 2004/09/08: [dist] change mail address format.(kosako AT sofnec ...) 2004/09/04: Version 3.2.9 2004/09/04: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. 2004/09/04: [bug] (thanks Bob Kerstetter and Richard Koch) search fail in ignore case mode. fix str_lower_case_match(). 2004/09/04: [inst] (thanks Isao Sonobe) clear sample directory in 'make clean'. 2004/09/04: [bug] fix ONIGENC_AMBIGUOUS_MATCH_COMPOUND/ASCII/NONASCII meanings in XXXXX_mbc_to_normalize() and XXXXX_is_mbc_ambiguous(). 2004/08/28: [bug] fix ONIGENC_AMBIGUOUS_MATCH_COMPOUND/ASCII/NONASCII meanings in iso_8859_XX_mbc_to_normalize() and iso_8859_XX_is_mbc_ambiguous(). 2004/08/24: Version 3.2.8 2004/08/24: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. 2004/08/24: [spec] add ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY. /a{n}?/ == /(?:a{n})?/ 2004/08/24: [dist] fix doc/RE and doc/RE.ja. 2004/08/24: [bug] (thanks starfish) memory leak in set_optimize_exact_info(). 2004/08/21: Version 3.2.7 2004/08/21: [test] success in ruby 1.8.2 (2004-07-28) [i686-linux]. (1.8.2 preview2) 2004/08/21: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. 2004/08/21: [bug] (thanks Isao Sonobe) (thanks kage) memory access violation in bm_search_notrev(). (forgotten to merge from 2.X) 2004/07/24: Version 3.2.6 2004/07/24: [test] success in ruby 1.9.0 (2004-07-23) [i686-linux]. 2004/07/24: [test] success in ruby 1.8.2 (2004-07-16) [i686-linux]. 2004/07/24: [bug] fix warnings for regexec.c. (gcc 2.91.66) 2004/07/24: [memo] change version control system from Subversion to CVS 1.11.17. 2004/07/20: [bug] (thanks Isao Sonobe) illegal result in negative character class in ignore case mode. fix pair-ambig-codes process in parse_exp(). ex. /[^a]/i.match("A") 2004/07/20: [bug] (thanks Isao Sonobe) undefined bytecode error happens in UTF-16BE etc.. compile_length_cclass_node() was not consistent with compile_cclass_node(). 2004/07/01: Version 3.2.5 2004/07/01: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. 2004/07/01: [new] add onig_get_syntax_{op,op2,behavior,options}. 2004/07/01: [bug] (thanks Isao Sonobe) invalid result in onig_capture_tree_traverse(). fix make_capture_history_tree(). 2004/06/29: Version 3.2.4 2004/06/29: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. 2004/06/29: [new] (thanks Isao Sonobe) add onig_number_of_captures(). 2004/06/25: Version 3.2.3 2004/06/25: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. 2004/06/25: [bug] (thanks Isao Sonobe) invalid result in onig_capture_tree_traverse(). fix make_capture_history_tree(). 2004/06/24: Version 3.2.2 2004/06/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/06/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/06/24: [test] success in ruby 1.8.2 (2004-06-23) [i686-linux]. 2004/06/24: [new] (thanks Isao Sonobe) add onig_number_of_capture_histories(). 2004/06/24: [bug] (thanks Isao Sonobe) invalid char position match in UTF-16 and UTF-32. add onigenc_always_false_is_allowed_reverse_match(). 2004/06/17: Version 3.2.1 2004/06/17: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/06/17: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/06/17: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. 2004/06/17: [impl] should not use OP_REPEAT for (...)? even if target size is long. 2004/06/17: [bug] (thanks nobu) [ruby-dev:23703] should use STACK_AT() instead of stkp in OP_REPEAT_INC. add IN_VAR_REPEAT flag in setup_tree(). 2004/06/16: [impl] change select_opt_exact_info() to use ByteValTable[]. 2004/06/16: [impl] change map_position_value() table values. 2004/06/14: [impl] (thanks John Carter) RelAddrType, AbsAddrType and LengthType change from short int to int type for the very long string match. 2004/06/14: [bug] (thanks Greg A. Woods) fix nmatch argument of regexec() is smaller than reg->num_mem + 1 case. (POSIX API) 2004/06/14: [spec] (thanks Greg A. Woods) set pmatch to NULL if nmatch is 0 in regexec(). (POSIX API) 2004/06/10: Version 3.2.0 2004/06/10: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/06/10: [test] success in ruby 1.9.0 (2004-05-27) [i386-mswin32]. 2004/06/10: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. 2004/06/10: [dist] add README.ja. 2004/06/10: [new] add onig_copy_encoding(). 2004/06/10: [API] add encoding argument to onig_set_meta_char(). add meta_char_table member to OnigEncodingType. 2004/06/08: [dist] add doc/API.ja. 2004/06/07: [API] add num_of_elements member to OnigCompileInfo. 2004/05/29: [memo] (thanks Kazuo Saito) Oniguruma 3.1.0 was merged to Ruby 1.9.0. 2004/05/26: [impl] rename NST_SIMPLE_REPEAT to NST_STOP_BT_SIMPLE_REPEAT. 2004/05/26: [impl] doesn't need to check that target's simple repeat-ness for EFFECT_MEMORY type node in setup_tree(). 2004/05/25: Version 3.1.0 2004/05/25: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/05/25: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/05/25: [test] success in ruby 1.9.0 (2004-05-23) [i686-linux]. 2004/05/25: [test] success in ruby 1.8.2 (2004-05-18) [i686-linux]. 2004/05/25: [bug] (thanks Masahiro Sakai) [ruby-dev:23560] ruby -ruri -ve 'URI::ABS_URI =~ "http://example.org/Andr\xC3\xA9"' nested STK_REPEAT type stack can't backtrack repeat_stk[]. add OP_REPEAT_INC_SG and OP_REPEAT_INC_NG_SG. 2004/05/25: [new] support UTF-32LE. (ONIG_ENCODING_UTF32_LE) 2004/05/25: [new] support UTF-32BE. (ONIG_ENCODING_UTF32_BE) 2004/05/24: [impl] divide enc/utf16.c to utf16_be.c and utf16_le.c. 2004/05/24: [impl] add enc/unicode.c. 2004/05/24: [API] change calling sequences of onig_new_deluxe() and onig_recompile_deluxe(). define OnigCompileInfo type. 2004/05/21: [impl] perform ensure process for rb_trap_exec() in match_at(). add onig_exec_trap() and CHECK_INTERRUPT_IN_MATCH_AT. 2004/05/21: [impl] add regex status check to onig_match(). 2004/05/21: [new] add onig_get_capture_tree() and onig_capture_tree_traverse(). 2004/05/20: [spec] (thanks Isao Sonobe) capture history return capture data tree. (see sample/listcap.c) 2004/05/19: [bug] (thanks Simon Strandgaard) Control-C does not work in matching process on Ruby. add calling of CHECK_INTERRUPT into match_at(). ex. /<(?:[^">]+|"[^"]*")+>/.match('') 2004/05/19: [bug] (thanks Simon Strandgaard) define virtual codepoint values for invalid encoding byte 0xfe and 0xff in UTF-8. ex. /\w+/u.match("%a\xffb\xfec%") ==> "a" 2004/05/19: [spec] (thanks Simon Strandgaard) too big backref number should be treated as a sequence of an octal char and number digits. ex. /b\3777\c/.match("b\3777\c") 2004/05/17: [spec] rename encoding names "UTF-16 BE" and "UTF-16 LE" to "UTF-16BE" and "UTF-16LE". 2004/05/17: [impl] move ismbchar() and mbclen() from oniguruma.h to oniggnu.h. 2004/05/17: [impl] rename onigenc_single_byte_is_allowed_reverse_match() to onigenc_always_true_is_allowed_reverse_match(). 2004/05/14: Version 3.0.0 2004/05/14: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/05/14: [test] success in ruby 1.9.0 (2004-05-14) [i686-linux]. 2004/05/14: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. (* need to edit parse.y: register int c; ---> int c; in yylex()) 2004/05/14: [impl] add regext.c. 2004/05/14: [spec] KOI8 is not included in library archive by default setup. 2004/05/14: [impl] implementation changes are completed for all encoding files. 2004/05/12: [impl] add divide_ambig_string_node(). ambiguous string is divided and normalized before optimization and compilation process. 2004/05/11: [dist] remove INSTALL-RUBY from distribution. 2004/04/28: [memo] (thanks Kazuo Saito) Oniguruma 2.2.8 was merged to Ruby 1.9.0. 2004/04/26: [spec] change value DEFAULT_MATCH_STACK_LIMIT_SIZE = 0 : unlimited 2004/04/26: [new] add onig_get_match_stack_limit_size() and onig_set_match_stack_limit_size(). 2004/04/26: [bug] add error check to re.c.181.patch and re.c.168.patch. 2004/04/23: [impl] remove ctype_support_level from OnigEncodingType. 2004/04/22: [spec] allow the range from single byte char to multibyte char in character class for implementation reason. ex. /[a-\xbb\xcc]/ in EUC-JP encoding. 2004/04/21: [impl] remove max_enc_len_by_first_byte() from OnigEncodingType. 2004/04/20: [new] add onig_copyright(). 2004/04/20: [impl] add regversion.c. 2004/04/15: [new] add onig_get_ambig_flag(). 2004/04/14: [bug] (thanks Isao Sonobe) undefined bytecode error happens if ONIG_OPTION_FIND_LONGEST is set. should finish matching process if find-condition is fail at OP_END in match_at(). 2004/04/12: [impl] add ambig_flag to regex_t. 2004/04/09: [impl] move onig_set_meta_char() to regsyntax.c. 2004/04/09: [bug] (thanks HIROSE Masaaki) fix onig_version(). 2004/04/08: [impl] add regsyntax.c. 2004/04/07: [new] support UTF-16 LE. (ONIG_ENCODING_UTF16_LE) 2004/04/05: [impl] add ONIGENC_CTYPE_NEWLINE. 2004/04/05: [memo] (thanks Kazuo Saito) Oniguruma 2.2.6 was merged to Ruby 1.9.0. 2004/04/02: [memo] Version 2.2.6 was released. 2004/03/26: [new] support UTF-16 BE. (ONIG_ENCODING_UTF16_BE) 2004/03/25: [spec] support non 8-bit encodings. 2004/03/16: [memo] 2.X branch for 8-bit encodings only. 2004/03/16: Version 2.2.5 2004/03/16: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/03/16: [test] success in ruby 1.9.0 (2004-02-24) [i686-linux]. 2004/03/16: [impl] add property name to error message of ONIGERR_INVALID_CHAR_PROPERTY_NAME. 2004/03/16: [spec] allow prefix 'Is' for \p{...} in ONIG_SYNTAX_PERL. add syntax op. ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS. 2004/03/15: [dist] add sample/syntax.c. 2004/03/15: [spec] support NOT op. in char property. \p{^...}, \P{^...}. add syntax op. ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT. 2004/03/15: [spec] rename ONIG_SYN_OP2_ESC_P_CHAR_PROPERTY to ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY. 2004/03/10: [impl] move ONIGERR_XXX from regenc.h to oniguruma.h, rename ONIGERR_XXX to ONIGENCERR_XXX in regenc.h. 2004/03/08: [impl] (thanks eban) replace defined(__CYGWIN__) to defined(__GNUC__). 2004/03/08: [bug] (thanks eban) [ruby-dev:23172] need to separate initialization for bcc32. 2004/03/06: [memo] (thanks Kazuo Saito) Oniguruma 2.2.4 was merged to Ruby 1.9.0. 2004/03/05: [API] change second argument type of onig_set_meta_char() from unsigned int to OnigCodePoint. 2004/03/05: [dist] (thanks Kazuo Saito) add MANIFEST-RUBY. 2004/03/04: Version 2.2.4 2004/03/04: [impl] (thanks Moriyoshi Koizumi) fix many warnings in Win32 VC++ with /W3 option. 2004/03/02: Version 2.2.3 2004/03/02: [bug] (thanks Isao Sonobe) return invalid capture region value if capture history is used. (OP_MEMORY_END_PUSH_REC bug) ex. /\g

(?@

\(\g\)){0}(?(?:\g

)*|){0}/ .match("((())())") 2004/03/02: [impl] (thanks Kazuo Saito) add :nodoc: to onig_stat_print() for RDoc. 2004/03/02: [impl] don't use ONIG_SOURCE_IS_WRAPPED. 2004/02/27: Version 2.2.2 2004/02/27: [impl] fix the position of onig_stat_print(). 2004/02/27: [impl] define ONIG_RUBY_DEFINE_GLOBAL_FUNCTION() in regint.h for ignored by RDoc. 2004/02/26: Version 2.2.1 2004/02/26: [bug] [bugs.php.net:#26677] (thanks behrens) invalid definition at onig_error_code_to_str() in the case of NOT HAVE_STDARG_PROTOTYPES. 2004/02/25: Version 2.2.0 2004/02/25: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/02/24: [test] success in ruby 1.9.0 (2004-02-24) [i686-linux]. 2004/02/24: [bug] undefined IS_BLANK() and IS_GRAPH() was used in onigenc_is_code_ctype() in the case of Ruby M17N. 2004/02/24: [new] support ISO-8859-16. (ONIG_ENCODING_ISO_8859_16) 2004/02/24: [bug] should not fold match for 0xdf in iso8859_6.c. 2004/02/24: [new] support ISO-8859-14. (ONIG_ENCODING_ISO_8859_14) 2004/02/23: [new] support ISO-8859-13. (ONIG_ENCODING_ISO_8859_13) 2004/02/23: [new] support ISO-8859-10. (ONIG_ENCODING_ISO_8859_10) 2004/02/20: [bug] fix iso_8859_4_mbc_is_case_ambig(). 2004/02/20: [new] support ISO-8859-9. (ONIG_ENCODING_ISO_8859_9) 2004/02/19: [bug] correct ctype tables for ISO-8859-3, ISO-8859-4, ISO-8859-6, ISO-8859-7, ISO-8859-8, KOI8_R. 2004/02/18: [bug] wrong replaced name OnigSyntaxGnuOnigex. 2004/02/17: [spec] check capture status for empty infinite loop. [ruby-dev:20224] etc... ex. /(?:\1a|())*/.match("a"), /(?:()|()|()|(x)|()|())*\2b\5/.match("b") add USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK. add OP_NULL_CHECK_END_MEMST, OP_NULL_CHECK_END_MEMST_PUSH. add stack type STK_NULL_CHECK_END. 2004/02/13: [impl] add OnigEncodingEUC_CN to enc/euc_kr.c. 2004/02/13: [bug] (thanks Simon Strandgaard) parsing of nested repeat was invalid. ex. /ab{2,3}*/ was /(?:a(?:b{2,3}))*/, should be /a(?:b{2,3}*)/ 2004/02/12: [bug] (thanks Simon Strandgaard) OP_REPEAT_INC_NG process in match_at() is wrong. ex. bad match /a.{0,2}?a/ =~ "0aXXXa0" 2004/02/12: [bug] (thanks Simon Strandgaard) wrong fetch after (?x) option. ex. "(?x)\ta .\n+b" 2004/02/12: [bug] (thanks Simon Strandgaard) [\^] is not a empty char class. 2004/02/09: [new] add onig_set_syntax_op(), onig_set_syntax_op2(), onig_set_syntax_behavior(), onig_set_syntax_options(). 2004/02/06: [dist] add a new target 'site' to Makefile.in. 2004/02/06: [dist] add index.html. 2004/02/03: [bug] oniggnu.h was not installed by 'make install'. 2004/02/02: Version 2.1.0 2004/02/02: [test] success in ruby 1.9.0 (2004-02-02) [i686-linux]. 2004/02/02: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/02/02: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2004/02/02: [new] support ISO-8859-11. (ONIG_ENCODING_ISO_8859_11) 2004/02/02: [new] support ISO-8859-5. (ONIG_ENCODING_ISO_8859_5) 2004/02/02: [impl] should check single byte encoding or not in and_cclass() and or_cclass(). 2004/01/30: [dist] add oniggnu.h. 2004/01/30: [bug] ISO-8859-7 0xb7 (middle dot) is Punct type. 2004/01/30: [new] support ISO-8859-8. (ONIG_ENCODING_ISO_8859_8) 2004/01/29: [new] support ISO-8859-7. (ONIG_ENCODING_ISO_8859_7) 2004/01/29: [new] support ISO-8859-6. (ONIG_ENCODING_ISO_8859_6) 2004/01/28: [new] support KOI8-R. (ONIG_ENCODING_KOI8_R) 2004/01/28: [new] support KOI8. (ONIG_ENCODING_KOI8) 2004/01/27: [dist] rename enc/isotable.c to enc/mktable.c. 2004/01/27: [new] support ISO-8859-4. (ONIG_ENCODING_ISO_8859_4) 2004/01/26: [new] support ISO-8859-3. (ONIG_ENCODING_ISO_8859_3) 2004/01/26: [bug] EncISO_8859_{1,15}_CtypeTable[256] was wrong. (0x80 - 0xff is not ASCII) 2004/01/23: [new] support ISO-8859-2. (ONIG_ENCODING_ISO_8859_2) 2004/01/23: [dist] add enc/isotable.c. 2004/01/22: [new] support EUC-TW. (ONIG_ENCODING_EUC_TW) 2004/01/22: [bug] definition of GET_ALIGNMENT_PAD_SIZE() and ALIGNMENT_RIGHT() was wrong. type casting should be unsigned int, not int. 2004/01/22: [impl] add defined(__x86_64) || defined(__x86_64__) to unaligned word access condition. (AMD64 ?) 2004/01/21: [dist] rename enc/eucjp.c to enc/euc_jp.c. 2004/01/21: [new] support EUC-KR. (ONIG_ENCODING_EUC_KR) 2004/01/20: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2004/01/20: [dist] change Makefile.in. 2004/01/20: [spec] add \p{...}, \P{...} in char class. 2004/01/20: [new] character property operators \p{...}, \P{...}. supported in ONIG_SYNTAX_JAVA and ONIG_SYNTAX_PERL. 2004/01/19: [spec] allow /a{,n}/ as /a{0,n}/. (but don't allow /a{,}/) 2004/01/19: [dist] rename onigcomp200.h to onigcmpt200.h. 2004/01/19: [dist] update re.c.168.patch. svn add re.c.181.patch. 2004/01/16: [dist] update sample/*.c for new API. 2004/01/16: [dist] add onigcomp200.h. (for old API compatibility) 2004/01/16: [dist] update documents API, RE and RE.ja. 2004/01/16: [spec] change prefix REG_ -> ONIG_, regex_ onig_, ENC_ -> ONIGENC, enc_ -> onigenc_. 2004/01/15: [impl] rename ENC_IS_MBC_E_WORD() to ENC_IS_MBC_WORD(). rename ENC_CTYPE_SUPPORT_LEVEL_SB_ONLY to ENC_CTYPE_SUPPORT_LEVEL_SB. 2004/01/14: [impl] rename UNALIGNED_WORD_ACCESS to PLATFORM_UNALIGNED_WORD_ACCESS. 2004/01/14: [impl] change MATCH_STACK_LIMIT_SIZE value from 200000 to 500000. 2004/01/13: [impl] remove ENC_CODE_TO_MBC_FIRST(enc,code) in regenc.h. remove code_to_mbc_first member in RegCharEncodingType. 2004/01/13: [impl] remove head byte bitset information in cclass->mbuf. 2003/12/26: [impl] change macro name ismb_xxxx() in enc/*.c for escape conflict. 2003/12/24: Version 2.0.0 2003/12/24: [spec] ignore case option is effective to numbered char. ex. /\x61/i =~ "A" 2003/12/24: [test] success in ruby 1.8.1 (2003-12-24) [i686-linux]. 2003/12/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2003/12/24: [test] success in ruby 1.8.0 (2003-08-08) [i386-mswin32]. 2003/12/24: [test] success in regex.c compile test on ruby-m17n. (but can't make miniruby because re.c patch fail.) 2003/12/24: [bug] (thanks H.Miyamoto) /[\W]/ was wrong in 1.9.5. 2003/12/22: [spec] implement fold match on UTF-8 encoding. 2003/12/19: [impl] add ctype_support_level and ctype_add_codes() member to RegCharEncoding type. 2003/12/19: [impl] add add_ctype_to_cc() in regparse.c. 2003/12/19: [impl] add enc_is_code_ctype() in REG_RUBY_M17N case. 2003/12/19: [impl] change ENC_CODE_TO_MBC() interface. 2003/12/18: [new] implement fold match. (variable number of char match in ignore case mode.) ex. German alphabet ess-tsett(U+00DF) match "SS" and "ss". 2003/12/17: [impl] refactoring of encoding system. 2003/12/17: [impl] add enc_init() in regenc.c. 2003/12/17: [new] support Big5. (REG_ENCODING_BIG5) 2003/12/16: [impl] change CodePoint from unsigned int to unsigned long. 2003/12/16: [new] support ISO 8859-15. (REG_ENCODING_ISO_8859_15) 2003/12/16: [impl] change P_() macro definition condition for Win32. 2003/12/16: [dist] add sample/encode.c 2003/12/16: [new] support ISO 8859-1. (REG_ENCODING_ISO_8859_1) 2003/12/15: [impl] rename IS_ENC_XXXX to ENC_IS_XXXX. 2003/12/15: [impl] rename RegDefaultCharEncoding to EncDefaultCharEncoding. 2003/12/15: [impl] divide encoding files. (enc/ascii.c, enc/utf8.c etc...) 2003/12/15: [bug] unexpected infinite loop in regex_snprintf_with_pattern(). change local var. type char* to UChar*. 2003/12/15: [impl] remove REG_MBLEN_TABLE[]. 2003/12/15: [spec] rename function prefix regex_get_prev_char_head(), regex_get_left_adjust_char_head() and regex_get_right_adjust_char_head() to enc_xxxxxx(). 2003/12/15: [impl] rename function prefixes in regenc.h from regex_ to enc_. 2003/12/12: [impl] remove USE_SBMB_CLASS. 2003/12/12: [impl] rename mb -> mbc, mblen() to enc_len(). 2003/12/12: [impl] rename WCINT to CodePoint. 2003/12/11: [impl] delete IS_XXXX() ctype macros from regint.h. 2003/12/11: [impl] add enc->wc_is_ctype() and RegAsciiCtypeTable[256]. 2003/12/11: [impl] remove RegAsciiCaseAmbigTable. 2003/12/10: [impl] use ENC_TO_LOWER() for ignore case comparison. 2003/12/08: [impl] *** re-defined RegCharEncoding in oniguruma.h. *** 2003/12/08: [impl] add USE_POSIX_REGION_OPTION to regint.h. 2003/12/08: [impl] add IS_ENC_WORD() to regenc.h. 2003/12/05: [impl] rename IS_CODE_XXXX() to IS_ENC_XXXX(). 2003/12/05: [impl] delete IS_CODE_WORD() from regenc.h. 2003/12/04: [spec] rename REG_SYN_OP_BACK_REF to REG_SYN_OP_DECIMAL_BACKREF. 2003/12/04: [spec] add (REG_SYN_OP_ESC_W_WORD | REG_SYN_OP_ESC_B_WORD_BOUND | REG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | REG_SYN_OP_BACK_REF) to RegSyntaxGrep. 2003/12/04: [spec] remove REG_ENCODING_DEFAULT and REGCODE_DEFAULT. 2003/12/04: [spec] move declarations of regex_get_default_encoding() and regex_set_default_encoding() from oniguruma.h to regenc.h. 2003/12/03: [new] add regex_get_default_encoding() and regex_set_default_encoding(). 2003/12/03: [spec] REG_ENCODING_DEFAULT meaning is changed. (current default value, not initial default value.) 2003/12/03: [spec] REGCODE_XXX is obsoleted. use REG_ENCODING_XXX. 2003/12/02: [memo] alias svnst='svn status | grep -v "^\?"' 2003/12/02: [spec] move regex_set_default_trans_table() declaration from oniguruma.h to regenc.h. (obsoleted API) 2003/12/02: [impl] move variables RegDefaultCharEncoding, DefaultTransTable and AmbiguityTable to regenc.c. 2003/12/01: [impl] add regex_continuous_sbmb() to regenc.c. 2003/12/01: [dist] add regenc.h and regenc.c. 2003/11/18: [dist] change testconv.rb. 2003/11/18: [bug] (thanks Masaru Tsuda) memory leak in parse_subexp(). 2003/11/18: [bug] (thanks Masaru Tsuda) memory leak in names_clear() and parse_char_class(). 2003/11/17: [bug] memory leak in parse_char_class(). 2003/11/17: [bug] (thanks Masaru Tsuda) OptExactInfo length should not over OPT_EXACT_MAXLEN. (concat_opt_exact_info_str()) 2003/11/12: Version 1.9.5 2003/11/12: [test] success in ruby 1.8.0 (2003-08-08) [i386-cygwin]. 2003/11/12: [test] success in ruby 1.8.1 (2003-11-11) [i686-linux]. 2003/11/12: [spec] add definition of REG_INEFFECTIVE_META_CHAR. 2003/11/11: [dist] add a sample program sample/sql.c. 2003/11/11: [new] add variable meta character. regex_set_meta_char() 2003/11/11: [spec] add syntax op. REG_SYN_OP_VARIABLE_META_CHARS. 2003/11/11: [spec] rename REG_SYN_OP_ESC_CAPITAL_Q_QUOTE to REG_SYN_OP2_ESC_CAPITAL_Q_QUOTE, REG_SYN_OP_QMARK_GROUP_EFFECT to REG_SYN_OP2_QMARK_GROUP_EFFECT. 2003/11/06: [impl] define THREAD_PASS as rb_thread_schedule() in Ruby mode. 2003/11/05: [spec] add syntax behavior REG_SYN_WARN_REDUNDANT_NESTED_REPEAT. 2003/11/05: [spec] rename REG_SYN_WARN_FOR_CC_OP_NOT_ESCAPED to REG_SYN_WARN_CC_OP_NOT_ESCAPED. 2003/11/04: [new] add regex_set_warn_func() and regex_set_verb_warn_func(). 2003/10/30: [new] add regex_name_to_backref_number(). (for multiplex definition name, see sample/names.c) 2003/10/30: [spec] add name_end and reg argument to callback function of regex_foreach_name(). (see sample/names.c) 2003/10/29: [spec] add syntax behavior REG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME. add error code REGERR_MULTIPLEX_DEFINED_NAME. 2003/10/14: [dist] modify sample/simple.c. 2003/10/03: [bug] (thanks nobu) [ruby-dev:21472] sub-anchor of optimization map info was wrong in concat_left_node_opt_info(). ex. /^(x?y)/ = "xy" fail. 2003/09/17: Version 1.9.4 2003/09/17: [spec] change specification of char-class range in ignore case mode follows with Ruby 1.8(2003-09-17). ex. /[H-c]/i ==> (H-Z, 0x5b-0x60, a-c)/i ==> H-Z, h-z, 0x5b-0x60, a-c, A-C 2003/09/16: [bug] (thanks Guy Decoux) remove env->option == option check in parse_effect(). change env->option for dynamic option in parse_exp(). (ex. bad match /(?i)(?-i)a/ =~ "A") 2003/09/12: [spec] rename REG_SYN_ALLOW_RANGE_OP_IN_CC to REG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC, REG_SYN_ESCAPE_IN_CC to REG_SYN_BACKSLASH_ESCAPE_IN_CC. 2003/09/11: [bug] change to IS_SYNTAX_OP2 at REG_SYN_OP2_ESC_GNU_BUF_ANCHOR. 2003/09/09: [spec] rename REG_SYN_OP2_ESC_M_BAR_META to REG_SYN_OP2_ESC_CAPITAL_M_BAR_META, REG_SYN_OP_ESC_Q_QUOTE to REG_SYN_OP_ESC_CAPITAL_Q_QUOTE, REG_SYN_OP_ESC_SUBEXP to REG_SYN_OP_ESC_LPAREN_SUBEXP, REG_SYN_OP_ESC_BUF_ANCHOR to REG_SYN_OP_ESC_AZ_BUF_ANCHOR, REG_SYN_OP_ESC_GNU_BUF_ANCHOR to REG_SYN_OP2_ESC_GNU_BUF_ANCHOR, REG_SYN_OP_ESC_CONTROL_CHAR to REG_SYN_OP_ESC_CONTROL_CHARS, REG_SYN_OP_ESC_WORD to REG_SYN_OP_ESC_W_WORD, REG_SYN_OP_ESC_WORD_BEGIN_END to REG_SYN_OP_ESC_LTGT_WORD_BEGIN_END, REG_SYN_OP_ESC_WORD_BOUND to REG_SYN_OP_ESC_B_WORD_BOUND, REG_SYN_OP_ESC_WHITE_SPACE to REG_SYN_OP_ESC_S_WHITE_SPACE, REG_SYN_OP_ESC_DIGIT to REG_SYN_OP_ESC_D_DIGIT, REG_SYN_OP_CC to REG_SYN_OP_BRACKET_CC, REG_SYN_OP2_CCLASS_SET to REG_SYN_OP2_CCLASS_SET_OP, REG_SYN_CONTEXT_INDEP_OPS to REG_SYN_CONTEXT_INDEP_REPEAT_OPS, REG_SYN_CONTEXT_INVALID_REPEAT_OPS to REG_SYN_CONTEXT_INVALID_REPEAT_OPS. add REG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR. 2003/09/08: [spec] rename REG_SYN_OP_ANYCHAR to REG_SYN_OP_DOT_ANYCHAR, REG_SYN_OP_0INF to REG_SYN_OP_ASTERISK_ZERO_INF, REG_SYN_OP_ESC_0INF to REG_SYN_OP_ESC_ASTERISK_ZERO_INF, REG_SYN_OP_1INF to REG_SYN_OP_PLUS_ONE_INF, REG_SYN_OP_ESC_1INF to REG_SYN_OP_ESC_PLUS_ONE_INF, REG_SYN_OP_0INF to REG_SYN_OP_QMARK_ZERO_ONE, REG_SYN_OP_ESC_0INF to REG_SYN_OP_ESC_QMARK_ZERO_ONE, REG_SYN_OP_INTERVAL to REG_SYN_OP_BRACE_INTERVAL, REG_SYN_OP_ESC_INTERVAL to REG_SYN_OP_ESC_BRACE_INTERVAL, REG_SYN_OP_SUBEXP to REG_SYN_OP_LPAREN_SUBEXP, REG_SYN_OP_ALT to REG_SYN_OP_VBAR_ALT, REG_SYN_OP_ESC_ALT to REG_SYN_OP_ESC_VBAR_ALT, REG_SYN_OP_NON_GREEDY to REG_SYN_OP_QMARK_NON_GREEDY, REG_SYN_OP_SUBEXP_EFFECT to REG_SYN_OP_QMARK_GROUP_EFFECT, REG_SYN_OP2_POSSESSIVE_{REPEAT,INTERVAL} to REG_SYN_OP2_PLUS_POSSESSIVE_{REPEAT,INTERVAL}, REG_SYN_OP2_SUBEXP_CALL to REG_SYN_OP2_ESC_G_SUBEXP_CALL, REG_SYN_OP2_NAMED_GROUP to REG_SYN_OP2_QMARK_LT_NAMED_GROUP and REG_SYN_OP2_ESC_K_NAMED_BACKREF. 2003/09/02: [tune] call reduce_nested_qualifier() after disabling capture for no-name group in noname_disable_map(). ex. /(a+)*(?...)/ 2003/09/02: [impl] include is forgotten to erase in regcomp.c. 2003/09/01: [dist] update doc/RE and doc/RE.ja. 2003/08/26: [bug] (thanks Guy Decoux) should not double free node at the case TK_CC_CC_OPEN in parse_char_class(). 2003/08/19: Version 1.9.3 2003/08/19: [inst] change re.c.180.patch. 2003/08/19: [impl] rename 'list of captures' to 'capture history'. 2003/08/19: [dist] add doc/RE.ja. (Japanese) 2003/08/19: [new] add regex_copy_syntax(). 2003/08/19: [spec] rename REG_SYN_OP2_ATMARK_LIST_OF_CAPTURES to REG_SYN_OP2_ATMARK_CAPTURE_HISTORY. 2003/08/18: [spec] (thanks nobu) don't use IMPORT in oniguruma.h and onigposix.h. 2003/08/18: [impl] (thanks nobu) change error output to stdout in testconv.rb. 2003/08/18: [inst] (thanks nobu) lacked $(srcdir) in Makefile.in. 2003/08/18: [bug] REG_MBLEN_TABLE[SJIS][0xFD-0xFF] should be 1. 2003/08/18: [bug] (thanks nobu) mbctab_sjis[0x80] should be 0. 2003/08/18: [bug] (thanks nobu) single/multi-byte decision was wrong in parse_char_class(). add regex_wc2mblen(). should not set fetched to 1 in TK_RAW_BYTE case. 2003/08/18: [bug] should update BitSet in the case inc_n >= 0 in add_wc_range_to_buf(). 2003/08/13: [bug] change re.c.180.patch for fix rb_reg_to_s() in re.c. 2003/08/11: [bug] should clear region->list in regex_region_resize(). 2003/08/08: Version 1.9.2 2003/08/08: [test] success in ruby 1.8.0 (2003-08-08) on Windows 2000 VC++ 6.0 and Cygwin. 2003/08/08: [impl] don't define macro vsnprintf for WIN32 platform, because definition is added in win32\win32.h. 2003/08/08: [test] success in ruby 1.8.0 and ruby 1.6.8(2003-08-03) on Linux. 2003/08/08: [dist] change re.c.180.patch and re.c.168.patch. 2003/08/08: [new] (thanks akr) implemented list of captures. (?@...), (?@...) 2003/08/07: [dist] add sample/listcap.c. 2003/08/06: [bug] OP_MEMORY_END_PUSH_REC case in match_at(). renewal of mem_start_stk[] should be after STACK_PUSH_MEM_END() call. 2003/07/29: [new] add regex_get_encoding(), regex_get_options() and regex_get_syntax(). 2003/07/25: [spec] (thanks akr) change group(...) to shy-group(?:...) if named group is used in the pattern. add REG_SYN_CAPTURE_ONLY_NAMED_GROUP. 2003/07/24: [spec] rename REG_OPTION_CAPTURE_ONLY_NAMED_GROUP to REG_OPTION_DONT_CAPTURE_GROUP. add REG_OPTION_CAPTURE_GROUP. 2003/07/17: [spec] rename REG_SYN_OP2_NAMED_SUBEXP to REG_SYN_OP2_NAMED_GROUP. 2003/07/17: [spec] add REGERR_EMPTY_GROUP_NAME. 2003/07/17: [spec] rename REGERR_INVALID_SUBEXP_NAME to REGERR_INVALID_CHAR_IN_GROUP_NAME. 2003/07/17: [spec] restrict usable chars of group name to alphabet, digit, '_' or multibyte-char in fetch_name(). [ruby-dev:20706] 2003/07/16: [impl] minor change of sample/names.c. 2003/07/14: [impl] rename USE_NAMED_SUBEXP to USE_NAMED_GROUP. 2003/07/14: [bug] add fetch_name() for USE_NAMED_SUBEXP off case. 2003/07/14: [API] add regex_number_of_names(). 2003/07/08: [impl] change error message for undefined group number call. 'undefined group reference: /(a)\g<2>/' --> 'undefined group <2> reference: /(a)\g<2>/' 2003/07/08: [dist] modify doc/RE. 2003/07/07: [impl] OP_SET_OPTION is not needed in compiled code. add IS_DYNAMIC_OPTION() to regint.h. 2003/07/07: [spec] called group should not ignore outside option (?i:...). ex. /(?i:(?(a)\2)){0}\g/.match("aA") add opcode OP_BACKREFN_IC and OP_BACKREF_MULTI_IC. set option status to effect memory in optimize_node_left(). 2003/07/07: [impl] add opcode OP_ANYCHAR_ML, OP_ANYCHAR_ML_STAR and OP_ANYCHAR_ML_START_PEEK_NEXT. 2003/07/07: [bug] (thanks nobu) REG_MBLEN_TABLE[SJIS][0x80] should be 1. 2003/07/07: [spec] rename REG_SYN_OP_QUOTE to REG_SYN_OP_ESC_Q_QUOTE. 2003/07/04: Version 1.9.1 2003/07/04: [new] add REG_OPTION_CAPTURE_ONLY_NAMED_GROUP. (thanks .NET) 2003/07/04: [spec] check mbuf member in the case of REG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC in parse_char_class(). 2003/07/04: [spec] typo REG_SYN_WARN_FOR_CC_OP_NOT_ESCAPEED. should be REG_SYN_WARN_FOR_CC_OP_NOT_ESCAPED. 2003/07/04: [bug] conflict values on REG_SYN_WARN_FOR_CC_OP_NOT_ESCAPEED and REG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC. (thanks nobu) 2003/07/03: [spec] add REG_SYN_OP_ESC_CONTROL_CHAR flag. 2003/07/03: [spec] remove REG_SYN_OP_ESC_OCTAL3 and REG_SYN_OP_ESC_X_HEX2 flag from RegSyntaxGnuRegex. 2003/07/03: [spec] remove REG_SYN_OP_NON_GREEDY flag from RegSyntaxGnuRegex. 2003/07/02: [dist] fix doc/RE. 2003/07/01: [impl] add config flag USE_VARIABLE_SYNTAX. (turn off variable syntax on Ruby) 2003/07/01: [spec] add syntax behavior REG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND. 2003/06/30: [spec] allow different length top-level alternatives in look-behind. ex. (?<=abc|abcd), (? (?>a*)b (thanks Jeffrey E. F. Friedl) 2003/06/02: [impl] remove multibyte-BitSet for OP_CCLASS_MB/OP_CCLASS_MB_NOT. 2003/05/30: [new] char class intersection operator &&[...] like Java(TM). (thanks akr) 2003/05/30: [bug] should use bbuf_free() for CClassNode in regex_node_free(). 2003/05/29: [bug] wrong usage of syntax REG_SYN_ALLOW_EMPTY_RANGE_IN_CC. /[d-a]/ should be error. 2003/05/28: [impl] optimize stop-backtrack compiled code. (/(?>a*)/, /(?>\w+)/ etc...) add OP_POP opcode. 2003/05/28: [new] possessive repeat operator. (?+, *+, ++, {n,m}+) 2003/05/27: [spec] '-' at beginning of char-class should be warn only if it is start of range. (ex. /[--a]/) 2003/05/27: [spec] should not warn for right bracket at beginning of pattern. ex. /]aaa/ 2003/05/27: [spec] change CCEND_ESC_WARN() from VERB_WARNING() to WARNING(). 2003/05/27: [spec] /[]aaa/ should be empty char-class error. /[]aaa]/ should be warn for 'without backslash'. (add char_exist_check() in regparse.c) 2003/05/26: [bug] OP_REPEAT in recursive subexp call. ex. /(?(a|b\gc){3,5})/.match("baaaaca") => "baaaaca" was wrong result. (should be "aaaa") 2003/05/26: [impl] add num_call member to regex_t. 2003/05/26: [impl] add repeat_range member to regex_t. (for delete upper,lower members from StackType.u.repeat) 2003/05/26: [bug] change print_names() to external regex_print_names(). 2003/05/26: [tune] change OP_NULL_CHECK_END process in match_at(). 2003/05/26: [spec] change CCEND_ESC_WARN() from WARNING() to VERB_WARNING(). 2003/05/26: [spec] remove POSIXLINE option. (?p:...) (be made the same as Ruby.) 2003/05/22: [spec] use OP_NULL_CHECK_XXX only if repeat is infinite. prev. /(?:()|()){0,10}\1\2/ =~ "" ==> FAIL now /(?:()|()){0,10}\1\2/ =~ "" ==> MATCH 2003/05/22: [impl] change target_empty setting condition in setup_tree(). 2003/05/19: [impl] avoid zero length repeat optimization. (thanks matz) /()*/ ==> /()?/, /()+/ ==> /()/ etc... 2003/05/19: [impl] minor changes for gcc -Wall. (-DREG_DEBUG_STATISTICS case) 2003/05/19: [spec] rename regex_foreach_names() to regex_foreach_name(). 2003/05/16: [new] add --with-statistics option to configure. 2003/05/16: [bug] move RegOpInfo[] definition to regint.h. 2003/05/16: [new] add regex_version(). 2003/05/14: Version 1.8.6 2003/05/14: [bug] use _vsnprintf() on Win32. 2003/05/14: [spec] define USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE. (/\n$/ =~ "\n", /\n\Z/ =~ "\n") [ruby-dev:20125] 2003/05/14: [impl] minor changes for gcc -Wall. 2003/05/14: [impl] add string.h check in AC_CHECK_HEADERS(). 2003/05/13: [impl] minor changes for gcc -Wall. 2003/05/13: [impl] add regex_snprintf_with_pattern(). 2003/05/13: [spec] add warning for char class meta character without escape in Ruby mode ('[', '-', ']'). 2003/05/13: [impl] define WARNING() and VERB_WARNING() in regint.h. 2003/05/13: [bug] correct is_code_ascii() for /[[:ascii:]]/. 2003/05/12: [dist] add regular expression document (doc/RE). 2003/05/12: [spec] specification of $(END_LINE) was made the same as Ruby 1.8. [ruby-dev:20130] (thanks matz) 2003/05/12: [memo] shifted to Subversion(version 0.21.0) from CVS. 2003/03/19: Version 1.8.5 2003/03/19: [impl] change REG_EXTERN definition. (thanks nobu) 2003/03/19: [impl] abbreviation for long error_par in regex_error_code_to_str(). 2003/03/18: [dist] change re.c.XXX.patch for GNU regex API changes. 2003/03/18: [spec] change API regex_new(), regex_recompile() and regex_error_code_to_str(). change API re_compile_pattern() and re_recompile_pattern(). 2003/03/18: [spec] replace REGERR_END_PATTERN_AT_GROUP_{COMMENT|OPTION} to REGERR_END_PATTERN_IN_GROUP. 2003/03/17: [impl] should free err_arg. 2003/03/17: [bug] mistake(high -> to) in add_wc_range_to_buf(). 2003/03/17: [spec] add err_arg argument to regex_new() and regex_recompile(). for detail error message. (thanks akr) 2003/03/12: Version 1.8.4 2003/03/12: [tune] use cached value of effect node in get_min_match_length(). 2003/03/12: [bug] escaped alphabet should be TK_RAW_BYTE in fetch_token() and fetch_token_in_cc(). 2003/03/12: [spec] change named backref and subexp call format. backref: \k, call: \g (thanks akr) 2003/03/11: [inst] add regparse.[ch] in win32/Makefile. 2003/03/11: [bug] if UNALIGNED_WORD_ACCESS isn't set then compile error in unset_addr_list_fix(). (thanks knu) 2003/03/10: [impl] divide regcomp.c to regcomp.c, regparse.c and regparse.h. 2003/03/10: [bug] should handle multi-byte code name in fetch_name(). 2003/03/10: [spec] remove REGERR_TABLE_FOR_IGNORE_CASE_IS_NOT_SETTED. 2003/03/10: [spec] support POSIX API option REG_NOSUB. add comp_options member to POSIX API regex_t. 2003/03/10: Version 1.8.3 2003/03/10: [bug] can not compile with Ruby 1.6.8. (inconsistent st.h with 1.6 and 1.8) use hash table on Ruby 1.8 only. 2003/03/10: [spec] forbid to use '\' in group name. 2003/03/08: [impl] remove check_backref_number(). 2003/03/08: [bug] called group in 0-repeat should not be eliminated from compile code. ex. /(?*n)(?){0}/ (thanks akr) add is_refered member to QualifierNode. 2003/03/07: [impl] use hash table(st.[ch]) for implementation of name table. (enable on Ruby in default) 2003/03/07: [new] add regex_foreach_names(). 2003/03/06: [impl] add member reg->stack_pop_level. 2003/03/06: [impl] add operator OP_MEMORY_START and member reg->backtrack_mem. 2003/03/06: [bug] if REG_OPTION_FIND_LONGEST or REG_OPTION_NOT_EMPTY, should handle backtrack of MEM_END. add OP_MEMORY_END_PUSH and OP_MEMORY_END_PUSH_REC. 2003/03/06: [impl] rename OP_MEMORY_END_PUSH to OP_MEMORY_END_MARK. 2003/03/06: [spec] change error messages. 2003/03/06: [tune] add tiny_pop check in STACK_POP. 2003/03/05: Version 1.8.2 2003/03/05: [impl] use cache info in EFFECT_MEMORY case in optimize_node_info(). 2003/03/05: [impl] add EFFECT_MEMORY node reference count check in optimize_node_left(). 2003/03/05: [impl] add min-len, max-len, char-len cache in EffectNode. 2003/03/05: [spec] allow to call in look behind. ex. /(?<=(?*a))/ 2003/03/05: [bug] forgotten N_ANCHOR case in check_backref_number(), subexp_inf_recursive_check_trav() etc... 2003/03/05: [impl] rename USE_ONIGURUMA_EXTENSION to USE_SBMB_CLASS. 2003/03/04: [impl] add CALL-node info in optimize_node_left(). 2003/03/04: [spec] prohibit left recursion of subexp call. ex. (?|(?*n)a) add subexp_inf_recursive_check_trav(). 2003/03/04: [spec] rename REG_SYN_STRICT_CHECK_BACKREF_NUMBER to REG_SYN_STRICT_CHECK_BACKREF 2003/03/03: [bug] /(?a(?*n)|)/ isn't infinite recursion. fix N_LIST case in subexp_recursive_check(). (thanks akr) 2003/03/03: [bug] /(?|(?*n))+/ segmentation fault. should re-allocate in unset_addr_list_add(). (thanks akr) 2003/03/01: Version 1.8.1 2003/03/01: [bug] change STACK_GET_MEM_START() and STACK_PUSH_MEM_END(). 2003/03/01: [new] add reg_name_to_group_numbers() to POSIX API. 2003/03/01: [impl] use OP_MEMORY_END_PUSH in callable subexp compiled code only if subexp is recursive. 2003/03/01: [spec] rename regex_name_to_backrefs() to regex_name_to_group_numbers(). 2003/02/28: [impl] use function stack_double() instead of macro. 2003/02/28: [new] subexp call. (?*name) (thanks akr) 2003/02/28: [spec] add match stack limit check. (MATCH_STACK_LIMIT_SIZE) 2003/02/28: [impl] check recursive subexp call. 2003/02/28: [impl] add opcode OP_MEMORY_END_PUSH for callable subexp. 2003/02/28: [impl] add opcode OP_CALL, OP_RETURN. add stack type STK_CALL_FRAME, STK_RETURN, STK_MEM_END. 2003/02/26: [spec] add new syntax behavior REG_SYN_STRICT_CHECK_BACKREF_NUMBER. if it is set, then error /(\1)/, /\1(..)/ etc... 2003/02/26: [spec] if backref number is greater than max group number, then return compile error. (REGERR_INVALID_BACKREF_NUMBER) 2003/02/26: [tune] bad implemented N_ALT case in get_min_match_length(). 2003/02/26: [dist] auto update testc.c and win32/testc.c in dist target. 2003/02/26: [impl] add -win option to testconv.rb. 2003/02/25: [spec] allow to assign same name to different group. add OP_BACKREF_MULTI. 2003/02/24: [impl] reduce redundant repeat of empty target. ex. /()*/ ==> /()?/, /()+/ ==> /()/, /(?:)+/ ==> // 2003/02/24: [impl] change condition in regex_is_allow_reverse_match(). 2003/02/24: [impl] convert i(/../, ...) functions in testconv.rb. 2003/02/24: [impl] change name table struct. 2003/02/22: Version 1.8.0 2003/02/22: [new] named subexp, named back reference. (thanks akr) define: (?...), back-ref: \g 2003/02/22: [impl] use str_node_can_be_split(). 2003/02/21: [dist] add sample/posix.c 2003/02/21: [spec] rename some error code symbols. 2003/02/21: [spec] max number of multibyte ranges(255) is small. 255 --> 1000. (thanks MoonWolf) 2003/02/20: [new] supported Basic Regular Expression(BRE) in POSIX API. (REG_EXTENDED option: Extended RE) 2003/02/20: [new] variable syntax. 2003/02/12: Version 1.7.2 2003/02/12: [bug] mismatch /\?a/i.match('?A'). check raw value in scan_make_node() and scan_backslash(). (thanks Nobu) 2003/02/12: [impl] rename 'max_mem' to 'num_mem' in regex_t. 2003/02/12: [impl] rename 'code' to 'enc' in regex_t. 2003/02/12: [spec] remove transtable argument in regex_new and regex_recompile. remove transtable member in regex_t. 2003/02/10: [inst] change backup file suffix name from '.orig' to '.ruby_orig'. (win32/Makefile) 2003/02/10: [spec] number check in scan_char_class() ignore-case mode. ex. /[\x58-\x64]/i 2003/02/10: [impl] don't use OP_MEMORY_END_PUSH (and STK_MEM_END). 2003/02/10: [impl] lift up head_exact value from child qualifier node to parent. 2003/02/10: [tune] change stack type values. 2003/02/10: [dist] add HISTORY. 2003/02/08: [tune] change stack type values. 2003/02/08: [tune] add STACK_BASE_CHECK(). 2003/02/08: [tune] add STACK_PUSH_ENSURED(). 2003/02/08: [dist] change contents of doc/API. 2003/02/07: [inst] change backup file suffix name from '.orig' to '.ruby_orig'. 2003/02/07: [spec] range in char-class should be same spec. with Ruby in ignore-case mode. (ex. /[A-c]/i == /[a-c]/i) (thanks MoonWolf) 2003/02/07: [spec] [!--] should be allowed. (thanks MoonWolf) 2003/02/07: [dist] refresh re.c.180.patch for re.c (2003-02-06). 2003/02/07: Version 1.7.1 2003/02/07: [impl] check first byte of string in ignore-case mode. (get_head_exact_node()) 2003/02/07: [impl] remove redundant statements in setup_tree(). 2003/02/06: [new] create Win32 DLL. 2003/02/06: [impl] use P_() macro for function prototype. 2003/02/06: [impl] add HAVE_PROTOTYPE, HAVE_STDARG_PROTOTYPES in configure.in and config.h.in. 2003/02/06: [spec] /[0-9-a]/ is allowed as usual char '-' and 'a' in Ruby. add USE_BETTER_COMPATIBILITY_FOR_ORIGINAL_REGEX in regint.h. (thanks MoonWolf) 2003/02/06: [spec] rename REG_MBCTYPE_XXXX to REG_ENCODING_XXXX in onigposix.h. 2003/02/05: [spec] rename MBCTYPE_XXXX to REG_MBCTYPE_XXXX in onigposix.h. 2003/02/05: [spec] add POSIX API error REG_EONIG_THREAD to onigposix.h. 2003/02/05: [dist] add .cvsignore file. 2003/02/04: Version 1.7 2003/02/04: [bug] typo miss in regex_region_copy(). 2003/02/04: [impl] change THREAD_PASS macro. (regint.h) 2003/02/04: [dist] add API document file doc/API. 2003/02/04: [tune] if sub_anchor has ANCHOR_BEGIN_LINE then set REG_OPTIMIZE_EXACT_BM in set_optimize_exact_info(). 2003/02/04: [spec] reimplement regex_clone() and it is obsoleted. 2003/02/04: [bug] add REGERR_OVER_THREAD_PASS_LIMIT_COUNT to regerror.c regposix.c. 2003/02/03: [bug] Hankaku-Kana may be second byte in Shift_JIS regex_is_allow_reverse_match(). 2003/02/03: [impl] add optimization type REG_OPTIMIZE_EXACT_BM_NOT_REV. remove exact_allow_reverse_match member in regex_t. 2003/02/03: [impl] add exact_allow_reverse_match member in regex_t. 2003/02/03: [impl] compile-search conflict in regex_search() is handled. 2003/02/01: [tune] decrease regex_region_clear() calling from regex_search(). 2003/02/01: [tune] remove region argument from match_at(). 2003/01/31: [tune] don't use strlen() in regexec() and regcomp(). 2003/01/31: [tune] decrease regex_reduce_chain() calling in regex_search(). 2003/01/31: [bug] STRING_CMP() in regexec.c was wrong in ignore-case. 2003/01/31: [impl] convert to lower-case char at string compile time. change SBTRANSCMP() in regexec.c. 2003/01/31: [impl] rename TTRANS() to TOLOWER(). 2003/01/30: [bug] .c.o --> .c.obj in win32\Makefile. 2003/01/30: [impl] add -DNOT_RUBY to Makefile.in. NOT_RUBY is refered in regint.h for escape double including config.h. 2003/01/30: [impl] when string hasn't case ambiguity, don't compile to ignore case opcode. 2003/01/29: [impl] add SJIS, UTF-8 test_sb() test. 2003/01/29: [dist] add INSTALL-RUBY file. 2003/01/28: [test] success in Cygwin, Ruby 1.8.0 (2003-01-27). 2003/01/24: [inst] add rback target to Makefile.in. 2003/01/24: [impl] change SBCMP() -> IS_NEWLINE() in match_at(). 2003/01/23: [impl] add encoding arg to scan_xxxx_number(). 2003/01/23: [impl] rename WCInt to WCINT. 2003/01/22: [bug] POSIX API regexec() was not thread safe. remove region member from POSIX regex_t. [new] add search time option REG_OPTION_POSIX_REGION. (region argument is treated as regmatch_t[] type) speed up regexec(). 2003/01/22: [memo] start CVS entry in my box. 2003/01/21: Version 1.6 2003/01/21: [test] Mac OS X 10.1, Ruby 1.8.0 (2003-01-20) 2003/01/20: [impl] add UTF-8 check to test.rb. (thanks UENO Katsuhiro) 2003/01/18: [impl] change REGION_NOTPOS to REG_REGION_NOTPOS in regex.h. 2003/01/17: [dist] add sample/simple.c. 2003/01/17: [inst] add configure option --with-rubydir. 2003/01/17: [bug] bad implemeted POSIX API options. default: /./ not match "\n", anchor not match "\n" REG_NEWLINE: /./ not match "\n", anchor match "\n" 2003/01/16: [impl] rewrite POSIX API regexec() for speed up. 2003/01/16: [impl] add region member to POSIX regex_t struct. 2003/01/16: [inst] rename library file from 'libregex.a' to 'libonig.a'. 2003/01/15: [dist] add testc.c to distribution file. 2003/01/15: [test] success in 'make rtest/ctest/ptest' on Windows 2000. 2003/01/15: [bug] change '/' to \' in win32/Makefile. 2003/01/14: [test] success in Ruby make test on Windows 2000. VC++6.0, Ruby 1.6.8 (2003-01-12) 2003/01/14: [inst] change Makefile.in and win32/Makefile. 2003/01/11: [inst] changes for Win32 platform. (regint.h, reggnu.c, regcomp.c) 2003/01/11: [dist] add win32 directory. (config.h, Makefile, testc.c) 2003/01/10: [inst] add onigposix.h to install target. (Makefile.in) 2003/01/10: [bug] lacked a comma in ESTRING[]. (regposerr.c) 2003/01/10: [bug] local variable name was wrong. buf -> tbuf (regerror()) 2003/01/10: [spec] remove REG_RUBY_M17N case from onigposix.h and regposix.c. 2003/01/09: Version 1.5 2003/01/09: [inst] replace Ruby re.c.XXX.patch files. (166 -> 168, 172 -> 180) 2003/01/09: [new] implement POSIX API. (thanks knu) (onigposix.h, regposix.c, regposerr.c) 2003/01/08: [spec] remove REGERR_END_PATTERN_AFTER_BACKSLASH in regex.h. 2003/01/08: [spec] region arg can be NULL in regex_search() and regex_match(). 2003/01/08: Version 1.4 2003/01/08: [inst] add test program converter (test.rb -> testc.c). 2003/01/08: [bug] move GET_WCINT() from regcomp.c to regint.h. 2003/01/07: [inst] add new test script (test.rb). 2002/12/30: [bug] wrong merge in multibyte mode (alt_merge_opt_exact_info()). 2002/12/28: [inst] add rtest target to Makefile.in. 2002/12/28: [bug] /\xfe/.match("\xfe") mismatch in multibyte mode. add "raw" flag arg to concat_opt_exact_info_str(). 2002/12/25: [bug] check condition was wrong in alt_merge_opt_map_info(). 2002/12/25: [impl] add threshold_len check in regex_search(). 2002/12/23: [bug] prec-read in alternative (/a|(?=z).f/.match("zf") => nil) 2002/12/23: [bug] \G in alternative (/a|\Gz/.match("bza") => "z"). add start member in MatchArg. (regexec.c) 2002/12/21: [impl] **** rewrite all optimization process. **** 2002/12/16: [impl] remove node subtype EFFECT_EMPTY. 2002/12/12: [impl] reconstruct node types. (regcomp.c) 2002/12/11: [impl] add regerror.c 2002/12/10: [bug] [ruby-dev:19042] (thanks Nobu) anchor(\G etc...) influenced outside of "|". (/a|\Gb/) 2002/11/30: [bug] [ruby-dev:18966] (thanks Nobu) char-class(\S, [^\s] etc...) optimize map-info was wrong. 2002/11/29: [bug] infinite loop on NULL-pointer str search (regex_search()). (thanks matz) 2002/11/29: [bug] change static -> extern (regex_chain_reduce()). 2002/11/29: [bug] change encoding to RegDefaultCharEncoding in re_recompile_pattern(). (adapt to re.c) 2002/04/24: [spec] USE_ONIGURUMA_EXTENSION is disabled in default. 2002/04/24: [new] add searching time option: REG_OPTION_NOTBOL/NOTEOL. add searching time option argument to regex_search() and regex_match(). (prepare for POSIX API) 2002/04/20: [impl] divide regex.c file into regcomp.c, regexec.c, reggnu.c and regint.h. 2002/04/09: [impl] move IS_MULTILINE() to outside of loop in OP_ANYCHAR_STAR. 2002/04/08: [impl] don't use OP_REPEAT operator for '??'. 2002/04/06: [impl] reduce redundant nested repeat operators(?,*,+,??,*?,+?). ex. (?:a*)?, (?:a??)* etc.. 2002/04/06: [spec] should not warn for /(?:a?)+?/. 2002/04/04: [spec] should allow fixed length alternative and repeat pattern in look-behind. ex. /(?<=(a|b){3})/ (thanks Guy Decoux) 2002/04/02: [spec] should warn for /(?:a+)?/ and /(?:a*)??/. (thanks akr) 2002/04/01: Version 1.3 2002/04/01: [dist] add COPYING. 2002/03/30: [spec] warn redundant nested repeat operator in Ruby verbose mode. ex. (?:a*)? 2002/03/30: [spec] nested repeat operator error check should be same with GNU regex. (thanks Guy Decoux) 2002/03/30: [new] add \x{hexadecimal-wide-char}. (thanks matz) 2002/03/27: [bug] MBCTYPE_XXX symbol values should be same with GNU regex. 2002/03/27: [impl] add THREAD_ATOMIC to regex_clone(), regex_init(), regex_end(). 2002/03/25: [spec] if encoding is utf-8, allow combination of singlebyte and multibyte code range in char class. (cancelled 2002/04/01: for M17N compatibility) 2002/03/25: [dist] description of the license condition is added to README. 2002/03/23: [bug] should set all bits of reg->mem_stats, if REG_OPTION_FIND_LONGEST or REG_OPTION_NOT_EMPTY. 2002/03/23: [new] add a new option REG_OPTION_NOT_EMPTY. 2002/03/20: [spec] allow incompleted left brace as an usual char. ex. /{/, /({)/, /a{2,3/ etc... 2002/03/20: [impl] serialize integer in bytecode. (switch by UNALIGNED_WORD_ACCESS in regex.c) 2002/03/20: [impl] change re_mbcinit() for REG_RUBY_M17N. 2002/03/19: [impl] word alignment of char class multi-byte code ranges. 2002/03/19: [impl] replace OP_EXACTMB4N with OP_EXACTMB3N. 2002/03/19: [bug] OP_CCLASS_MB_NOT process in matchAt() is wrong. 2002/03/19: [new] add re_mbctab[] for Ruby extension library compatibility. 2002/03/19: [spec] allow nested repeat operator, if operator is {n,m} type. 2002/03/19: [new] add REG_IS_PATTERN_ERROR(ecode) in regex.h 2002/03/18: [spec] /[a-b-c]/ should be error. 2002/03/18: [bug] /[\w-a]/ should be error. (thanks Guy Decoux) 2002/03/18: [bug] /[\]/ should be error. (thanks Guy Decoux) 2002/03/18: [bug] /()*/ etc.. should not be error. (thanks Guy Decoux) 2002/03/18: [spec] /a{1}*/ should not be error. (thanks Guy Decoux) 2002/03/18: [bug] ab{2}{3} was interpreded to (?:a(?:b{2})){3} (thanks Guy Decoux) 2002/03/18: [bug] abort /(?i)*a/ etc... (thanks Guy Decoux) 2002/03/18: [bug] abort /a|*/,/a|{1}/ etc... (thanks Guy Decoux) 2002/03/13: Version 1.2 2002/03/13: [test] success in rubicon/builtin/AllBuiltinTests.rb. (thanks rubicon) 2002/03/13: [bug] OP_EXACTMBN process in matchAt() is wrong. 2002/03/13: [bug] start argument of BackwardSearchRange() is wrong. 2002/03/12: [spec] change function name style from CamelCase to underline_separation. (includes API) 2002/03/12: [bug] if pattern has nested null-check, cause infinite loop. correct STACK_NULL_CHECK() macro. (thanks Guy Decoux) 2002/03/11: [bug] it is wrong that four numbers to continue as an octal value in scanBackSlash(). ex. /\0111/ (thanks matz) 2002/03/11: [new] \k (single-byte word char), \K (multi-byte char). 2002/03/09: [inst] add two targets to Makefile.in (166 and 172). 2002/03/09: [spec] decrease REG_MAX_BACKREF_NUM, REG_MAX_REPEAT_NUM values. 2002/03/08: [spec] allow use of "\A"(begin-buf) in look-behind. 2002/03/08: [impl] add a new opcode OP_PUSH_IF_PEEK_NEXT. 2002/03/08: [impl] add a new opcode OP_ANYCHAR_STAR_PEEK_NEXT. 2002/03/07: [spec] prohibit use of capture group "(...)" in negative look-behind. 2002/03/07: [inst] add configure.in, config.h.in, Makefile.in. 2002/03/07: [impl] call Init_REGEX_STAT() in RegexInit(). 2002/03/07: [spec] less length string match with negative look-behind. ex. /(? svn copy file:///home/kosako/svnreps/svnrep_onig/trunk file:///home/kosako/svnreps/svnrep_onig/tags/5.0.0 -m "ADD TAG: 5.0.0" svn propset svn:ignore -F .cvsignore . svn commit -m "..." cvs history -T cvs rtag "VERSION_X_X_X" oniguruma * write Makefile.am and configure.in. > aclocal > libtoolize or glibtoolize > automake --foreign --add-missing > autoconf > configure --with-rubydir=... CFLAGS="-O2 -Wall" VERSION = current:revision:age current: interface number (from 0) revision: implementation number of same interface (from 0) age: number of supported previous interfaces (if current only supported then age == 0) //END ================================================ FILE: src/Onigmo/INSTALL ================================================ Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ================================================ FILE: src/Onigmo/Makefile.am ================================================ ## Makefile.am for Oniguruma encdir = $(top_srcdir)/enc sampledir = $(top_srcdir)/sample libname = libonig.la ACLOCAL_AMFLAGS = -I m4 #AM_CFLAGS = -DNOT_RUBY AM_CFLAGS = INCLUDES = -I$(top_srcdir) -I$(includedir) SUBDIRS = . sample include_HEADERS = oniguruma.h oniggnu.h onigposix.h lib_LTLIBRARIES = $(libname) libonig_la_SOURCES = regint.h regparse.h regenc.h st.h \ regerror.c regparse.c regext.c regcomp.c regexec.c reggnu.c \ regenc.c regsyntax.c regtrav.c regversion.c st.c \ regposix.c regposerr.c \ $(encdir)/unicode.c $(encdir)/ascii.c $(encdir)/utf8.c \ $(encdir)/utf16_be.c $(encdir)/utf16_le.c \ $(encdir)/utf32_be.c $(encdir)/utf32_le.c \ $(encdir)/unicode/casefold.h $(encdir)/unicode/name2ctype.h \ $(encdir)/euc_jp.c $(encdir)/sjis.c $(encdir)/cp932.c \ $(encdir)/iso8859_1.c \ $(encdir)/iso8859_2.c $(encdir)/iso8859_3.c \ $(encdir)/iso8859_4.c $(encdir)/iso8859_5.c \ $(encdir)/iso8859_6.c $(encdir)/iso8859_7.c \ $(encdir)/iso8859_8.c $(encdir)/iso8859_9.c \ $(encdir)/iso8859_10.c $(encdir)/iso8859_11.c \ $(encdir)/iso8859_13.c $(encdir)/iso8859_14.c \ $(encdir)/iso8859_15.c $(encdir)/iso8859_16.c \ $(encdir)/euc_tw.c $(encdir)/euc_kr.c $(encdir)/big5.c \ $(encdir)/gb18030.c $(encdir)/koi8_r.c $(encdir)/cp1251.c libonig_la_LDFLAGS = -version-info $(LTVERSION) EXTRA_DIST = .gitignore oniguruma.pc.in HISTORY README.ja index.html \ index_ja.html doc/API doc/API.ja doc/RE doc/RE.ja doc/FAQ doc/FAQ.ja \ doc/UnicodeProps.txt \ tool/.gitignore tool/CaseFolding.py tool/convert-name2ctype.sh \ tool/enc-unicode.rb \ win32/Makefile win32/config.h win32/testc.c \ win32/makedef.py win32/onig.rc \ $(encdir)/koi8.c $(encdir)/mktable.c \ $(sampledir)/encode.c $(sampledir)/listcap.c $(sampledir)/names.c \ $(sampledir)/posix.c $(sampledir)/simple.c $(sampledir)/sql.c \ $(sampledir)/syntax.c $(sampledir)/crnl.c \ test.rb testconv.rb testconvu.rb \ onig.py testpy.py bin_SCRIPTS = onig-config onig-config: onig-config.in do_subst = sed \ -e 's,[@]datadir[@],$(datadir),g' \ -e 's,[@]datarootdir[@],$(datarootdir),g' \ -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ -e 's,[@]prefix[@],$(prefix),g' \ -e 's,[@]exec_prefix[@],$(exec_prefix),g' \ -e 's,[@]libdir[@],$(libdir),g' \ -e 's,[@]includedir[@],$(includedir),g' oniguruma.pc: $(srcdir)/oniguruma.pc.in Makefile $(do_subst) < $(<) > $(@) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = oniguruma.pc dll: $(CXX) -shared -Wl,--output-def,libonig.def -o libonig.dll *.o \ $(LIBS) strip libonig.dll # Ruby TEST rtest: $(RUBYDIR)/ruby -w -Ke $(srcdir)/test.rb # character-types-table source generator mktable: $(encdir)/mktable.c $(srcdir)/regenc.h $(CC) -I$(top_srcdir) -o mktable $(encdir)/mktable.c # TEST TESTS = testc testp testcu check_PROGRAMS = testc testp testcu atest: testc testp testcu @echo "[Oniguruma API, ASCII/EUC-JP check]" @$(top_builddir)/testc | grep RESULT @echo "[POSIX API, ASCII/EUC-JP check]" @$(top_builddir)/testp | grep RESULT @echo "[Oniguruma API, UTF-16 check]" @$(top_builddir)/testcu | grep RESULT testc_SOURCES = testc.c testc_LDADD = libonig.la testp_SOURCES = testc.c testp_LDADD = libonig.la testp_CFLAGS = -DPOSIX_TEST testcu_SOURCES = testu.c testcu_LDADD = libonig.la testc.c: $(srcdir)/test.rb $(srcdir)/testconv.rb ruby -Ke $(srcdir)/testconv.rb < $(srcdir)/test.rb > $@ testu.c: $(srcdir)/test.rb $(srcdir)/testconvu.rb ruby -Ke $(srcdir)/testconvu.rb $(srcdir)/test.rb > $@ win32/testc.c: $(srcdir)/test.rb $(srcdir)/testconv.rb ruby -Ke $(srcdir)/testconv.rb -win < $(srcdir)/test.rb | nkf -cs > $@ ## END OF FILE ================================================ FILE: src/Onigmo/Makefile.in ================================================ # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program 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. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ TESTS = testc$(EXEEXT) testp$(EXEEXT) testcu$(EXEEXT) check_PROGRAMS = testc$(EXEEXT) testp$(EXEEXT) testcu$(EXEEXT) subdir = . DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/config.h.in $(srcdir)/onig-config.in \ $(top_srcdir)/configure AUTHORS COPYING INSTALL compile \ config.guess config.sub depcomp install-sh ltmain.sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = onig-config CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libonig_la_LIBADD = am_libonig_la_OBJECTS = regerror.lo regparse.lo regext.lo regcomp.lo \ regexec.lo reggnu.lo regenc.lo regsyntax.lo regtrav.lo \ regversion.lo st.lo regposix.lo regposerr.lo unicode.lo \ ascii.lo utf8.lo utf16_be.lo utf16_le.lo utf32_be.lo \ utf32_le.lo euc_jp.lo sjis.lo cp932.lo iso8859_1.lo \ iso8859_2.lo iso8859_3.lo iso8859_4.lo iso8859_5.lo \ iso8859_6.lo iso8859_7.lo iso8859_8.lo iso8859_9.lo \ iso8859_10.lo iso8859_11.lo iso8859_13.lo iso8859_14.lo \ iso8859_15.lo iso8859_16.lo euc_tw.lo euc_kr.lo big5.lo \ gb18030.lo koi8_r.lo cp1251.lo libonig_la_OBJECTS = $(am_libonig_la_OBJECTS) libonig_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libonig_la_LDFLAGS) $(LDFLAGS) -o $@ am_testc_OBJECTS = testc.$(OBJEXT) testc_OBJECTS = $(am_testc_OBJECTS) testc_DEPENDENCIES = libonig.la am_testcu_OBJECTS = testu.$(OBJEXT) testcu_OBJECTS = $(am_testcu_OBJECTS) testcu_DEPENDENCIES = libonig.la am_testp_OBJECTS = testp-testc.$(OBJEXT) testp_OBJECTS = $(am_testp_OBJECTS) testp_DEPENDENCIES = libonig.la testp_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(testp_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SCRIPTS = $(bin_SCRIPTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libonig_la_SOURCES) $(testc_SOURCES) $(testcu_SOURCES) \ $(testp_SOURCES) DIST_SOURCES = $(libonig_la_SOURCES) $(testc_SOURCES) \ $(testcu_SOURCES) $(testp_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive DATA = $(pkgconfig_DATA) HEADERS = $(include_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags am__tty_colors = \ red=; grn=; lgn=; blu=; std= DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d "$(distdir)" \ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr "$(distdir)"; }; } am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION = @LTVERSION@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RUBYDIR = @RUBYDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATISTICS = @STATISTICS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ encdir = $(top_srcdir)/enc sampledir = $(top_srcdir)/sample libname = libonig.la ACLOCAL_AMFLAGS = -I m4 #AM_CFLAGS = -DNOT_RUBY AM_CFLAGS = INCLUDES = -I$(top_srcdir) -I$(includedir) SUBDIRS = . sample include_HEADERS = oniguruma.h oniggnu.h onigposix.h lib_LTLIBRARIES = $(libname) libonig_la_SOURCES = regint.h regparse.h regenc.h st.h \ regerror.c regparse.c regext.c regcomp.c regexec.c reggnu.c \ regenc.c regsyntax.c regtrav.c regversion.c st.c \ regposix.c regposerr.c \ $(encdir)/unicode.c $(encdir)/ascii.c $(encdir)/utf8.c \ $(encdir)/utf16_be.c $(encdir)/utf16_le.c \ $(encdir)/utf32_be.c $(encdir)/utf32_le.c \ $(encdir)/unicode/casefold.h $(encdir)/unicode/name2ctype.h \ $(encdir)/euc_jp.c $(encdir)/sjis.c $(encdir)/cp932.c \ $(encdir)/iso8859_1.c \ $(encdir)/iso8859_2.c $(encdir)/iso8859_3.c \ $(encdir)/iso8859_4.c $(encdir)/iso8859_5.c \ $(encdir)/iso8859_6.c $(encdir)/iso8859_7.c \ $(encdir)/iso8859_8.c $(encdir)/iso8859_9.c \ $(encdir)/iso8859_10.c $(encdir)/iso8859_11.c \ $(encdir)/iso8859_13.c $(encdir)/iso8859_14.c \ $(encdir)/iso8859_15.c $(encdir)/iso8859_16.c \ $(encdir)/euc_tw.c $(encdir)/euc_kr.c $(encdir)/big5.c \ $(encdir)/gb18030.c $(encdir)/koi8_r.c $(encdir)/cp1251.c libonig_la_LDFLAGS = -version-info $(LTVERSION) EXTRA_DIST = .gitignore oniguruma.pc.in HISTORY README.ja index.html \ index_ja.html doc/API doc/API.ja doc/RE doc/RE.ja doc/FAQ doc/FAQ.ja \ doc/UnicodeProps.txt \ tool/.gitignore tool/CaseFolding.py tool/convert-name2ctype.sh \ tool/enc-unicode.rb \ win32/Makefile win32/config.h win32/testc.c \ win32/makedef.py win32/onig.rc \ $(encdir)/koi8.c $(encdir)/mktable.c \ $(sampledir)/encode.c $(sampledir)/listcap.c $(sampledir)/names.c \ $(sampledir)/posix.c $(sampledir)/simple.c $(sampledir)/sql.c \ $(sampledir)/syntax.c $(sampledir)/crnl.c \ test.rb testconv.rb testconvu.rb \ onig.py testpy.py bin_SCRIPTS = onig-config do_subst = sed \ -e 's,[@]datadir[@],$(datadir),g' \ -e 's,[@]datarootdir[@],$(datarootdir),g' \ -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ -e 's,[@]prefix[@],$(prefix),g' \ -e 's,[@]exec_prefix[@],$(exec_prefix),g' \ -e 's,[@]libdir[@],$(libdir),g' \ -e 's,[@]includedir[@],$(includedir),g' pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = oniguruma.pc testc_SOURCES = testc.c testc_LDADD = libonig.la testp_SOURCES = testc.c testp_LDADD = libonig.la testp_CFLAGS = -DPOSIX_TEST testcu_SOURCES = testu.c testcu_LDADD = libonig.la all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 onig-config: $(top_builddir)/config.status $(srcdir)/onig-config.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libonig.la: $(libonig_la_OBJECTS) $(libonig_la_DEPENDENCIES) $(libonig_la_LINK) -rpath $(libdir) $(libonig_la_OBJECTS) $(libonig_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list testc$(EXEEXT): $(testc_OBJECTS) $(testc_DEPENDENCIES) @rm -f testc$(EXEEXT) $(LINK) $(testc_OBJECTS) $(testc_LDADD) $(LIBS) testcu$(EXEEXT): $(testcu_OBJECTS) $(testcu_DEPENDENCIES) @rm -f testcu$(EXEEXT) $(LINK) $(testcu_OBJECTS) $(testcu_LDADD) $(LIBS) testp$(EXEEXT): $(testp_OBJECTS) $(testp_DEPENDENCIES) @rm -f testp$(EXEEXT) $(testp_LINK) $(testp_OBJECTS) $(testp_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ascii.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/big5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp1251.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp932.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/euc_jp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/euc_kr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/euc_tw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gb18030.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_10.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_13.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_14.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_15.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_3.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_7.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iso8859_9.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/koi8_r.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regcomp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regenc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regerror.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regexec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reggnu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regparse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regposerr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regposix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regsyntax.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regtrav.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regversion.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sjis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/st.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testp-testc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unicode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf16_be.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf16_le.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf32_be.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf32_le.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf8.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< unicode.lo: $(encdir)/unicode.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unicode.lo -MD -MP -MF $(DEPDIR)/unicode.Tpo -c -o unicode.lo `test -f '$(encdir)/unicode.c' || echo '$(srcdir)/'`$(encdir)/unicode.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unicode.Tpo $(DEPDIR)/unicode.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/unicode.c' object='unicode.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unicode.lo `test -f '$(encdir)/unicode.c' || echo '$(srcdir)/'`$(encdir)/unicode.c ascii.lo: $(encdir)/ascii.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ascii.lo -MD -MP -MF $(DEPDIR)/ascii.Tpo -c -o ascii.lo `test -f '$(encdir)/ascii.c' || echo '$(srcdir)/'`$(encdir)/ascii.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ascii.Tpo $(DEPDIR)/ascii.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/ascii.c' object='ascii.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ascii.lo `test -f '$(encdir)/ascii.c' || echo '$(srcdir)/'`$(encdir)/ascii.c utf8.lo: $(encdir)/utf8.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utf8.lo -MD -MP -MF $(DEPDIR)/utf8.Tpo -c -o utf8.lo `test -f '$(encdir)/utf8.c' || echo '$(srcdir)/'`$(encdir)/utf8.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utf8.Tpo $(DEPDIR)/utf8.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/utf8.c' object='utf8.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utf8.lo `test -f '$(encdir)/utf8.c' || echo '$(srcdir)/'`$(encdir)/utf8.c utf16_be.lo: $(encdir)/utf16_be.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utf16_be.lo -MD -MP -MF $(DEPDIR)/utf16_be.Tpo -c -o utf16_be.lo `test -f '$(encdir)/utf16_be.c' || echo '$(srcdir)/'`$(encdir)/utf16_be.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utf16_be.Tpo $(DEPDIR)/utf16_be.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/utf16_be.c' object='utf16_be.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utf16_be.lo `test -f '$(encdir)/utf16_be.c' || echo '$(srcdir)/'`$(encdir)/utf16_be.c utf16_le.lo: $(encdir)/utf16_le.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utf16_le.lo -MD -MP -MF $(DEPDIR)/utf16_le.Tpo -c -o utf16_le.lo `test -f '$(encdir)/utf16_le.c' || echo '$(srcdir)/'`$(encdir)/utf16_le.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utf16_le.Tpo $(DEPDIR)/utf16_le.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/utf16_le.c' object='utf16_le.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utf16_le.lo `test -f '$(encdir)/utf16_le.c' || echo '$(srcdir)/'`$(encdir)/utf16_le.c utf32_be.lo: $(encdir)/utf32_be.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utf32_be.lo -MD -MP -MF $(DEPDIR)/utf32_be.Tpo -c -o utf32_be.lo `test -f '$(encdir)/utf32_be.c' || echo '$(srcdir)/'`$(encdir)/utf32_be.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utf32_be.Tpo $(DEPDIR)/utf32_be.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/utf32_be.c' object='utf32_be.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utf32_be.lo `test -f '$(encdir)/utf32_be.c' || echo '$(srcdir)/'`$(encdir)/utf32_be.c utf32_le.lo: $(encdir)/utf32_le.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utf32_le.lo -MD -MP -MF $(DEPDIR)/utf32_le.Tpo -c -o utf32_le.lo `test -f '$(encdir)/utf32_le.c' || echo '$(srcdir)/'`$(encdir)/utf32_le.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utf32_le.Tpo $(DEPDIR)/utf32_le.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/utf32_le.c' object='utf32_le.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utf32_le.lo `test -f '$(encdir)/utf32_le.c' || echo '$(srcdir)/'`$(encdir)/utf32_le.c euc_jp.lo: $(encdir)/euc_jp.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT euc_jp.lo -MD -MP -MF $(DEPDIR)/euc_jp.Tpo -c -o euc_jp.lo `test -f '$(encdir)/euc_jp.c' || echo '$(srcdir)/'`$(encdir)/euc_jp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/euc_jp.Tpo $(DEPDIR)/euc_jp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/euc_jp.c' object='euc_jp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o euc_jp.lo `test -f '$(encdir)/euc_jp.c' || echo '$(srcdir)/'`$(encdir)/euc_jp.c sjis.lo: $(encdir)/sjis.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sjis.lo -MD -MP -MF $(DEPDIR)/sjis.Tpo -c -o sjis.lo `test -f '$(encdir)/sjis.c' || echo '$(srcdir)/'`$(encdir)/sjis.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sjis.Tpo $(DEPDIR)/sjis.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/sjis.c' object='sjis.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sjis.lo `test -f '$(encdir)/sjis.c' || echo '$(srcdir)/'`$(encdir)/sjis.c cp932.lo: $(encdir)/cp932.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cp932.lo -MD -MP -MF $(DEPDIR)/cp932.Tpo -c -o cp932.lo `test -f '$(encdir)/cp932.c' || echo '$(srcdir)/'`$(encdir)/cp932.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cp932.Tpo $(DEPDIR)/cp932.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/cp932.c' object='cp932.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cp932.lo `test -f '$(encdir)/cp932.c' || echo '$(srcdir)/'`$(encdir)/cp932.c iso8859_1.lo: $(encdir)/iso8859_1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_1.lo -MD -MP -MF $(DEPDIR)/iso8859_1.Tpo -c -o iso8859_1.lo `test -f '$(encdir)/iso8859_1.c' || echo '$(srcdir)/'`$(encdir)/iso8859_1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_1.Tpo $(DEPDIR)/iso8859_1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_1.c' object='iso8859_1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_1.lo `test -f '$(encdir)/iso8859_1.c' || echo '$(srcdir)/'`$(encdir)/iso8859_1.c iso8859_2.lo: $(encdir)/iso8859_2.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_2.lo -MD -MP -MF $(DEPDIR)/iso8859_2.Tpo -c -o iso8859_2.lo `test -f '$(encdir)/iso8859_2.c' || echo '$(srcdir)/'`$(encdir)/iso8859_2.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_2.Tpo $(DEPDIR)/iso8859_2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_2.c' object='iso8859_2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_2.lo `test -f '$(encdir)/iso8859_2.c' || echo '$(srcdir)/'`$(encdir)/iso8859_2.c iso8859_3.lo: $(encdir)/iso8859_3.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_3.lo -MD -MP -MF $(DEPDIR)/iso8859_3.Tpo -c -o iso8859_3.lo `test -f '$(encdir)/iso8859_3.c' || echo '$(srcdir)/'`$(encdir)/iso8859_3.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_3.Tpo $(DEPDIR)/iso8859_3.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_3.c' object='iso8859_3.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_3.lo `test -f '$(encdir)/iso8859_3.c' || echo '$(srcdir)/'`$(encdir)/iso8859_3.c iso8859_4.lo: $(encdir)/iso8859_4.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_4.lo -MD -MP -MF $(DEPDIR)/iso8859_4.Tpo -c -o iso8859_4.lo `test -f '$(encdir)/iso8859_4.c' || echo '$(srcdir)/'`$(encdir)/iso8859_4.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_4.Tpo $(DEPDIR)/iso8859_4.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_4.c' object='iso8859_4.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_4.lo `test -f '$(encdir)/iso8859_4.c' || echo '$(srcdir)/'`$(encdir)/iso8859_4.c iso8859_5.lo: $(encdir)/iso8859_5.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_5.lo -MD -MP -MF $(DEPDIR)/iso8859_5.Tpo -c -o iso8859_5.lo `test -f '$(encdir)/iso8859_5.c' || echo '$(srcdir)/'`$(encdir)/iso8859_5.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_5.Tpo $(DEPDIR)/iso8859_5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_5.c' object='iso8859_5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_5.lo `test -f '$(encdir)/iso8859_5.c' || echo '$(srcdir)/'`$(encdir)/iso8859_5.c iso8859_6.lo: $(encdir)/iso8859_6.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_6.lo -MD -MP -MF $(DEPDIR)/iso8859_6.Tpo -c -o iso8859_6.lo `test -f '$(encdir)/iso8859_6.c' || echo '$(srcdir)/'`$(encdir)/iso8859_6.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_6.Tpo $(DEPDIR)/iso8859_6.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_6.c' object='iso8859_6.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_6.lo `test -f '$(encdir)/iso8859_6.c' || echo '$(srcdir)/'`$(encdir)/iso8859_6.c iso8859_7.lo: $(encdir)/iso8859_7.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_7.lo -MD -MP -MF $(DEPDIR)/iso8859_7.Tpo -c -o iso8859_7.lo `test -f '$(encdir)/iso8859_7.c' || echo '$(srcdir)/'`$(encdir)/iso8859_7.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_7.Tpo $(DEPDIR)/iso8859_7.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_7.c' object='iso8859_7.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_7.lo `test -f '$(encdir)/iso8859_7.c' || echo '$(srcdir)/'`$(encdir)/iso8859_7.c iso8859_8.lo: $(encdir)/iso8859_8.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_8.lo -MD -MP -MF $(DEPDIR)/iso8859_8.Tpo -c -o iso8859_8.lo `test -f '$(encdir)/iso8859_8.c' || echo '$(srcdir)/'`$(encdir)/iso8859_8.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_8.Tpo $(DEPDIR)/iso8859_8.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_8.c' object='iso8859_8.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_8.lo `test -f '$(encdir)/iso8859_8.c' || echo '$(srcdir)/'`$(encdir)/iso8859_8.c iso8859_9.lo: $(encdir)/iso8859_9.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_9.lo -MD -MP -MF $(DEPDIR)/iso8859_9.Tpo -c -o iso8859_9.lo `test -f '$(encdir)/iso8859_9.c' || echo '$(srcdir)/'`$(encdir)/iso8859_9.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_9.Tpo $(DEPDIR)/iso8859_9.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_9.c' object='iso8859_9.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_9.lo `test -f '$(encdir)/iso8859_9.c' || echo '$(srcdir)/'`$(encdir)/iso8859_9.c iso8859_10.lo: $(encdir)/iso8859_10.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_10.lo -MD -MP -MF $(DEPDIR)/iso8859_10.Tpo -c -o iso8859_10.lo `test -f '$(encdir)/iso8859_10.c' || echo '$(srcdir)/'`$(encdir)/iso8859_10.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_10.Tpo $(DEPDIR)/iso8859_10.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_10.c' object='iso8859_10.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_10.lo `test -f '$(encdir)/iso8859_10.c' || echo '$(srcdir)/'`$(encdir)/iso8859_10.c iso8859_11.lo: $(encdir)/iso8859_11.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_11.lo -MD -MP -MF $(DEPDIR)/iso8859_11.Tpo -c -o iso8859_11.lo `test -f '$(encdir)/iso8859_11.c' || echo '$(srcdir)/'`$(encdir)/iso8859_11.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_11.Tpo $(DEPDIR)/iso8859_11.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_11.c' object='iso8859_11.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_11.lo `test -f '$(encdir)/iso8859_11.c' || echo '$(srcdir)/'`$(encdir)/iso8859_11.c iso8859_13.lo: $(encdir)/iso8859_13.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_13.lo -MD -MP -MF $(DEPDIR)/iso8859_13.Tpo -c -o iso8859_13.lo `test -f '$(encdir)/iso8859_13.c' || echo '$(srcdir)/'`$(encdir)/iso8859_13.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_13.Tpo $(DEPDIR)/iso8859_13.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_13.c' object='iso8859_13.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_13.lo `test -f '$(encdir)/iso8859_13.c' || echo '$(srcdir)/'`$(encdir)/iso8859_13.c iso8859_14.lo: $(encdir)/iso8859_14.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_14.lo -MD -MP -MF $(DEPDIR)/iso8859_14.Tpo -c -o iso8859_14.lo `test -f '$(encdir)/iso8859_14.c' || echo '$(srcdir)/'`$(encdir)/iso8859_14.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_14.Tpo $(DEPDIR)/iso8859_14.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_14.c' object='iso8859_14.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_14.lo `test -f '$(encdir)/iso8859_14.c' || echo '$(srcdir)/'`$(encdir)/iso8859_14.c iso8859_15.lo: $(encdir)/iso8859_15.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_15.lo -MD -MP -MF $(DEPDIR)/iso8859_15.Tpo -c -o iso8859_15.lo `test -f '$(encdir)/iso8859_15.c' || echo '$(srcdir)/'`$(encdir)/iso8859_15.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_15.Tpo $(DEPDIR)/iso8859_15.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_15.c' object='iso8859_15.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_15.lo `test -f '$(encdir)/iso8859_15.c' || echo '$(srcdir)/'`$(encdir)/iso8859_15.c iso8859_16.lo: $(encdir)/iso8859_16.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iso8859_16.lo -MD -MP -MF $(DEPDIR)/iso8859_16.Tpo -c -o iso8859_16.lo `test -f '$(encdir)/iso8859_16.c' || echo '$(srcdir)/'`$(encdir)/iso8859_16.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iso8859_16.Tpo $(DEPDIR)/iso8859_16.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/iso8859_16.c' object='iso8859_16.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iso8859_16.lo `test -f '$(encdir)/iso8859_16.c' || echo '$(srcdir)/'`$(encdir)/iso8859_16.c euc_tw.lo: $(encdir)/euc_tw.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT euc_tw.lo -MD -MP -MF $(DEPDIR)/euc_tw.Tpo -c -o euc_tw.lo `test -f '$(encdir)/euc_tw.c' || echo '$(srcdir)/'`$(encdir)/euc_tw.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/euc_tw.Tpo $(DEPDIR)/euc_tw.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/euc_tw.c' object='euc_tw.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o euc_tw.lo `test -f '$(encdir)/euc_tw.c' || echo '$(srcdir)/'`$(encdir)/euc_tw.c euc_kr.lo: $(encdir)/euc_kr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT euc_kr.lo -MD -MP -MF $(DEPDIR)/euc_kr.Tpo -c -o euc_kr.lo `test -f '$(encdir)/euc_kr.c' || echo '$(srcdir)/'`$(encdir)/euc_kr.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/euc_kr.Tpo $(DEPDIR)/euc_kr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/euc_kr.c' object='euc_kr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o euc_kr.lo `test -f '$(encdir)/euc_kr.c' || echo '$(srcdir)/'`$(encdir)/euc_kr.c big5.lo: $(encdir)/big5.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT big5.lo -MD -MP -MF $(DEPDIR)/big5.Tpo -c -o big5.lo `test -f '$(encdir)/big5.c' || echo '$(srcdir)/'`$(encdir)/big5.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/big5.Tpo $(DEPDIR)/big5.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/big5.c' object='big5.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o big5.lo `test -f '$(encdir)/big5.c' || echo '$(srcdir)/'`$(encdir)/big5.c gb18030.lo: $(encdir)/gb18030.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gb18030.lo -MD -MP -MF $(DEPDIR)/gb18030.Tpo -c -o gb18030.lo `test -f '$(encdir)/gb18030.c' || echo '$(srcdir)/'`$(encdir)/gb18030.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gb18030.Tpo $(DEPDIR)/gb18030.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/gb18030.c' object='gb18030.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gb18030.lo `test -f '$(encdir)/gb18030.c' || echo '$(srcdir)/'`$(encdir)/gb18030.c koi8_r.lo: $(encdir)/koi8_r.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT koi8_r.lo -MD -MP -MF $(DEPDIR)/koi8_r.Tpo -c -o koi8_r.lo `test -f '$(encdir)/koi8_r.c' || echo '$(srcdir)/'`$(encdir)/koi8_r.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/koi8_r.Tpo $(DEPDIR)/koi8_r.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/koi8_r.c' object='koi8_r.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o koi8_r.lo `test -f '$(encdir)/koi8_r.c' || echo '$(srcdir)/'`$(encdir)/koi8_r.c cp1251.lo: $(encdir)/cp1251.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cp1251.lo -MD -MP -MF $(DEPDIR)/cp1251.Tpo -c -o cp1251.lo `test -f '$(encdir)/cp1251.c' || echo '$(srcdir)/'`$(encdir)/cp1251.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cp1251.Tpo $(DEPDIR)/cp1251.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(encdir)/cp1251.c' object='cp1251.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cp1251.lo `test -f '$(encdir)/cp1251.c' || echo '$(srcdir)/'`$(encdir)/cp1251.c testp-testc.o: testc.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testp_CFLAGS) $(CFLAGS) -MT testp-testc.o -MD -MP -MF $(DEPDIR)/testp-testc.Tpo -c -o testp-testc.o `test -f 'testc.c' || echo '$(srcdir)/'`testc.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/testp-testc.Tpo $(DEPDIR)/testp-testc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testc.c' object='testp-testc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testp_CFLAGS) $(CFLAGS) -c -o testp-testc.o `test -f 'testc.c' || echo '$(srcdir)/'`testc.c testp-testc.obj: testc.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testp_CFLAGS) $(CFLAGS) -MT testp-testc.obj -MD -MP -MF $(DEPDIR)/testp-testc.Tpo -c -o testp-testc.obj `if test -f 'testc.c'; then $(CYGPATH_W) 'testc.c'; else $(CYGPATH_W) '$(srcdir)/testc.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/testp-testc.Tpo $(DEPDIR)/testp-testc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testc.c' object='testp-testc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(testp_CFLAGS) $(CFLAGS) -c -o testp-testc.obj `if test -f 'testc.c'; then $(CYGPATH_W) 'testc.c'; else $(CYGPATH_W) '$(srcdir)/testc.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ done uninstall-includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(includedir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ echo "$$grn$$dashes"; \ else \ echo "$$red$$dashes"; \ fi; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ echo "$$dashes$$std"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @$(am__cd) '$(distuninstallcheck_dir)' \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(DATA) $(HEADERS) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-includeHEADERS install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binSCRIPTS install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binSCRIPTS uninstall-includeHEADERS \ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check-am \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ dist-gzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags distcleancheck \ distdir distuninstallcheck dvi dvi-am html html-am info \ info-am install install-am install-binSCRIPTS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am \ install-includeHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-pkgconfigDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-binSCRIPTS uninstall-includeHEADERS \ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA onig-config: onig-config.in oniguruma.pc: $(srcdir)/oniguruma.pc.in Makefile $(do_subst) < $(<) > $(@) dll: $(CXX) -shared -Wl,--output-def,libonig.def -o libonig.dll *.o \ $(LIBS) strip libonig.dll # Ruby TEST rtest: $(RUBYDIR)/ruby -w -Ke $(srcdir)/test.rb # character-types-table source generator mktable: $(encdir)/mktable.c $(srcdir)/regenc.h $(CC) -I$(top_srcdir) -o mktable $(encdir)/mktable.c atest: testc testp testcu @echo "[Oniguruma API, ASCII/EUC-JP check]" @$(top_builddir)/testc | grep RESULT @echo "[POSIX API, ASCII/EUC-JP check]" @$(top_builddir)/testp | grep RESULT @echo "[Oniguruma API, UTF-16 check]" @$(top_builddir)/testcu | grep RESULT testc.c: $(srcdir)/test.rb $(srcdir)/testconv.rb ruby -Ke $(srcdir)/testconv.rb < $(srcdir)/test.rb > $@ testu.c: $(srcdir)/test.rb $(srcdir)/testconvu.rb ruby -Ke $(srcdir)/testconvu.rb $(srcdir)/test.rb > $@ win32/testc.c: $(srcdir)/test.rb $(srcdir)/testconv.rb ruby -Ke $(srcdir)/testconv.rb -win < $(srcdir)/test.rb | nkf -cs > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ================================================ FILE: src/Onigmo/README ================================================ README 2013/03/21 Onigmo (Oniguruma-mod) -- (C) K.Takata https://github.com/k-takata/Onigmo Onigmo is a regular expressions library forked from Oniguruma. Some of new features introduced in Perl 5.10+ can be used. Some patches are merged from Ruby 2.0.0. Main New features: Regular Expressions (depends on the syntax): \K, \R, \X, (?(cond)yes|no) (?adlu), \g{name}, \g{n}, (?&name), (?n), (?R), (?0) (?P...), (?P=name), (?P>name) API: onig_search_gpos (for Perl-compatible \G) Encoding: CP932 Syntax: Python New Source Files: enc/cp932.c CP932 encoding. enc/unicode/casefold.h Unicode case folding data. enc/unicode/name2ctype.h Unicode properties data. onig.py onig.dll/libonig.so loader. testpy.py test program. tool/CaseFolding.py generates casefold.h. tool/convert-name2ctype.sh converts name2ctype.kwd to name2ctypes.h. tool/enc-unicode.rb generates name2ctype.kwd. win32/makedef.py creates onig.def. win32/onig.rc resource file for onig.dll. ToDo: * Reduce the size of Unicode Character Data. * (?|...) * Improve (?(cond)yes|no). (support look-ahead/behind assertions.) Oniguruma's README follows: ====================================================================== README 2007/05/31 Oniguruma ---- (C) K.Kosako http://www.geocities.jp/kosako3/oniguruma/ Oniguruma is a regular expressions library. The characteristics of this library is that different character encoding for every regular expression object can be specified. Supported character encodings: ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, EUC-JP, EUC-TW, EUC-KR, EUC-CN, Shift_JIS, Big5, GB18030, KOI8-R, CP1251, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16 * GB18030: contributed by KUBO Takehiro * CP1251: contributed by Byte ------------------------------------------------------------ License BSD license. Install Case 1: Unix and Cygwin platform 1. ./configure 2. make 3. make install * uninstall make uninstall * test (ASCII/EUC-JP) make atest * configuration check onig-config --cflags onig-config --libs onig-config --prefix onig-config --exec-prefix Case 2: Win32 platform (VC++) 1. copy win32\Makefile Makefile 2. copy win32\config.h config.h 3. nmake onig_s.lib: static link library onig.dll: dynamic link library * test (ASCII/Shift_JIS) 4. copy win32\testc.c testc.c 5. nmake ctest Regular Expressions See doc/RE (or doc/RE.ja for Japanese). Usage Include oniguruma.h in your program. (Oniguruma API) See doc/API for Oniguruma API. If you want to disable UChar type (== unsigned char) definition in oniguruma.h, define ONIG_ESCAPE_UCHAR_COLLISION and then include oniguruma.h. If you want to disable regex_t type definition in oniguruma.h, define ONIG_ESCAPE_REGEX_T_COLLISION and then include oniguruma.h. Example of the compiling/linking command line in Unix or Cygwin, (prefix == /usr/local case) cc sample.c -L/usr/local/lib -lonig If you want to use static link library(onig_s.lib) in Win32, add option -DONIG_EXTERN=extern to C compiler. Sample Programs sample/simple.c example of the minimum (Oniguruma API) sample/names.c example of the named group callback. sample/encode.c example of some encodings. sample/listcap.c example of the capture history. sample/posix.c POSIX API sample. sample/sql.c example of the variable meta characters. (SQL-like pattern matching) Test Programs sample/syntax.c Perl, Java and ASIS syntax test. sample/crnl.c --enable-crnl-as-line-terminator test Source Files oniguruma.h Oniguruma API header file. (public) onig-config.in configuration check program template. regenc.h character encodings framework header file. regint.h internal definitions regparse.h internal definitions for regparse.c and regcomp.c regcomp.c compiling and optimization functions regenc.c character encodings framework. regerror.c error message function regext.c extended API functions. (deluxe version API) regexec.c search and match functions regparse.c parsing functions. regsyntax.c pattern syntax functions and built-in syntax definitions. regtrav.c capture history tree data traverse functions. regversion.c version info function. st.h hash table functions header file st.c hash table functions oniggnu.h GNU regex API header file. (public) reggnu.c GNU regex API functions onigposix.h POSIX API header file. (public) regposerr.c POSIX error message function. regposix.c POSIX API functions. enc/mktable.c character type table generator. enc/ascii.c ASCII encoding. enc/euc_jp.c EUC-JP encoding. enc/euc_tw.c EUC-TW encoding. enc/euc_kr.c EUC-KR, EUC-CN encoding. enc/sjis.c Shift_JIS encoding. enc/big5.c Big5 encoding. enc/gb18030.c GB18030 encoding. enc/koi8.c KOI8 encoding. enc/koi8_r.c KOI8-R encoding. enc/cp1251.c CP1251 encoding. enc/iso8859_1.c ISO-8859-1 encoding. (Latin-1) enc/iso8859_2.c ISO-8859-2 encoding. (Latin-2) enc/iso8859_3.c ISO-8859-3 encoding. (Latin-3) enc/iso8859_4.c ISO-8859-4 encoding. (Latin-4) enc/iso8859_5.c ISO-8859-5 encoding. (Cyrillic) enc/iso8859_6.c ISO-8859-6 encoding. (Arabic) enc/iso8859_7.c ISO-8859-7 encoding. (Greek) enc/iso8859_8.c ISO-8859-8 encoding. (Hebrew) enc/iso8859_9.c ISO-8859-9 encoding. (Latin-5 or Turkish) enc/iso8859_10.c ISO-8859-10 encoding. (Latin-6 or Nordic) enc/iso8859_11.c ISO-8859-11 encoding. (Thai) enc/iso8859_13.c ISO-8859-13 encoding. (Latin-7 or Baltic Rim) enc/iso8859_14.c ISO-8859-14 encoding. (Latin-8 or Celtic) enc/iso8859_15.c ISO-8859-15 encoding. (Latin-9 or West European with Euro) enc/iso8859_16.c ISO-8859-16 encoding. (Latin-10 or South-Eastern European with Euro) enc/utf8.c UTF-8 encoding. enc/utf16_be.c UTF-16BE encoding. enc/utf16_le.c UTF-16LE encoding. enc/utf32_be.c UTF-32BE encoding. enc/utf32_le.c UTF-32LE encoding. enc/unicode.c Unicode information data. win32/Makefile Makefile for Win32 (VC++) win32/config.h config.h for Win32 ToDo ? case fold flag: Katakana <-> Hiragana. ? add ONIG_OPTION_NOTBOS/NOTEOS. (\A, \z, \Z) ?? \X (== \PM\pM*) ?? implement syntax behavior ONIG_SYN_CONTEXT_INDEP_ANCHORS. ?? transmission stopper. (return ONIG_STOP from match_at()) and I'm thankful to Akinori MUSHA. Mail Address: K.Kosako ================================================ FILE: src/Onigmo/README.ja ================================================ README.ja 2013/03/21 鬼雲 (鬼車改) -- (C) K.Takata https://github.com/k-takata/Onigmo 鬼雲は、鬼車から派生した正規表現ライブラリである。 Perl 5.10以降で新たに導入された正規表現の一部が使用可能になっている。 一部のパッチは Ruby 2.0.0 からマージしている。 主な新機能: 正規表現 (文法依存): \K, \R, \X, (?(cond)yes|no) (?adlu), \g{name}, \g{n}, (?&name), (?n), (?R), (?0) (?P...), (?P=name), (?P>name) API: onig_search_gpos (Perl互換の \G 用) エンコーディング: CP932 文法: Python 新規ソースファイル: enc/cp932.c CP932 エンコーディング enc/unicode/casefold.h Unicodeケースフォールドデータ enc/unicode/name2ctype.h Unicodeプロパティデータ onig.py onig.dll/libonig.so ローダ testpy.py テストプログラム tool/CaseFolding.py casefold.hを生成 tool/convert-name2ctype.sh name2ctype.kwdをname2ctypes.hに変換 tool/enc-unicode.rb name2ctype.kwdを生成 win32/makedef.py onig.defを作成 win32/onig.rc onig.dll用リソースファイル ToDo: * Unicode Character Data のサイズ削減。 * (?|...) * (?(cond)yes|no) の改善。(先読み・戻り読みの対応) 以下、鬼車の README.ja: ====================================================================== README.ja 2007/05/31 鬼車 ---- (C) K.Kosako http://www.geocities.jp/kosako3/oniguruma/ 鬼車は正規表現ライブラリである。 このライブラリの特長は、それぞれの正規表現オブジェクトごとに 文字エンコーディングを指定できることである。 サポートしている文字エンコーディング: ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, EUC-JP, EUC-TW, EUC-KR, EUC-CN, Shift_JIS, Big5, GB18030, KOI8-R, CP1251, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16 * GB18030: 久保健洋氏提供 * CP1251: Byte氏提供 ------------------------------------------------------------ ライセンス BSDライセンスに従う。 インストール ケース1: UnixとCygwin環境 1. ./configure 2. make 3. make install アンインストール make uninstall 動作テスト (ASCII/EUC-JP) make atest 構成確認 onig-config --cflags onig-config --libs onig-config --prefix onig-config --exec-prefix ケース2: Win32(VC++)環境 1. copy win32\Makefile Makefile 2. copy win32\config.h config.h 3. nmake onig_s.lib: static link library onig.dll: dynamic link library * 動作テスト (ASCII/Shift_JIS) 4. copy win32\testc.c testc.c 5. nmake ctest 正規表現 doc/RE.jaを参照 使用方法 使用するプログラムで、oniguruma.hをインクルードする(Oniguruma APIの場合)。 Oniguruma APIについては、doc/API.jaを参照。 oniguruma.hで定義されている型名UChar(== unsigned char)を無効にしたい場合 には、ONIG_ESCAPE_UCHAR_COLLISIONをdefineしてからoniguruma.hをインクルード すること。このときにはUCharは定義されず、OnigUCharという名前の定義のみが 有効になる。 oniguruma.hで定義されている型名regex_tを無効にしたい場合には、 ONIG_ESCAPE_REGEX_T_COLLISIONをdefineしてからoniguruma.hをインクルード すること。このときにはregex_tは定義されず、OnigRegexType, OnigRegexという 名前の定義のみが有効になる。 Unix/Cygwin上でコンパイル、リンクする場合の例: (prefixが/usr/localのとき) cc sample.c -L/usr/local/lib -lonig GNU libtoolを使用しているので、プラットフォームが共有ライブラリをサポートして いれば、使用できるようになっている。 静的ライブラリと共有ライブラリのどちらを使用するかを指定する方法、実行時点での 環境設定方法については、自分で調べて下さい。 Win32でスタティックリンクライブラリ(onig_s.lib)をリンクする場合には、 コンパイルするときに -DONIG_EXTERN=extern をコンパイル引数に追加すること。 使用例プログラム sample/simple.c 最小例 (Oniguruma API) sample/names.c 名前付きグループコールバック使用例 sample/encode.c 幾つかの文字エンコーディング使用例 sample/listcap.c 捕獲履歴機能の使用例 sample/posix.c POSIX API使用例 sample/sql.c 可変メタ文字機能使用例 (SQL-like パターン) テストプログラム sample/syntax.c Perl、Java、ASIS文法のテスト sample/crnl.c --enable-crnl-as-line-terminator テスト ソースファイル oniguruma.h 鬼車APIヘッダ (公開) onig-config.in onig-configプログラム テンプレート regenc.h 文字エンコーディング枠組みヘッダ regint.h 内部宣言 regparse.h regparse.cとregcomp.cのための内部宣言 regcomp.c コンパイル、最適化関数 regenc.c 文字エンコーディング枠組み regerror.c エラーメッセージ関数 regext.c 拡張API関数 regexec.c 検索、照合関数 regparse.c 正規表現パターン解析関数 regsyntax.c 正規表現パターン文法関数、組込み文法定義 regtrav.c 捕獲履歴木巡回関数 regversion.c 版情報関数 st.h ハッシュテーブル関数宣言 st.c ハッシュテーブル関数 oniggnu.h GNU regex APIヘッダ (公開) reggnu.c GNU regex API関数 onigposix.h POSIX APIヘッダ (公開) regposerr.c POSIX APIエラーメッセージ関数 regposix.c POSIX API関数 enc/mktable.c 文字タイプテーブル生成プログラム enc/ascii.c ASCII エンコーディング enc/euc_jp.c EUC-JP エンコーディング enc/euc_tw.c EUC-TW エンコーディング enc/euc_kr.c EUC-KR, EUC-CN エンコーディング enc/sjis.c Shift_JIS エンコーディング enc/big5.c Big5 エンコーディング enc/gb18030.c GB18030 エンコーディング enc/koi8.c KOI8 エンコーディング enc/koi8_r.c KOI8-R エンコーディング enc/cp1251.c CP1251 エンコーディング enc/iso8859_1.c ISO-8859-1 (Latin-1) enc/iso8859_2.c ISO-8859-2 (Latin-2) enc/iso8859_3.c ISO-8859-3 (Latin-3) enc/iso8859_4.c ISO-8859-4 (Latin-4) enc/iso8859_5.c ISO-8859-5 (Cyrillic) enc/iso8859_6.c ISO-8859-6 (Arabic) enc/iso8859_7.c ISO-8859-7 (Greek) enc/iso8859_8.c ISO-8859-8 (Hebrew) enc/iso8859_9.c ISO-8859-9 (Latin-5 または Turkish) enc/iso8859_10.c ISO-8859-10 (Latin-6 または Nordic) enc/iso8859_11.c ISO-8859-11 (Thai) enc/iso8859_13.c ISO-8859-13 (Latin-7 または Baltic Rim) enc/iso8859_14.c ISO-8859-14 (Latin-8 または Celtic) enc/iso8859_15.c ISO-8859-15 (Latin-9 または West European with Euro) enc/iso8859_16.c ISO-8859-16 (Latin-10 または South-Eastern European with Euro) enc/utf8.c UTF-8 エンコーディング enc/utf16_be.c UTF-16BE エンコーディング enc/utf16_le.c UTF-16LE エンコーディング enc/utf32_be.c UTF-32BE エンコーディング enc/utf32_le.c UTF-32LE エンコーディング enc/unicode.c Unicode情報 win32/Makefile Win32用 Makefile (for VC++) win32/config.h Win32用 config.h 残件 ? case fold flag: Katakana <-> Hiragana ? ONIG_OPTION_NOTBOS/NOTEOS追加 (\A, \z, \Z) ?? \X (== \PM\pM*) ?? 文法要素 ONIG_SYN_CONTEXT_INDEP_ANCHORSの実装 ?? 検索位置移動停止演算子 (match_at()からONIG_STOPを返す) and I'm thankful to Akinori MUSHA. アドレス: K.Kosako ================================================ FILE: src/Onigmo/aclocal.m4 ================================================ # generated automatically by aclocal 1.11.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program 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. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, [m4_warning([this file was generated for autoconf 2.65. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.11.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.11.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) ================================================ FILE: src/Onigmo/compile ================================================ #! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2009-10-06.20; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software # Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use `[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/Onigmo/config.guess ================================================ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Free Software Foundation, Inc. timestamp='2009-12-30' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else echo ${UNAME_MACHINE}-unknown-linux-gnueabi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/Onigmo/config.h.in ================================================ /* config.h.in. Generated from configure.in by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define if compilerr supports prototypes */ #undef HAVE_PROTOTYPES /* Define if compiler supports stdarg prototypes */ #undef HAVE_STDARG_PROTOTYPES /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define if combination explosion check */ #undef USE_COMBINATION_EXPLOSION_CHECK /* Define if enable CR+NL as line terminator */ #undef USE_CRNL_AS_LINE_TERMINATOR /* Version number of package */ #undef VERSION /* Define to empty if `const' does not conform to ANSI C. */ #undef const ================================================ FILE: src/Onigmo/config.sub ================================================ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Free Software Foundation, Inc. timestamp='2010-01-22' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | ubicom32 \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile-* | tilegx-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze) basic_machine=microblaze-xilinx ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; # This must be matched before tile*. tilegx*) basic_machine=tilegx-unknown os=-linux-gnu ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ================================================ FILE: src/Onigmo/configure ================================================ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for onig 5.13.5. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac ECHO=${lt_ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF $* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='onig' PACKAGE_TARNAME='onig' PACKAGE_VERSION='5.13.5' PACKAGE_STRING='onig 5.13.5' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS ALLOCA LTVERSION CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL lt_ECHO RANLIB AR OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC STATISTICS RUBYDIR am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_rubydir with_statistics enable_combination_explosion_check enable_crnl_as_line_terminator enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures onig 5.13.5 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/onig] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of onig 5.13.5:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-combination-explosion-check enable combination explosion check --enable-crnl-as-line-terminator enable CR+NL as line terminator --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-rubydir=RUBYDIR specify value for RUBYDIR (default ..) --with-statistics take matching time statistical data --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF onig configure 5.13.5 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by onig $as_me 5.13.5, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.11' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do for ac_t in install-sh install.sh shtool; do if test -f "$ac_dir/$ac_t"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/$ac_t -c" break 2 fi done done if test -z "$ac_aux_dir"; then as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test "${ac_cv_path_mkdir+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='onig' VERSION='5.13.5' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers config.h" RUBYDIR=".." # Check whether --with-rubydir was given. if test "${with_rubydir+set}" = set; then : withval=$with_rubydir; RUBYDIR=$withval fi STATISTICS="" # Check whether --with-statistics was given. if test "${with_statistics+set}" = set; then : withval=$with_statistics; STATISTICS=-DONIG_DEBUG_STATISTICS fi # Check whether --enable-combination-explosion-check was given. if test "${enable_combination_explosion_check+set}" = set; then : enableval=$enable_combination_explosion_check; comb_expl_check=$enableval fi if test "${comb_expl_check}" = yes; then $as_echo "#define USE_COMBINATION_EXPLOSION_CHECK 1" >>confdefs.h fi # Check whether --enable-crnl-as-line-terminator was given. if test "${enable_crnl_as_line_terminator+set}" = set; then : enableval=$enable_crnl_as_line_terminator; crnl_as_line_terminator=$enableval fi if test "${crnl_as_line_terminator}" = yes; then $as_echo "#define USE_CRNL_AS_LINE_TERMINATOR 1" >>confdefs.h fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.2.6b' macro_revision='1.3017' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if test "${ac_cv_build+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if test "${ac_cv_host+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if test "${ac_cv_path_SED+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if test "${ac_cv_path_FGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if test "${lt_cv_path_LD+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test "${lt_cv_path_NM+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$ac_tool_prefix"; then for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DUMPBIN+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if test "${lt_cv_nm_interface+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:4692: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:4695: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:4698: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if test "${lt_cv_sys_max_cmd_len+set}" = set; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if test "${lt_cv_ld_reload_flag+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5904 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if test "${lt_cv_cc_needs_belf+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_NMEDIT+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_LIPO+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL64+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if test "${lt_cv_apple_cc_single_mod+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if test "${lt_cv_objdir+set}" = set; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7434: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7438: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7773: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7777: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7878: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7882: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7933: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7937: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu) link_all_deplibs=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi link_all_deplibs=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(void) {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = x""yes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10317 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10413 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi LTVERSION="5:0:5" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in stdlib.h string.h strings.h sys/time.h unistd.h sys/times.h stdint.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 $as_echo_n "checking size of int... " >&6; } if test "${ac_cv_sizeof_int+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : else if test "$ac_cv_type_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "cannot compute sizeof (int) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 $as_echo "$ac_cv_sizeof_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT $ac_cv_sizeof_int _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 $as_echo_n "checking size of short... " >&6; } if test "${ac_cv_sizeof_short+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : else if test "$ac_cv_type_short" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "cannot compute sizeof (short) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 $as_echo "$ac_cv_sizeof_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SHORT $ac_cv_sizeof_short _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 $as_echo_n "checking size of long... " >&6; } if test "${ac_cv_sizeof_long+set}" = set; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : else if test "$ac_cv_type_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "cannot compute sizeof (long) See \`config.log' for more details." "$LINENO" 5; }; } else ac_cv_sizeof_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 $as_echo "$ac_cv_sizeof_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_LONG $ac_cv_sizeof_long _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if test "${ac_cv_c_const+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if test "${ac_cv_header_time+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 $as_echo_n "checking for working alloca.h... " >&6; } if test "${ac_cv_working_alloca_h+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { char *p = (char *) alloca (2 * sizeof (int)); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_working_alloca_h=yes else ac_cv_working_alloca_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 $as_echo "$ac_cv_working_alloca_h" >&6; } if test $ac_cv_working_alloca_h = yes; then $as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 $as_echo_n "checking for alloca... " >&6; } if test "${ac_cv_func_alloca_works+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __GNUC__ # define alloca __builtin_alloca #else # ifdef _MSC_VER # include # define alloca _alloca # else # ifdef HAVE_ALLOCA_H # include # else # ifdef _AIX #pragma alloca # else # ifndef alloca /* predefined by HP cc +Olibcalls */ char *alloca (); # endif # endif # endif # endif #endif int main () { char *p = (char *) alloca (1); if (p) return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_func_alloca_works=yes else ac_cv_func_alloca_works=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 $as_echo "$ac_cv_func_alloca_works" >&6; } if test $ac_cv_func_alloca_works = yes; then $as_echo "#define HAVE_ALLOCA 1" >>confdefs.h else # The SVR3 libPW and SVR4 libucb both contain incompatible functions # that cause trouble. Some versions do not even contain alloca or # contain a buggy version. If you still want to use their alloca, # use ar to extract alloca.o from them instead of compiling alloca.c. ALLOCA=\${LIBOBJDIR}alloca.$ac_objext $as_echo "#define C_ALLOCA 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 $as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } if test "${ac_cv_os_cray+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined CRAY && ! defined CRAY2 webecray #else wenotbecray #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "webecray" >/dev/null 2>&1; then : ac_cv_os_cray=yes else ac_cv_os_cray=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 $as_echo "$ac_cv_os_cray" >&6; } if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define CRAY_STACKSEG_END $ac_func _ACEOF break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 $as_echo_n "checking stack direction for C alloca... " >&6; } if test "${ac_cv_c_stack_direction+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_c_stack_direction=0 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int find_stack_direction () { static char *addr = 0; auto char dummy; if (addr == 0) { addr = &dummy; return find_stack_direction (); } else return (&dummy > addr) ? 1 : -1; } int main () { return find_stack_direction () < 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_stack_direction=1 else ac_cv_c_stack_direction=-1 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 $as_echo "$ac_cv_c_stack_direction" >&6; } cat >>confdefs.h <<_ACEOF #define STACK_DIRECTION $ac_cv_c_stack_direction _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if test "${ac_cv_func_memcmp_working+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for prototypes" >&5 $as_echo_n "checking for prototypes... " >&6; } if test "${_cv_have_prototypes+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(int x) { return 0; } int main () { return foo(10); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : _cv_have_prototypes=yes else _cv_have_prototypes=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_cv_have_prototypes" >&5 $as_echo "$_cv_have_prototypes" >&6; } if test "$_cv_have_prototypes" = yes; then $as_echo "#define HAVE_PROTOTYPES 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for variable length prototypes and stdarg.h" >&5 $as_echo_n "checking for variable length prototypes and stdarg.h... " >&6; } if test "${_cv_stdarg+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int foo(int x, ...) { va_list va; va_start(va, x); va_arg(va, int); va_arg(va, char *); va_arg(va, double); va_end(va); return 0; } int main () { return foo(10, "", 3.14); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : _cv_stdarg=yes else _cv_stdarg=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_cv_stdarg" >&5 $as_echo "$_cv_stdarg" >&6; } if test "$_cv_stdarg" = yes; then $as_echo "#define HAVE_STDARG_PROTOTYPES 1" >>confdefs.h fi ac_config_files="$ac_config_files Makefile onig-config sample/Makefile" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by onig $as_me 5.13.5, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ onig config.status 5.13.5 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ AR \ AR_FLAGS \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ SHELL \ ECHO \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` ;; esac ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "onig-config") CONFIG_FILES="$CONFIG_FILES onig-config" ;; "sample/Makefile") CONFIG_FILES="$CONFIG_FILES sample/Makefile" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == "file_magic". file_magic_cmd=$lt_file_magic_cmd # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name of the directory that contains temporary libtool files. objdir=$objdir # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that does not interpret backslashes. ECHO=$lt_ECHO # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $* )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[^=]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$@"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1+=\$2" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1=\$$1\$2" } _LT_EOF ;; esac sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; "default":C) chmod +x onig-config ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi ================================================ FILE: src/Onigmo/configure.in ================================================ dnl Process this file with autoconf to produce a configure script. AC_INIT(onig, 5.13.5) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE(foreign) AC_CONFIG_HEADER(config.h) dnl default value for RUBYDIR RUBYDIR=".." AC_ARG_WITH(rubydir, [ --with-rubydir=RUBYDIR specify value for RUBYDIR (default ..)], [ RUBYDIR=$withval ]) AC_SUBST(RUBYDIR) dnl default value for STATISTICS STATISTICS="" AC_ARG_WITH(statistics, [ --with-statistics take matching time statistical data], [ STATISTICS=-DONIG_DEBUG_STATISTICS ]) AC_SUBST(STATISTICS) dnl check for COMBINATION_EXPLOSION AC_ARG_ENABLE(combination-explosion-check, [ --enable-combination-explosion-check enable combination explosion check], [comb_expl_check=$enableval]) if test "${comb_expl_check}" = yes; then AC_DEFINE(USE_COMBINATION_EXPLOSION_CHECK,1,[Define if combination explosion check]) fi dnl check for CRNL_AS_LINE_TERMINATOR AC_ARG_ENABLE(crnl-as-line-terminator, [ --enable-crnl-as-line-terminator enable CR+NL as line terminator], [crnl_as_line_terminator=$enableval]) if test "${crnl_as_line_terminator}" = yes; then AC_DEFINE(USE_CRNL_AS_LINE_TERMINATOR,1,[Define if enable CR+NL as line terminator]) fi dnl Checks for programs. AC_PROG_CC AC_PROG_LIBTOOL AM_PROG_CC_C_O LTVERSION="5:0:5" AC_SUBST(LTVERSION) AC_PROG_INSTALL AC_PROG_MAKE_SET dnl Checks for libraries. dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(stdlib.h string.h strings.h sys/time.h unistd.h sys/times.h stdint.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_CHECK_SIZEOF(int, 4) AC_CHECK_SIZEOF(short, 2) AC_CHECK_SIZEOF(long, 4) AC_C_CONST AC_HEADER_TIME dnl Checks for library functions. AC_FUNC_ALLOCA AC_FUNC_MEMCMP AC_CACHE_CHECK(for prototypes, _cv_have_prototypes, [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);], _cv_have_prototypes=yes, _cv_have_prototypes=no)]) if test "$_cv_have_prototypes" = yes; then AC_DEFINE(HAVE_PROTOTYPES,1,[Define if compilerr supports prototypes]) fi AC_CACHE_CHECK(for variable length prototypes and stdarg.h, _cv_stdarg, [AC_TRY_COMPILE([ #include int foo(int x, ...) { va_list va; va_start(va, x); va_arg(va, int); va_arg(va, char *); va_arg(va, double); va_end(va); return 0; } ], [return foo(10, "", 3.14);], _cv_stdarg=yes, _cv_stdarg=no)]) if test "$_cv_stdarg" = yes; then AC_DEFINE(HAVE_STDARG_PROTOTYPES,1,[Define if compiler supports stdarg prototypes]) fi AC_OUTPUT([Makefile onig-config sample/Makefile], [chmod +x onig-config]) ================================================ FILE: src/Onigmo/depcomp ================================================ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free # Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/Onigmo/doc/API ================================================ Onigmo (Oniguruma-mod) API Version 5.11.4 2011/10/08 #include # int onig_init(void) Initialize library. You don't have to call it explicitly, because it is called in onig_new(). # int onig_error_code_to_str(UChar* err_buf, OnigPosition err_code, ...) Get error message string. If this function is used for onig_new(), don't call this after the pattern argument of onig_new() is freed. normal return: error message string length arguments 1 err_buf: error message string buffer. (required size: ONIG_MAX_ERROR_MESSAGE_LEN) 2 err_code: error code returned by other API functions. 3 err_info (optional): error info returned by onig_new(). # void onig_set_warn_func(OnigWarnFunc func) Set warning function. WARNING: '[', '-', ']' in character class without escape. ']' in pattern without escape. arguments 1 func: function pointer. void (*func)(char* warning_message) # void onig_set_verb_warn_func(OnigWarnFunc func) Set verbose warning function. WARNING: redundant nested repeat operator. arguments 1 func: function pointer. void (*func)(char* warning_message) # int onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* err_info) Create a regex object. normal return: ONIG_NORMAL arguments 1 reg: return regex object's address. 2 pattern: regex pattern string. 3 pattern_end: terminate address of pattern. (pattern + pattern length) 4 option: compile time options. ONIG_OPTION_NONE no option ONIG_OPTION_SINGLELINE '^' -> '\A', '$' -> '\Z' ONIG_OPTION_DOTALL '.' match with newline ONIG_OPTION_MULTILINE same as ONIG_OPTION_DOTALL ONIG_OPTION_IGNORECASE ambiguity match on ONIG_OPTION_EXTEND extended pattern form ONIG_OPTION_FIND_LONGEST find longest match ONIG_OPTION_FIND_NOT_EMPTY ignore empty match ONIG_OPTION_NEGATE_SINGLELINE clear ONIG_OPTION_SINGLELINE which is enabled on ONIG_SYNTAX_POSIX_BASIC, ONIG_SYNTAX_POSIX_EXTENDED, ONIG_SYNTAX_PERL, ONIG_SYNTAX_PERL58, ONIG_SYNTAX_PERL58_NG, ONIG_SYNTAX_JAVA, ONIG_SYNTAX_PYTHON ONIG_OPTION_DONT_CAPTURE_GROUP only named group captured. ONIG_OPTION_CAPTURE_GROUP named and no-named group captured. ONIG_OPTION_NEWLINE_CRLF Treat CR+LF as a newline too. (default: LF only) To use this option, you must enable the following line in regenc.h. /* #define USE_CRNL_AS_LINE_TERMINATOR */ 5 enc: character encoding. ONIG_ENCODING_ASCII ASCII ONIG_ENCODING_ISO_8859_1 ISO 8859-1 ONIG_ENCODING_ISO_8859_2 ISO 8859-2 ONIG_ENCODING_ISO_8859_3 ISO 8859-3 ONIG_ENCODING_ISO_8859_4 ISO 8859-4 ONIG_ENCODING_ISO_8859_5 ISO 8859-5 ONIG_ENCODING_ISO_8859_6 ISO 8859-6 ONIG_ENCODING_ISO_8859_7 ISO 8859-7 ONIG_ENCODING_ISO_8859_8 ISO 8859-8 ONIG_ENCODING_ISO_8859_9 ISO 8859-9 ONIG_ENCODING_ISO_8859_10 ISO 8859-10 ONIG_ENCODING_ISO_8859_11 ISO 8859-11 ONIG_ENCODING_ISO_8859_13 ISO 8859-13 ONIG_ENCODING_ISO_8859_14 ISO 8859-14 ONIG_ENCODING_ISO_8859_15 ISO 8859-15 ONIG_ENCODING_ISO_8859_16 ISO 8859-16 ONIG_ENCODING_UTF8 UTF-8 ONIG_ENCODING_UTF16_BE UTF-16BE ONIG_ENCODING_UTF16_LE UTF-16LE ONIG_ENCODING_UTF32_BE UTF-32BE ONIG_ENCODING_UTF32_LE UTF-32LE ONIG_ENCODING_EUC_JP EUC-JP ONIG_ENCODING_EUC_TW EUC-TW ONIG_ENCODING_EUC_KR EUC-KR ONIG_ENCODING_EUC_CN EUC-CN ONIG_ENCODING_SJIS Shift_JIS ONIG_ENCODING_KOI8_R KOI8-R ONIG_ENCODING_CP1251 CP1251 ONIG_ENCODING_BIG5 Big5 ONIG_ENCODING_GB18030 GB18030 or any OnigEncodingType data address defined by user. 6 syntax: address of pattern syntax definition. ONIG_SYNTAX_ASIS plain text ONIG_SYNTAX_POSIX_BASIC POSIX Basic RE ONIG_SYNTAX_POSIX_EXTENDED POSIX Extended RE ONIG_SYNTAX_EMACS Emacs ONIG_SYNTAX_GREP grep ONIG_SYNTAX_GNU_REGEX GNU regex ONIG_SYNTAX_JAVA Java (Sun java.util.regex) ONIG_SYNTAX_PERL58 Perl 5.8 ONIG_SYNTAX_PERL58_NG Perl 5.8 + named group ONIG_SYNTAX_PERL Perl 5.10+ ONIG_SYNTAX_PYTHON Python ONIG_SYNTAX_RUBY Ruby ONIG_SYNTAX_DEFAULT default (== Ruby) onig_set_default_syntax() or any OnigSyntaxType data address defined by user. 7 err_info: address for return optional error info. Use this value as 3rd argument of onig_error_code_to_str(). # int onig_new_without_alloc(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* err_info) Create a regex object. reg object area is not allocated in this function. normal return: ONIG_NORMAL # int onig_new_deluxe(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo) Create a regex object. This function is deluxe version of onig_new(). normal return: ONIG_NORMAL arguments 1 reg: return address of regex object. 2 pattern: regex pattern string. 3 pattern_end: terminate address of pattern. (pattern + pattern length) 4 ci: compile time info. ci->num_of_elements: number of elements in ci. (current version: 5) ci->pattern_enc: pattern string character encoding. ci->target_enc: target string character encoding. ci->syntax: address of pattern syntax definition. ci->option: compile time option. ci->case_fold_flag: character matching case fold bit flag for ONIG_OPTION_IGNORECASE mode. ONIGENC_CASE_FOLD_MIN: minimum ONIGENC_CASE_FOLD_DEFAULT: minimum onig_set_default_case_fold_flag() 5 err_info: address for return optional error info. Use this value as 3rd argument of onig_error_code_to_str(). Different character encoding combination is allowed for the following cases only. pattern_enc: ASCII, ISO_8859_1 target_enc: UTF16_BE, UTF16_LE, UTF32_BE, UTF32_LE pattern_enc: UTF16_BE/LE target_enc: UTF16_LE/BE pattern_enc: UTF32_BE/LE target_enc: UTF32_LE/BE # void onig_free(regex_t* reg) Free memory used by regex object. arguments 1 reg: regex object. # void onig_free_body(regex_t* reg) Free memory used by regex object. (Except reg oneself.) arguments 1 reg: regex object. # OnigPosition onig_search(regex_t* reg, const UChar* str, const UChar* end, const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option) # OnigPosition onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end, const UChar* global_pos, const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option) Search string and return search result and matching region. normal return: match position offset (i.e. p - str >= 0) not found: ONIG_MISMATCH (< 0) arguments 1 reg: regex object 2 str: target string 3 end: terminate address of target string 4 global_pos: position of \G if not need, set same value as str. 5 start: search start address of target string 6 range: search terminate address of target string in forward search (start <= searched string < range) in backward search (range <= searched string <= start) 7 region: address for return group match range info (NULL is allowed) 8 option: search time option ONIG_OPTION_NOTBOL string head(str) isn't considered as begin of line ONIG_OPTION_NOTEOL string end (end) isn't considered as end of line ONIG_OPTION_POSIX_REGION region argument is regmatch_t[] of POSIX API. # OnigPosition onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region, OnigOptionType option) Match string and return result and matching region. normal return: match length (>= 0) not match: ONIG_MISMATCH ( < 0) arguments 1 reg: regex object 2 str: target string 3 end: terminate address of target string 4 at: match address of target string 5 region: address for return group match range info (NULL is allowed) 6 option: search time option ONIG_OPTION_NOTBOL string head(str) isn't considered as begin of line ONIG_OPTION_NOTEOL string end (end) isn't considered as end of line ONIG_OPTION_POSIX_REGION region argument is regmatch_t[] type of POSIX API. # OnigRegion* onig_region_new(void) Create a region. # void onig_region_free(OnigRegion* region, int free_self) Free memory used by region. arguments 1 region: target region 2 free_self: [1: free all, 0: free memory used in region but not self] # void onig_region_copy(OnigRegion* to, OnigRegion* from) Copy contents of region. arguments 1 to: target region 2 from: source region # void onig_region_clear(OnigRegion* region) Clear contents of region. arguments 1 region: target region # int onig_region_resize(OnigRegion* region, int n) Resize group range area of region. normal return: ONIG_NORMAL arguments 1 region: target region 2 n: new size # int onig_name_to_group_numbers(regex_t* reg, const UChar* name, const UChar* name_end, int** num_list) Return the group number list of the name. Named subexp is defined by (?....). normal return: number of groups for the name. (ex. /(?..)(?..)/ ==> 2) name not found: -1 arguments 1 reg: regex object. 2 name: group name. 3 name_end: terminate address of group name. 4 num_list: return list of group number. # int onig_name_to_backref_number(regex_t* reg, const UChar* name, const UChar* name_end, OnigRegion *region) Return the group number corresponding to the named backref (\k). If two or more regions for the groups of the name are effective, the greatest number in it is obtained. normal return: group number. arguments 1 reg: regex object. 2 name: group name. 3 name_end: terminate address of group name. 4 region: search/match result region. # int onig_foreach_name(regex_t* reg, int (*func)(const UChar*, const UChar*, int,int*,regex_t*,void*), void* arg) Iterate function call for all names. normal return: 0 error: func's return value. arguments 1 reg: regex object. 2 func: callback function. func(name, name_end, , , reg, arg); if func does not return 0, then iteration is stopped. 3 arg: argument for func. # int onig_number_of_names(regex_t* reg) Return the number of names defined in the pattern. Multiple definitions of one name is counted as one. arguments 1 reg: regex object. # OnigEncoding onig_get_encoding(regex_t* reg) # OnigOptionType onig_get_options(regex_t* reg) # OnigCaseFoldType onig_get_case_fold_flag(regex_t* reg) # OnigSyntaxType* onig_get_syntax(regex_t* reg) Return a value of the regex object. arguments 1 reg: regex object. # int onig_number_of_captures(regex_t* reg) Return the number of capture group in the pattern. arguments 1 reg: regex object. # int onig_number_of_capture_histories(regex_t* reg) Return the number of capture history defined in the pattern. You can't use capture history if ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY is disabled in the pattern syntax.(disabled in the default syntax) arguments 1 reg: regex object. # OnigCaptureTreeNode* onig_get_capture_tree(OnigRegion* region) Return the root node of capture history data tree. This value is undefined if matching has faild. arguments 1 region: matching result. # int onig_capture_tree_traverse(OnigRegion* region, int at, int(*func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg) Traverse and callback in capture history data tree. normal return: 0 error: callback func's return value. arguments 1 region: match region data. 2 at: callback position. ONIG_TRAVERSE_CALLBACK_AT_FIRST: callback first, then traverse children. ONIG_TRAVERSE_CALLBACK_AT_LAST: traverse children first, then callback. ONIG_TRAVERSE_CALLBACK_AT_BOTH: callback first, then traverse children, and at last callback again. 3 func: callback function. if func does not return 0, then traverse is stopped. int func(int group, OnigPosition beg, OnigPosition end, int level, int at, void* arg) group: group number beg: capture start position end: capture end position level: nest level (from 0) at: callback position ONIG_TRAVERSE_CALLBACK_AT_FIRST ONIG_TRAVERSE_CALLBACK_AT_LAST arg: optional callback argument 4 arg; optional callback argument. # int onig_noname_group_capture_is_active(regex_t* reg) Return noname group capture activity. active: 1 inactive: 0 arguments 1 reg: regex object. if option ONIG_OPTION_DONT_CAPTURE_GROUP == ON --> inactive if the regex pattern have named group and syntax ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP == ON and option ONIG_OPTION_CAPTURE_GROUP == OFF --> inactive else --> active # UChar* onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s) Return previous character head address. arguments 1 enc: character encoding 2 start: string address 3 s: target address of string # UChar* onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) Return left-adjusted head address of a character. arguments 1 enc: character encoding 2 start: string address 3 s: target address of string # UChar* onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) Return right-adjusted head address of a character. arguments 1 enc: character encoding 2 start: string address 3 s: target address of string # int onigenc_strlen(OnigEncoding enc, const UChar* s, const UChar* end) # int onigenc_strlen_null(OnigEncoding enc, const UChar* s) Return number of characters in the string. # int onigenc_str_bytelen_null(OnigEncoding enc, const UChar* s) Return number of bytes in the string. # int onig_set_default_syntax(OnigSyntaxType* syntax) Set default syntax. arguments 1 syntax: address of pattern syntax definition. # void onig_copy_syntax(OnigSyntaxType* to, const OnigSyntaxType* from) Copy syntax. arguments 1 to: destination address. 2 from: source address. # unsigned int onig_get_syntax_op(OnigSyntaxType* syntax) # unsigned int onig_get_syntax_op2(OnigSyntaxType* syntax) # unsigned int onig_get_syntax_behavior(OnigSyntaxType* syntax) # OnigOptionType onig_get_syntax_options(OnigSyntaxType* syntax) # void onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op) # void onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2) # void onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior) # void onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options) Get/Set elements of the syntax. arguments 1 syntax: syntax 2 op, op2, behavior, options: value of element. # void onig_copy_encoding(OnigEncoding to, OnigOnigEncoding from) Copy encoding. arguments 1 to: destination address. 2 from: source address. # int onig_set_meta_char(OnigSyntaxType* syntax, unsigned int what, OnigCodePoint code) Set a variable meta character to the code point value. Except for an escape character, this meta characters specification is not work, if ONIG_SYN_OP_VARIABLE_META_CHARACTERS is not effective by the syntax. (Build-in syntaxes are not effective.) normal return: ONIG_NORMAL arguments 1 syntax: target syntax 2 what: specifies which meta character it is. ONIG_META_CHAR_ESCAPE ONIG_META_CHAR_ANYCHAR ONIG_META_CHAR_ANYTIME ONIG_META_CHAR_ZERO_OR_ONE_TIME ONIG_META_CHAR_ONE_OR_MORE_TIME ONIG_META_CHAR_ANYCHAR_ANYTIME 3 code: meta character or ONIG_INEFFECTIVE_META_CHAR. # OnigCaseFoldType onig_get_default_case_fold_flag() Get default case fold flag. # int onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag) Set default case fold flag. 1 case_fold_flag: case fold flag # unsigned int onig_get_match_stack_limit_size(void) Return the maximum number of stack size. (default: 0 == unlimited) # int onig_set_match_stack_limit_size(unsigned int size) Set the maximum number of stack size. (size = 0: unlimited) normal return: ONIG_NORMAL # int onig_end(void) The use of this library is finished. normal return: ONIG_NORMAL It is not allowed to use regex objects which created before onig_end() call. # const char* onig_version(void) Return version string. (ex. "5.0.3") // END ================================================ FILE: src/Onigmo/doc/API.ja ================================================ Onigmo インターフェース Version 5.11.4 2011/10/08 #include # int onig_init(void) ライブラリの初期化 onig_new()の中で呼び出されるので、この関数を明示的に呼び出さなくてもよい。 # int onig_error_code_to_str(UChar* err_buf, OnigPosition err_code, ...) エラーメッセージを取得する。 この関数を、onig_new()の結果に対して呼び出す場合には、onig_new()のpattern引数を メモリ解放するよりも前に呼び出さなければならない。 正常終了戻り値: エラーメッセージ文字列のバイト長 引数 1 err_buf: エラーメッセージを格納する領域 (必要なサイズ: ONIG_MAX_ERROR_MESSAGE_LEN) 2 err_code: エラーコード 3 err_info (optional): onig_new()のerr_info # void onig_set_warn_func(OnigWarnFunc func) 警告通知関数をセットする。 警告: '[', '-', ']' in character class without escape. ']' in pattern without escape. 引数 1 func: 警告関数 void (*func)(char* warning_message) # void onig_set_verb_warn_func(OnigWarnFunc func) 詳細警告通知関数をセットする。 詳細警告: redundant nested repeat operator. 引数 1 func: 詳細警告関数 void (*func)(char* warning_message) # int onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* err_info) 正規表現オブジェクト(regex)を作成する。 正常終了戻り値: ONIG_NORMAL 引数 1 reg: 作成された正規表現オブジェクトを返すアドレス 2 pattern: 正規表現パターン文字列 3 pattern_end: 正規表現パターン文字列の終端アドレス(pattern + pattern length) 4 option: 正規表現コンパイル時オプション ONIG_OPTION_NONE オプションなし ONIG_OPTION_SINGLELINE '^' -> '\A', '$' -> '\Z' ONIG_OPTION_DOTALL '.'が改行にマッチする ONIG_OPTION_MULTILINE ONIG_OPTION_DOTALLと同じ ONIG_OPTION_IGNORECASE 曖昧マッチ オン ONIG_OPTION_EXTEND パターン拡張形式 ONIG_OPTION_FIND_LONGEST 最長マッチ ONIG_OPTION_FIND_NOT_EMPTY 空マッチを無視 ONIG_OPTION_NEGATE_SINGLELINE ONIG_SYNTAX_POSIX_BASIC, ONIG_SYNTAX_POSIX_EXTENDED, ONIG_SYNTAX_PERL, ONIG_SYNTAX_PERL58, ONIG_SYNTAX_PERL58_NG, ONIG_SYNTAX_JAVA, ONIG_SYNTAX_PYTHONで デフォルトで有効なONIG_OPTION_SINGLELINEをクリアする。 ONIG_OPTION_DONT_CAPTURE_GROUP 名前付き捕獲式集合のみ捕獲 ONIG_OPTION_CAPTURE_GROUP 名前無し捕獲式集合も捕獲 ONIG_OPTION_NEWLINE_CRLF CR+LFも改行として扱う。(デフォルトではLFのみ。) この機能を使うには、regenc.hの以下の行を有効にする必要がある。 /* #define USE_CRNL_AS_LINE_TERMINATOR */ 5 enc: 文字エンコーディング ONIG_ENCODING_ASCII ASCII ONIG_ENCODING_ISO_8859_1 ISO 8859-1 ONIG_ENCODING_ISO_8859_2 ISO 8859-2 ONIG_ENCODING_ISO_8859_3 ISO 8859-3 ONIG_ENCODING_ISO_8859_4 ISO 8859-4 ONIG_ENCODING_ISO_8859_5 ISO 8859-5 ONIG_ENCODING_ISO_8859_6 ISO 8859-6 ONIG_ENCODING_ISO_8859_7 ISO 8859-7 ONIG_ENCODING_ISO_8859_8 ISO 8859-8 ONIG_ENCODING_ISO_8859_9 ISO 8859-9 ONIG_ENCODING_ISO_8859_10 ISO 8859-10 ONIG_ENCODING_ISO_8859_11 ISO 8859-11 ONIG_ENCODING_ISO_8859_13 ISO 8859-13 ONIG_ENCODING_ISO_8859_14 ISO 8859-14 ONIG_ENCODING_ISO_8859_15 ISO 8859-15 ONIG_ENCODING_ISO_8859_16 ISO 8859-16 ONIG_ENCODING_UTF8 UTF-8 ONIG_ENCODING_UTF16_BE UTF-16BE ONIG_ENCODING_UTF16_LE UTF-16LE ONIG_ENCODING_UTF32_BE UTF-32BE ONIG_ENCODING_UTF32_LE UTF-32LE ONIG_ENCODING_EUC_JP EUC-JP ONIG_ENCODING_EUC_TW EUC-TW ONIG_ENCODING_EUC_KR EUC-KR ONIG_ENCODING_EUC_CN EUC-CN ONIG_ENCODING_SJIS Shift_JIS ONIG_ENCODING_KOI8_R KOI8-R ONIG_ENCODING_CP1251 CP1251 ONIG_ENCODING_BIG5 Big5 ONIG_ENCODING_GB18030 GB18030 または、ユーザが定義したOnigEncodingTypeデータのアドレス 6 syntax: 正規表現パターン文法定義 ONIG_SYNTAX_ASIS plain text ONIG_SYNTAX_POSIX_BASIC POSIX Basic RE ONIG_SYNTAX_POSIX_EXTENDED POSIX Extended RE ONIG_SYNTAX_EMACS Emacs ONIG_SYNTAX_GREP grep ONIG_SYNTAX_GNU_REGEX GNU regex ONIG_SYNTAX_JAVA Java (Sun java.util.regex) ONIG_SYNTAX_PERL58 Perl 5.8 ONIG_SYNTAX_PERL58_NG Perl 5.8 + 名前付き捕獲式集合 ONIG_SYNTAX_PERL Perl 5.10以降 ONIG_SYNTAX_PYTHON Python ONIG_SYNTAX_RUBY Ruby ONIG_SYNTAX_DEFAULT default (== Ruby) onig_set_default_syntax() または、ユーザが定義したOnigSyntaxTypeデータのアドレス 7 err_info: エラー情報を返すためのアドレス onig_error_code_to_str()の三番目の引数として使用する # int onig_new_without_alloc(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* err_info) 正規表現オブジェクト(regex)を作成する。 regの領域を内部で割り当てない。 正常終了戻り値: ONIG_NORMAL # int onig_new_deluxe(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo) 正規表現オブジェクト(regex)を作成する。 この関数は、onig_new()のデラックス版。 正常終了戻り値: ONIG_NORMAL 引数 1 reg: 作成された正規表現オブジェクトを返すアドレス 2 pattern: 正規表現パターン文字列 3 pattern_end: 正規表現パターン文字列の終端アドレス(pattern + pattern length) 4 ci: コンパイル情報 ci->num_of_elements: ciの要素数 (現在の版では: 5) ci->pattern_enc: パターン文字列の文字エンコーディング ci->target_enc: 対象文字列の文字エンコーディング ci->syntax: 正規表現パターン文法定義 ci->option: 正規表現コンパイル時オプション ci->case_fold_flag: ONIG_OPTION_IGNORECASEモードでの 文字曖昧マッチ指定ビットフラグ ONIGENC_CASE_FOLD_MIN: 最小 ONIGENC_CASE_FOLD_DEFAULT: 最小 onig_set_default_case_fold_flag() 5 err_info: エラー情報を返すためのアドレス onig_error_code_to_str()の三番目の引数として使用する 異なる文字エンコーディングの組み合わせは、以下の場合にのみ許される。 pattern_enc: ASCII, ISO_8859_1 target_enc: UTF16_BE, UTF16_LE, UTF32_BE, UTF32_LE pattern_enc: UTF16_BE/LE target_enc: UTF16_LE/BE pattern_enc: UTF32_BE/LE target_enc: UTF32_LE/BE # void onig_free(regex_t* reg) 正規表現オブジェクトのメモリを解放する。 引数 1 reg: 正規表現オブジェクト # void onig_free_body(regex_t* reg) 正規表現オブジェクトのメモリを解放する。(reg自身の領域を除いて) 引数 1 reg: 正規表現オブジェクト # OnigPosition onig_search(regex_t* reg, const UChar* str, const UChar* end, const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option) # OnigPosition onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end, const UChar* global_pos, const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option) 正規表現で文字列を検索し、検索結果とマッチ領域を返す。 正常終了戻り値: マッチ位置 (p - str >= 0) 検索失敗: ONIG_MISMATCH (< 0) 引数 1 reg: 正規表現オブジェクト 2 str: 検索対象文字列 3 end: 検索対象文字列の終端アドレス 4 global_pos: \Gのアドレス 不要時はstrと同じ値を設定すること 5 start: 検索対象文字列の検索先頭位置アドレス 6 range: 検索対象文字列の検索終了位置アドレス 前方探索 (start <= 探索される文字列 < range) 後方探索 (range <= 探索される文字列 <= start) 7 region: マッチ領域情報(region) (NULLも許される) 8 option: 検索時オプション ONIG_OPTION_NOTBOL 文字列の先頭(str)を行頭と看做さない ONIG_OPTION_NOTEOL 文字列の終端(end)を行末と看做さない ONIG_OPTION_POSIX_REGION region引数をPOSIX APIのregmatch_t[]にする # OnigPosition onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region, OnigOptionType option) 文字列の指定位置でマッチングを行い、結果とマッチ領域を返す。 正常終了戻り値: マッチしたバイト長 (>= 0) not match: ONIG_MISMATCH ( < 0) 引数 1 reg: 正規表現オブジェクト 2 str: 検索対象文字列 3 end: 検索対象文字列の終端アドレス 4 at: 検索対象文字列の検索アドレス 5 region: マッチ領域情報(region) (NULLも許される) 6 option: 検索時オプション ONIG_OPTION_NOTBOL 文字列の先頭(str)を行頭と看做さない ONIG_OPTION_NOTEOL 文字列の終端(end)を行末と看做さない ONIG_OPTION_POSIX_REGION region引数をPOSIX APIのregmatch_t[]にする # OnigRegion* onig_region_new(void) マッチ領域情報(region)を作成する。 # void onig_region_free(OnigRegion* region, int free_self) マッチ領域情報(region)で使用されているメモリを解放する。 引数 1 region: マッチ領域情報オブジェクト 2 free_self: [1: region自身を含めて全て解放, 0: region自身は解放しない] # void onig_region_copy(OnigRegion* to, OnigRegion* from) マッチ領域情報(region)を複製する。 引数 1 to: 対象領域 2 from: 元領域 # void onig_region_clear(OnigRegion* region) マッチ領域情報(region)の中味をクリアする。 引数 1 region: 対象領域 # int onig_region_resize(OnigRegion* region, int n) マッチ領域情報(region)の捕獲式集合(グループ)数を変更する。 正常終了戻り値: ONIG_NORMAL 引数 1 region: 対象領域 2 n: 新しいサイズ # int onig_name_to_group_numbers(regex_t* reg, const UChar* name, const UChar* name_end, int** num_list) 指定した名前に対する名前付き捕獲式集合(グループ)の グループ番号リストを返す。 名前付き捕獲式集合は、(?....)によって定義できる。 正常終了戻り値: 指定された名前に対するグループ数 (例 /(?..)(?..)/ ==> 2) 名前に対するグループが存在しない: -1 引数 1 reg: 正規表現オブジェクト 2 name: 捕獲式集合(グループ)名 3 name_end: 捕獲式集合(グループ)名の終端アドレス 4 num_list: 番号リストを返すアドレス # int onig_name_to_backref_number(regex_t* reg, const UChar* name, const UChar* name_end, OnigRegion *region) 指定された名前の後方参照(\k)に対する捕獲式集合(グループ)の番号を返す。 名前に対して、複数のマッチ領域が有効であれば、その中の最大の番号を返す。 名前に対する捕獲式集合が一個しかないときには、対応するマッチ領域が有効か どうかに関係なく、その番号を返す。(従って、regionにはNULLを渡してもよい。) 正常終了戻り値: 番号 引数 1 reg: 正規表現オブジェクト 2 name: 捕獲式集合(グループ)名 3 name_end: 捕獲式集合(グループ)名の終端アドレス 4 region: search/match結果のマッチ領域 # int onig_foreach_name(regex_t* reg, int (*func)(const UChar*, const UChar*, int,int*,regex_t*,void*), void* arg) 全ての名前に対してコールバック関数呼び出しを実行する。 正常終了戻り値: 0 エラー: コールバック関数の戻り値 引数 1 reg: 正規表現オブジェクト 2 func: コールバック関数 func(name, name_end, , , reg, arg); funcが0以外の値を返すと、それ以降のコールバックは行なわずに 終了する。 3 arg: funcに対する追加引数 # int onig_number_of_names(regex_t* reg) パターン中で定義された名前の数を返す。 一個の名前の多重定義は一個と看做す。 引数 1 reg: 正規表現オブジェクト # OnigEncoding onig_get_encoding(regex_t* reg) # OnigOptionType onig_get_options(regex_t* reg) # OnigCaseFoldType onig_get_case_fold_flag(regex_t* reg) # OnigSyntaxType* onig_get_syntax(regex_t* reg) 正規表現オブジェクトに対して、対応する値を返す。 引数 1 reg: 正規表現オブジェクト # int onig_number_of_captures(regex_t* reg) パターン中で定義された捕獲グループの数を返す。 引数 1 reg: 正規表現オブジェクト # int onig_number_of_capture_histories(regex_t* reg) パターン中で定義された捕獲履歴(?@...)の数を返す。 使用する文法で捕獲履歴機能が有効(ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY) でなければ、捕獲履歴機能は使用できない。 引数 1 reg: 正規表現オブジェクト # OnigCaptureTreeNode* onig_get_capture_tree(OnigRegion* region) 捕獲履歴データのルートノードを返す。 マッチが失敗している場合には、この値は不定である。 引数 1 region: マッチ領域 # int onig_capture_tree_traverse(OnigRegion* region, int at, int(*func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg) 捕獲履歴データ木を巡回してコールバックする。 正常終了戻り値: 0 エラー: コールバック関数の戻り値 引数 1 region: マッチ領域 2 at: コールバックを行なうタイミング ONIG_TRAVERSE_CALLBACK_AT_FIRST: 最初にコールバックして、子ノードを巡回 ONIG_TRAVERSE_CALLBACK_AT_LAST: 子ノードを巡回して、コールバック ONIG_TRAVERSE_CALLBACK_AT_BOTH: 最初にコールバックして、子ノードを巡回、最後にもう一度コールバック 3 func: コールバック関数 funcが0以外の値を返すと、それ以降の巡回は行なわずに 終了する。 int func(int group, OnigPosition beg, OnigPosition end, int level, int at, void* arg) group: グループ番号 beg: マッチ開始位置 end マッチ終了位置 level: ネストレベル (0から) at: コールバックが呼び出されたタイミング ONIG_TRAVERSE_CALLBACK_AT_FIRST ONIG_TRAVERSE_CALLBACK_AT_LAST arg: 追加引数 4 arg; funcに対する追加引数 # int onig_noname_group_capture_is_active(regex_t* reg) 名前なし式集合の捕獲機能が有効かどうかを返す。 有効: 1 無効: 0 引数 1 reg: 正規表現オブジェクト オプションのONIG_OPTION_DONT_CAPTURE_GROUPがON --> 無効 パターンが名前つき式集合を使用している AND 使用文法で、ONIG_SYN_CAPTURE_ONLY_NAMED_GROUPがON AND オプションのONIG_OPTION_CAPTURE_GROUPがOFF --> 無効 上記以外の場合 --> 有効 # UChar* onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s) 文字一個分前の文字列位置を返す。 引数 1 enc: 文字エンコーディング 2 start: 文字列の先頭アドレス 3 s: 文字列中の位置 # UChar* onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) 文字の先頭バイト位置になるように左側に調整したアドレスを返す。 引数 1 enc: 文字エンコーディング 2 start: 文字列の先頭アドレス 3 s: 文字列中の位置 # UChar* onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) 文字の先頭バイト位置になるように右側に調整したアドレスを返す。 引数 1 enc: 文字エンコーディング 2 start: 文字列の先頭アドレス 3 s: 文字列中の位置 # int onigenc_strlen(OnigEncoding enc, const UChar* s, const UChar* end) # int onigenc_strlen_null(OnigEncoding enc, const UChar* s) 文字列の文字数を返す。 # int onigenc_str_bytelen_null(OnigEncoding enc, const UChar* s) 文字列のバイト数を返す。 # int onig_set_default_syntax(OnigSyntaxType* syntax) デフォルトの正規表現パターン文法をセットする。 引数 1 syntax: 正規表現パターン文法 # void onig_copy_syntax(OnigSyntaxType* to, const OnigSyntaxType* from) 正規表現パターン文法をコピーする。 引数 1 to: 対象 2 from: 元 # unsigned int onig_get_syntax_op(OnigSyntaxType* syntax) # unsigned int onig_get_syntax_op2(OnigSyntaxType* syntax) # unsigned int onig_get_syntax_behavior(OnigSyntaxType* syntax) # OnigOptionType onig_get_syntax_options(OnigSyntaxType* syntax) # void onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op) # void onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2) # void onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior) # void onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options) 正規表現パターン文法の要素を参照/取得する。 引数 1 syntax: 正規表現パターン文法 2 op, op2, behavior, options: 要素の値 # void onig_copy_encoding(OnigEncoding to, OnigOnigEncoding from) 文字エンコーディングをコピーする。 引数 1 to: 対象 2 from: 元 # int onig_set_meta_char(OnigSyntaxType* syntax, unsigned int what, OnigCodePoint code) メタ文字を指定したコードポイント値にセットする。 ONIG_SYN_OP_VARIABLE_META_CHARACTERSが正規表現パターン文法で有効に なっていない場合には、エスケープ文字を除いて、ここで指定したメタ文字は 機能しない。(組込みの文法では有効にしていない。) 正常終了戻り値: ONIG_NORMAL 引数 1 syntax: 対象文法 2 what: メタ文字機能の指定 ONIG_META_CHAR_ESCAPE ONIG_META_CHAR_ANYCHAR ONIG_META_CHAR_ANYTIME ONIG_META_CHAR_ZERO_OR_ONE_TIME ONIG_META_CHAR_ONE_OR_MORE_TIME ONIG_META_CHAR_ANYCHAR_ANYTIME 3 code: メタ文字のコードポイント または ONIG_INEFFECTIVE_META_CHAR. # OnigCaseFoldType onig_get_default_case_fold_flag() デフォルトのcase foldフラグを取得する。 # int onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag) デフォルトのcase foldフラグをセットする。 引数 1 case_fold_flag: case foldフラグ # unsigned int onig_get_match_stack_limit_size(void) マッチスタックサイズの最大値を返す。 (デフォルト: 0 == 無制限) # int onig_set_match_stack_limit_size(unsigned int size) マッチスタックサイズの最大値を指定する。 (size = 0: 無制限) 正常終了戻り値: ONIG_NORMAL # int onig_end(void) ライブラリの使用を終了する。 正常終了戻り値: ONIG_NORMAL onig_init()を再度呼び出しても、以前に作成した正規表現オブジェクト を使用することはできない。 # const char* onig_version(void) バージョン文字列を返す。(例 "5.0.3") // END ================================================ FILE: src/Onigmo/doc/FAQ ================================================ FAQ 2011/09/18 1. Longest match You can execute longest match by using ONIG_OPTION_FIND_LONGEST option in onig_new(). 2. Thread safe In order to make thread safe, which of (A) or (B) must be done. (A) Onigmo Layer Define the macro below in oniguruma/regint.h. USE_MULTI_THREAD_SYSTEM THREAD_ATOMIC_START THREAD_ATOMIC_END THREAD_PASS THREAD_SYSTEM_INIT THREAD_SYSTEM_END (B) Application Layer The plural threads should not do simultaneously that making new regexp objects or re-compiling objects or freeing objects, even if these objects are differ. 3. CR + LF DOS newline (CR (0x0c) + LF (0x0a) sequence) Enable the following line in regenc.h, and use ONIG_OPTION_NEWLINE_CRLF option in onig_new(). /* #define USE_CRNL_AS_LINE_TERMINATOR */ 4. Mailing list There is no mailing list about Onigmo/Oniguruma. // END ================================================ FILE: src/Onigmo/doc/FAQ.ja ================================================ FAQ 2011/09/18 1. 最長マッチ onig_new()の中で、ONIG_OPTION_FIND_LONGESTオプション を使用すれば最長マッチになる。 2. スレッドセーフ スレッドセーフにするには、以下の(A)と(B)のどちらかを行なえば よい。 (A) Onigmo Layer oniguruma/regint.hの中の以下のマクロを定義する。 USE_MULTI_THREAD_SYSTEM THREAD_ATOMIC_START THREAD_ATOMIC_END THREAD_PASS 何らかの初期化/終了処理が必要であれば、以下のマクロに定義する。 THREAD_SYSTEM_INIT THREAD_SYSTEM_END (B) Application Layer 同時に複数のスレッドが、正規表現オブジェクトを作成する、 または解放する、ことを行なってはならない。 それらのオブジェクトが全く別のものであっても。 もう少し詳しい説明は、このドキュメントの中の "スレッドセーフに関する補足"に書いておいた。 3. CR + LF DOSの改行(CR(0x0c) + LF(0x0a)の連続) regenc.hの中の、以下の部分を有効にし、onig_new()で ONIG_OPTION_NEWLINE_CRLFオプションを使用する。 /* #define USE_CRNL_AS_LINE_TERMINATOR */ 4. メーリングリスト 鬼雲/鬼車に関するメーリングリストは存在しない。 //END スレッドセーフに関する補足 スレッドセーフにするには、個別のアプリケーションの中で行うか、 Onigurumaライブラリの中で行うか、どちらかを選ぶことができます。 (Onigurumaを使用する側で対処するか、Onigurumaに対処させるか どちらか片方で行う必要があるということです。) これらの方法について、以下(A)と(B)で説明します。 マルチスレッドAPIは、それぞれのプラットフォームによっても 異なりますので、以下の説明の中で具体的に何を呼ぶのかを 書くことは無理です。実際に使用されるマルチスレッドAPIで、 対応する機能のものを指定してください。 (A) Onigurumaの中で対応する場合 oniguruma/regint.hの中で以下のマクロを定義して再コンパイルしてください。 USE_MULTI_THREAD_SYSTEM 単に有効にすればよいです。 THREAD_ATOMIC_START THREAD_ATOMIC_END THREAD_ATOMIC_STARTからTHREAD_ATOMIC_ENDで囲まれた プログラムのコード部分をあるスレッドが実行中に、他の スレッドに実行権が移動しないことを保障するものに定義 してください。 (名前の通り、囲まれたコード部分をスレッドアトミックに するという意味) THREAD_PASS これを実行したスレッドから、他のスレッドに実行権を委譲 するものに定義をしてください。(再スケジュールを呼び出す という意味) 対応する機能が全くなければ、空定義にしてください。 (参考例) Rubyの場合を例にすると、 Rubyは自分自身で独自のスレッド機能を実装しています。 その機能を使用すると、以下のように定義すればよいことに なります。 #define USE_MULTI_THREAD_SYSTEM #define THREAD_SYSTEM_INIT #define THREAD_SYSTEM_END #define THREAD_ATOMIC_START DEFER_INTS #define THREAD_ATOMIC_END ENABLE_INTS #define THREAD_PASS rb_thread_schedule() Rubyの場合、タイマ割り込みを使用して、スレッドの切り替えを 行っています。DEFER_INTSは割り込みハンドラの実行を一時的に 止めるためのマクロです。ENABLE_INTSマクロで割り込みハンドラ の実行を許可します。 これによって、THREAD_ATOMIC_STARTからTHREAD_ATOMIC_END で囲まれた部分の実行中に、他のスレッドに実行権が移動しません。 (B) アプリケーションの中で対応する場合 以下を保障するように、スレッドの実行を制御してください。 同時に複数のスレッドが、正規表現オブジェクトを作成する、または解放する、ことを 行なってはならない。それらのオブジェクトが全く別のものであっても。 onig_new(), onig_new_deluxe(), onig_free()のどれかの呼び出しを、 複数のスレッドが同時に実行することを避けてください。同時でなければ別にかまいません。 これは何故必要なのかというと、正規表現オブジェクトを作成する 過程で、内部で共通に参照するテーブルがあります。 このテーブルに対してのデータ登録処理が複数のスレッドで衝突して 異常な状態にならないために必要です。 // END ================================================ FILE: src/Onigmo/doc/RE ================================================ Onigmo (Oniguruma-mod) Regular Expressions Version 5.13.0 2012/01/19 syntax: ONIG_SYNTAX_RUBY (default) 1. Syntax elements \ escape (enable or disable meta character meaning) | alternation (...) group [...] character class 2. Characters \t horizontal tab (0x09) \v vertical tab (0x0B) \n newline (0x0A) \r return (0x0D) \b back space (0x08) \f form feed (0x0C) \a bell (0x07) \e escape (0x1B) \nnn octal char (encoded byte value) \xHH hexadecimal char (encoded byte value) \x{7HHHHHHH} wide hexadecimal char (character code point value) \cx control char (character code point value) \C-x control char (character code point value) \M-x meta (x|0x80) (character code point value) \M-\C-x meta control char (character code point value) (* \b is effective in character class [...] only) 3. Character types . any character (except newline) \w word character Not Unicode: alphanumeric and "_". Unicode: General_Category -- (Letter|Mark|Number|Connector_Punctuation) It depends on ONIG_OPTION_ASCII_RANGE option that non-ASCII char includes or not. \W non word char \s whitespace char Not Unicode: \t, \n, \v, \f, \r, \x20 Unicode: 0009, 000A, 000B, 000C, 000D, 0085(NEL), General_Category -- Line_Separator -- Paragraph_Separator -- Space_Separator It depends on ONIG_OPTION_ASCII_RANGE option that non-ASCII char includes or not. \S non whitespace char \d decimal digit char Unicode: General_Category -- Decimal_Number It depends on ONIG_OPTION_ASCII_RANGE option that non-ASCII char includes or not. \D non decimal digit char \h hexadecimal digit char [0-9a-fA-F] \H non hexadecimal digit char Character Property * \p{property-name} * \p{^property-name} (negative) * \P{property-name} (negative) property-name: + works on all encodings Alnum, Alpha, Blank, Cntrl, Digit, Graph, Lower, Print, Punct, Space, Upper, XDigit, Word, ASCII, + works on EUC_JP, Shift_JIS, CP932 Hiragana, Katakana, Han, Latin, Greek, Cyrillic + works on UTF8, UTF16, UTF32 see UnicodeProps.txt \R Linebreak Unicode: (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) Not Unicode: (?>\x0D\x0A|[\x0A-\x0D]) \X eXtended grapheme cluster Unicode: (?>\P{M}\p{M}*) Not Unicode: (?m:.) 4. Quantifier greedy ? 1 or 0 times * 0 or more times + 1 or more times {n,m} at least n but not more than m times {n,} at least n times {,n} at least 0 but not more than n times ({0,n}) {n} n times reluctant ?? 1 or 0 times *? 0 or more times +? 1 or more times {n,m}? at least n but not more than m times {n,}? at least n times {,n}? at least 0 but not more than n times (== {0,n}?) possessive (greedy and does not backtrack after repeated) ?+ 1 or 0 times *+ 0 or more times ++ 1 or more times ({n,m}+, {n,}+, {n}+ are possessive op. in ONIG_SYNTAX_JAVA and ONIG_SYNTAX_PERL only) ex. /a*+/ === /(?>a*)/ 5. Anchors ^ beginning of the line $ end of the line \b word boundary \B not word boundary \A beginning of string \Z end of string, or before newline at the end \z end of string \G matching start position 6. Character class ^... negative class (lowest precedence operator) x-y range from x to y [...] set (character class in character class) ..&&.. intersection (low precedence at the next of ^) ex. [a-w&&[^c-g]z] ==> ([a-w] AND ([^c-g] OR z)) ==> [abh-w] * If you want to use '[', '-', ']' as a normal character in a character class, you should escape these characters by '\'. POSIX bracket ([:xxxxx:], negate [:^xxxxx:]) Not Unicode Case: alnum alphabet or digit char alpha alphabet ascii code value: [0 - 127] blank \t, \x20 cntrl digit 0-9 graph \x21-\x7E and all of multibyte encoded characters lower print \x20-\x7E and all of multibyte encoded characters punct space \t, \n, \v, \f, \r, \x20 upper xdigit 0-9, a-f, A-F word alphanumeric, "_" and multibyte characters Unicode Case: alnum Letter | Mark | Decimal_Number alpha Letter | Mark ascii 0000 - 007F blank Space_Separator | 0009 cntrl Control | Format | Unassigned | Private_Use | Surrogate digit Decimal_Number graph [[:^space:]] && ^Control && ^Unassigned && ^Surrogate lower Lowercase_Letter print [[:graph:]] | Space_Separator punct Connector_Punctuation | Dash_Punctuation | Close_Punctuation | Final_Punctuation | Initial_Punctuation | Other_Punctuation | Open_Punctuation space Space_Separator | Line_Separator | Paragraph_Separator | 0009 | 000A | 000B | 000C | 000D | 0085 upper Uppercase_Letter xdigit 0030 - 0039 | 0041 - 0046 | 0061 - 0066 (0-9, a-f, A-F) word Letter | Mark | Decimal_Number | Connector_Punctuation It depends on ONIG_OPTION_ASCII_RANGE option and ONIG_OPTION_POSIX_BRACKET_ALL_RANGE option that POSIX brackets match non-ASCII char or not. 7. Extended groups (?#...) comment (?imxdau-imx) option on/off i: ignore case m: multi-line (dot(.) match newline) x: extended form character set option (character range option) d: Default (compatible with Ruby 1.9.3) \w, \d and \s doesn't match non-ASCII characters. \b, \B and POSIX brackets use the each encoding's rules. a: ASCII ONIG_OPTION_ASCII_RANGE option is turned on. \w, \d, \s and POSIX brackets doesn't match non-ASCII characters. \b and \B use the ASCII rules. u: Unicode ONIG_OPTION_ASCII_RANGE option is turned off. \w (\W), \d (\D), \s (\S), \b (\B) and POSIX brackets use the each encoding's rules. (?imxdau-imx:subexp) option on/off for subexp (?:subexp) not captured group (subexp) captured group (?=subexp) look-ahead (?!subexp) negative look-ahead (?<=subexp) look-behind (?subexp) atomic group don't backtrack in subexp. (?subexp), (?'name'subexp) define named group (All characters of the name must be a word character.) Not only a name but a number is assigned like a captured group. Assigning the same name as two or more subexps is allowed. In this case, a subexp call can not be performed although the back reference is possible. (ONIG_SYNTAX_PERL: a subexp call is allowed in this case.) (?(cond)yes-subexp), (?(cond)yes-subexp|no-subexp) conditional expression Matches yes-subexp if (cond) yields a true value, matches no-subexp otherwise. Following (cond) can be used: (n) (n >= 1) Checks if the numbered capturing group has matched something. (), ('name') Checks if a group with the given name has matched something. 8. Back reference \n back reference by group number (n >= 1) \k back reference by group number (n >= 1) \k'n' back reference by group number (n >= 1) \k<-n> back reference by relative group number (n >= 1) \k'-n' back reference by relative group number (n >= 1) \k back reference by group name \k'name' back reference by group name In the back reference by the multiplex definition name, a subexp with a large number is referred to preferentially. (When not matched, a group of the small number is referred to.) * Back reference by group number is forbidden if named group is defined in the pattern and ONIG_OPTION_CAPTURE_GROUP is not set. * ONIG_SYNTAX_PERL: \g{n}, \g{-n} and \g{name} can also be used. back reference with nest level level: 0, 1, 2, ... \k (n >= 1) \k (n >= 1) \k'n+level' (n >= 1) \k'n-level' (n >= 1) \k<-n+level> (n >= 1) \k<-n-level> (n >= 1) \k'-n+level' (n >= 1) \k'-n-level' (n >= 1) \k \k \k'name+level' \k'name-level' Destinate relative nest level from back reference position. ex 1. /\A(?|.|(?:(?.)\g\k))\z/.match("reer") ex 2. r = Regexp.compile(<<'__REGEXP__'.strip, Regexp::EXTENDED) (? \g \g* \g ){0} (? < \g \s* > ){0} (? [a-zA-Z_:]+ ){0} (? [^<&]+ (\g | [^<&]+)* ){0} (? >){0} \g __REGEXP__ p r.match('fbbbf').captures 9. Subexp call ("Tanaka Akira special") \g call by group name \g'name' call by group name \g call by group number (n >= 1) \g'n' call by group number (n >= 1) \g<0> call the whole pattern recursively \g'0' call the whole pattern recursively \g<-n> call by relative group number (n >= 1) \g'-n' call by relative group number (n >= 1) \g<+n> call by relative group number (n >= 1) \g'+n' call by relative group number (n >= 1) * left-most recursive call is not allowed. ex. (?a|\gb) => error (?a|b\gc) => OK * Call by group number is forbidden if named group is defined in the pattern and ONIG_OPTION_CAPTURE_GROUP is not set. * If the option status of called group is different from calling position then the group's option is effective. ex. (?-i:\g)(?i:(?a)){0} match to "A" * ONIG_SYNTAX_PERL: use (?&name), (?n), (?-n), (?+n), (?R) or (?0) instead. 10. Captured group Behavior of the no-named group (...) changes with the following conditions. (But named group is not changed.) case 1. /.../ (named group is not used, no option) (...) is treated as a captured group. case 2. /.../g (named group is not used, 'g' option) (...) is treated as a no-captured group (?:...). case 3. /..(?..)../ (named group is used, no option) (...) is treated as a no-captured group (?:...). numbered-backref/call is not allowed. case 4. /..(?..)../G (named group is used, 'G' option) (...) is treated as a captured group. numbered-backref/call is allowed. where g: ONIG_OPTION_DONT_CAPTURE_GROUP G: ONIG_OPTION_CAPTURE_GROUP ('g' and 'G' options are argued in ruby-dev ML) ----------------------------- A-1. Syntax depend options + ONIG_SYNTAX_RUBY (?m): dot(.) match newline + ONIG_SYNTAX_PERL, ONIG_SYNTAX_JAVA and ONIG_SYNTAX_PYTHON (?s): dot(.) match newline (?m): ^ match after newline, $ match before newline + ONIG_SYNTAX_PERL (?d), (?l): same as (?u) A-2. Original extensions + hexadecimal digit char type \h, \H + named group (?...), (?'name'...) + named backref \k + subexp call \g, \g A-3. Lacked features compare with perl 5.14.0 + \N{name}, \N{U+xxxx}, \N + \l,\u,\L,\U, \C + \v, \V, \h, \H, \o{xxx} + (?{code}) + (??{code}) + (?|...) + (*VERB:ARG) * \Q...\E This is effective on ONIG_SYNTAX_PERL and ONIG_SYNTAX_JAVA. A-4. Differences with Japanized GNU regex(version 0.12) of Ruby 1.8 + add character property (\p{property}, \P{property}) + add hexadecimal digit char type (\h, \H) + add look-behind (?<=fixed-char-length-pattern), (?>]/ in EUC-JP encoding. + effect range of isolated option is to next ')'. ex. (?:(?i)a|b) is interpreted as (?:(?i:a|b)), not (?:(?i:a)|b). + isolated option is not transparent to previous pattern. ex. a(?i)* is a syntax error pattern. + allowed incomplete left brace as an usual string. ex. /{/, /({)/, /a{2,3/ etc... + negative POSIX bracket [:^xxxx:] is supported. + POSIX bracket [:ascii:] is added. + repeat of look-ahead is not allowed. ex. /(?=a)*/, /(?!b){5}/ + Ignore case option is effective to numbered character. ex. /\x61/i =~ "A" + In the range quantifier, the number of the minimum is omissible. /a{,n}/ == /a{0,n}/ The simultaneous abbreviation of the number of times of the minimum and the maximum is not allowed. (/a{,}/) + /a{n}?/ is not a non-greedy operator. /a{n}?/ == /(?:a{n})?/ + invalid back reference is checked and cause error. /\1/, /(a)\2/ + Zero-length match in infinite repeat stops the repeat, then changes of the capture group status are checked as stop condition. /(?:()|())*\1\2/ =~ "" /(?:\1a|())*/ =~ "a" A-5. Disabled functions by default syntax + capture history (?@...) and (?@...) ex. /(?@a)*/.match("aaa") ==> [<0-1>, <1-2>, <2-3>] see sample/listcap.c file. A-6. Problems + Invalid encoding byte sequence is not checked. ex. UTF-8 * Invalid first byte is treated as a character. /./u =~ "\xa3" * Incomplete byte sequence is not checked. /\w+/ =~ "a\xf3\x8ec" // END ================================================ FILE: src/Onigmo/doc/RE.ja ================================================ 鬼雲 (鬼車改) 正規表現 Version 5.13.0 2012/01/19 使用文法: ONIG_SYNTAX_RUBY (既定値) 1. 基本要素 \ 退避修飾 (エスケープ) 正規表現記号の有効/無効の制御 | 選択子 (...) 式集合 (グループ) [...] 文字集合 (文字クラス) 2. 文字 \t 水平タブ (0x09) \v 垂直タブ (0x0B) \n 改行 (0x0A) \r 復帰 (0x0D) \b 後退空白 (0x08) \f 改頁 (0x0C) \a 鐘 (0x07) \e 退避修飾 (0x1B) \nnn 八進数表現 符号化バイト値(の一部) \xHH 十六進数表現 符号化バイト値(の一部) \x{7HHHHHHH} 拡張十六進数表現 コードポイント値 \cx 制御文字表現 コードポイント値 \C-x 制御文字表現 コードポイント値 \M-x 超 (x|0x80) コードポイント値 \M-\C-x 超 + 制御文字表現 コードポイント値 ※ \bは、文字集合内でのみ有効 3. 文字種 . 任意文字 (改行を除く) \w 単語構成文字 Unicode以外の場合: 英数字 および "_"。 Unicodeの場合: General_Category -- (Letter|Mark|Number|Connector_Punctuation) ASCII外の文字を含むかどうかは ONIG_OPTION_ASCII_RANGE オプションに 依存する。 \W 非単語構成文字 \s 空白文字 Unicode以外の場合: \t, \n, \v, \f, \r, \x20 Unicodeの場合: 0009, 000A, 000B, 000C, 000D, 0085(NEL), General_Category -- Line_Separator -- Paragraph_Separator -- Space_Separator ASCII外の文字を含むかどうかは ONIG_OPTION_ASCII_RANGE オプションに 依存する。 \S 非空白文字 \d 10進数字 Unicodeの場合: General_Category -- Decimal_Number ASCII外の文字を含むかどうかは ONIG_OPTION_ASCII_RANGE オプションに 依存する。 \D 非10進数字 \h 16進数字 [0-9a-fA-F] \H 非16進数字 Character Property * \p{property-name} * \p{^property-name} (negative) * \P{property-name} (negative) property-name: + 全てのエンコーディングで有効 Alnum, Alpha, Blank, Cntrl, Digit, Graph, Lower, Print, Punct, Space, Upper, XDigit, Word, ASCII, + EUC-JP, Shift_JIS, CP932で有効 Hiragana, Katakana, Han, Latin, Greek, Cyrillic + UTF8, UTF16, UTF32で有効 UnicodeProps.txt 参照 \R 改行文字 (Linebreak) Unicodeの場合: (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) Unicode以外の場合: (?>\x0D\x0A|[\x0A-\x0D]) \X eXtended grapheme cluster Unicodeの場合: (?>\P{M}\p{M}*) Unicode以外の場合: (?m:.) 4. 量指定子 欲張り ? 一回または零回 * 零回以上 + 一回以上 {n,m} n回以上m回以下 {n,} n回以上 {,n} 零回以上n回以下 ({0,n}) {n} n回 無欲 ?? 一回または零回 *? 零回以上 +? 一回以上 {n,m}? n回以上m回以下 {n,}? n回以上 {,n}? 零回以上n回以下 (== {0,n}?) 強欲 (欲張りで、繰り返しに成功した後は回数を減らすような後退再試行をしない) ?+ 一回または零回 *+ 零回以上 ++ 一回以上 ({n,m}+, {n,}+, {n}+ は、ONIG_SYNTAX_JAVAとONIG_SYNTAX_PERLでのみ強欲な 指定子) 例. /a*+/ === /(?>a*)/ 5. 錨 ^ 行頭 $ 行末 \b 単語境界 \B 非単語境界 \A 文字列先頭 \Z 文字列末尾、または文字列末尾の改行の直前 \z 文字列末尾 \G 照合開始位置 6. 文字集合 ^... 否定 (最低優先度演算子) x-y 範囲 (xからyまで) [...] 集合 (文字集合内文字集合) ..&&.. 積演算 (^の次に優先度が低い演算子) 例. [a-w&&[^c-g]z] ==> ([a-w] and ([^c-g] or z)) ==> [abh-w] ※ '[', '-', ']'を、文字集合内で通常文字の意味で使用したい場合には、 これらの文字を'\'で退避修飾しなければならない。 POSIXブラケット ([:xxxxx:], 否定 [:^xxxxx:]) Unicode以外の場合: alnum 英数字 alpha 英字 ascii 0 - 127 blank \t, \x20 cntrl digit 0-9 graph \x21-\x7E および 多バイト文字全部を含む lower print \x20-\x7E および 多バイト文字全部を含む punct space \t, \n, \v, \f, \r, \x20 upper xdigit 0-9, a-f, A-F word 英数字, "_" および 多バイト文字 Unicodeの場合: alnum Letter | Mark | Decimal_Number alpha Letter | Mark ascii 0000 - 007F blank Space_Separator | 0009 cntrl Control | Format | Unassigned | Private_Use | Surrogate digit Decimal_Number graph [[:^space:]] && ^Control && ^Unassigned && ^Surrogate lower Lowercase_Letter print [[:graph:]] | Space_Separator punct Connector_Punctuation | Dash_Punctuation | Close_Punctuation | Final_Punctuation | Initial_Punctuation | Other_Punctuation | Open_Punctuation space Space_Separator | Line_Separator | Paragraph_Separator | 0009 | 000A | 000B | 000C | 000D | 0085 upper Uppercase_Letter xdigit 0030 - 0039 | 0041 - 0046 | 0061 - 0066 (0-9, a-f, A-F) word Letter | Mark | Decimal_Number | Connector_Punctuation POSIXブラケットがASCII外の文字にマッチするかどうかは ONIG_OPTION_ASCII_RANGEオプションとONIG_OPTION_POSIX_BRACKET_ALL_RANGE オプションに依存する。 7. 拡張式集合 (?#...) 注釈 (?imxdau-imx) 孤立オプション i: 大文字小文字照合 m: 複数行 x: 拡張形式 文字集合オプション (文字範囲オプション) d: デフォルト (Ruby 1.9.3 互換) \w, \d, \s は、非ASCII文字にマッチしない。 \b, \B, POSIXブラケットは、各エンコーディングの ルールに従う。 a: ASCII ONIG_OPTION_ASCII_RANGEオプションがオンになる。 \w, \d, \s, POSIXブラケットは、非ASCII文字に マッチしない。 \b, \B は、ASCIIのルールに従う。 u: Unicode ONIG_OPTION_ASCII_RANGEオプションがオフになる。 \w (\W), \d (\D), \s (\S), \b (\B), POSIXブラケット は、各エンコーディングのルールに従う。 (?imxdau-imx:式) 式オプション (式) 捕獲式集合 (?:式) 非捕獲式集合 (?=式) 先読み (?!式) 否定先読み (?<=式) 戻り読み (?式) 原子的式集合 式全体を通過したとき、式の中での後退再試行を行なわない (?式), (?'name'式) 名前付き捕獲式集合 式集合に名前を割り当てる(定義する)。 (名前は単語構成文字でなければならない。) 名前だけでなく、捕獲式集合と同様に番号も割り当てられる。 番号指定が禁止されていない状態 (10. 捕獲式集合 を参照) のときは、名前を使わないで番号でも参照できる。 複数の式集合に同じ名前を与えることは許されている。 この場合には、この名前を使用した後方参照は可能であるが、 部分式呼出しはできない。 (ONIG_SYNTAX_PERLでは部分式呼出しも可能。) (?(条件)真の式), (?(条件)真の式|偽の式) 条件式 (条件)が真であれば真の式がマッチし、偽であれば偽の式が マッチする。 (条件)には以下のものが使用できる。 (n) (n >= 1) 番号指定の後方参照が何かにマッチしていれば真、 マッチしていなければ偽 (), ('name') 名前指定の後方参照が何かにマッチしていれば真、 マッチしていなければ偽 8. 後方参照 \n 番号指定参照 (n >= 1) \k 番号指定参照 (n >= 1) \k'n' 番号指定参照 (n >= 1) \k<-n> 相対番号指定参照 (n >= 1) \k'-n' 相対番号指定参照 (n >= 1) \k 名前指定参照 \k'name' 名前指定参照 名前指定参照で、その名前が複数の式集合で多重定義されている場合には、 番号の大きい式集合から優先的に参照される。 (マッチしないときには番号の小さい式集合が参照される) ※ 番号指定参照は、名前付き捕獲式集合が定義され、 かつ ONIG_OPTION_CAPTURE_GROUPが指定されていない場合には、 禁止される。(10. 捕獲式集合 を参照) ※ ONIG_SYNTAX_PERLでは、\g{n}, \g{-n}, \g{name} も使用可能。 ネストレベル付き後方参照 level: 0, 1, 2, ... \k (n >= 1) \k (n >= 1) \k'n+level' (n >= 1) \k'n-level' (n >= 1) \k<-n+level> (n >= 1) \k<-n-level> (n >= 1) \k'-n+level' (n >= 1) \k'-n-level' (n >= 1) \k \k \k'name+level' \k'name-level' 後方参照の位置から相対的な部分式呼出しネストレベルを指定して、そのレベルでの 捕獲値を参照する。 例-1. /\A(?|.|(?:(?.)\g\k))\z/.match("reer") 例-2. r = Regexp.compile(<<'__REGEXP__'.strip, Regexp::EXTENDED) (? \g \g* \g ){0} (? < \g \s* > ){0} (? [a-zA-Z_:]+ ){0} (? [^<&]+ (\g | [^<&]+)* ){0} (? >){0} \g __REGEXP__ p r.match('fbbbf').captures 9. 部分式呼出し ("田中哲スペシャル") \g 名前指定呼出し \g'name' 名前指定呼出し \g 番号指定呼出し (n >= 1) \g'n' 番号指定呼出し (n >= 1) \g<0> パターン全体の再帰呼び出し \g'0' パターン全体の再帰呼び出し \g<-n> 相対番号指定呼出し (n >= 1) \g'-n' 相対番号指定呼出し (n >= 1) \g<+n> 相対番号指定呼出し (n >= 1) \g'+n' 相対番号指定呼出し (n >= 1) ※ 最左位置での再帰呼出しは禁止される。 例. (?a|\gb) => error (?a|b\gc) => OK ※ 番号指定呼出しは、名前付き捕獲式集合が定義され、 かつ ONIG_OPTION_CAPTURE_GROUPが指定されていない場合には、 禁止される。 (10. 捕獲式集合 を参照) ※ 呼び出された式集合のオプション状態が呼出し側のオプション状態と異なっている とき、呼び出された側のオプション状態が有効である。 例. (?-i:\g)(?i:(?a)){0} は "A" に照合成功する。 ※ ONIG_SYNTAX_PERLでは代わりに (?&name), (?n), (?-n), (?+n), (?R), (?0) を 使用する。 10. 捕獲式集合 捕獲式集合(...)は、以下の条件に応じて振舞が変化する。 (名前付き捕獲式集合は変化しない) case 1. /.../ (名前付き捕獲式集合は不使用、オプションなし) (...) は、捕獲式集合として扱われる。 case 2. /.../g (名前付き捕獲式集合は不使用、オプション 'g'を指定) (...) は、非捕獲式集合として扱われる。 case 3. /..(?..)../ (名前付き捕獲式集合は使用、オプションなし) (...) は、非捕獲式集合として扱われる。 番号指定参照/呼び出しは不許可。 case 4. /..(?..)../G (名前付き捕獲式集合は使用、オプション 'G'を指定) (...) は、捕獲式集合として扱われる。 番号指定参照/呼び出しは許可。 但し g: ONIG_OPTION_DONT_CAPTURE_GROUP G: ONIG_OPTION_CAPTURE_GROUP ('g'と'G'オプションは、ruby-dev MLで議論された。) これらの振舞の意味は、 名前付き捕獲と名前無し捕獲を同時に使用する必然性のある場面は少ないであろう という理由から考えられたものである。 ----------------------------- 補記 1. 文法依存オプション + ONIG_SYNTAX_RUBY (?m): 終止符記号(.)は改行と照合成功 + ONIG_SYNTAX_PERL、ONIG_SYNTAX_JAVA、ONIG_SYNTAX_PYTHON (?s): 終止符記号(.)は改行と照合成功 (?m): ^ は改行の直後に照合する、$ は改行の直前に照合する + ONIG_SYNTAX_PERL (?d), (?l): (?u)と同じ 補記 2. 独自拡張機能 + 16進数数字、非16進数字 \h, \H + 名前付き捕獲式集合 (?...), (?'name'...) + 名前指定後方参照 \k + 部分式呼出し \g, \g 補記 3. Perl 5.14.0と比較して存在しない機能 + \N{name}, \N{U+xxxx}, \N + \l,\u,\L,\U, \C + \v, \V, \h, \H, \o{xxx} + (?{code}) + (??{code}) + (?|...) + (*VERB:ARG) * \Q...\E 但しONIG_SYNTAX_PERLとONIG_SYNTAX_JAVAでは有効 補記 4. Ruby 1.8 の日本語化 GNU regex(version 0.12)との違い + 文字Property機能追加 (\p{property}, \P{Property}) + 16進数字タイプ追加 (\h, \H) + 戻り読み機能を追加 + 強欲な繰り返し指定子を追加 (?+, *+, ++) + 文字集合の中の演算子を追加 ([...], &&) ('[' は、文字集合の中で通常の文字として使用するときには 退避修飾しなければならない) + 名前付き捕獲式集合と、部分式呼出し機能追加 + 多バイト文字コードが指定されているとき、 文字集合の中で八進数または十六進数表現の連続は、多バイト符合で表現された 一個の文字と解釈される (例. [\xa1\xa2], [\xa1\xa7-\xa4\xa1]) + 文字集合の中で、一バイト文字と多バイト文字の範囲指定は許される。 ex. /[a-あ]/ + 孤立オプションの有効範囲は、その孤立オプションを含んでいる式集合の 終わりまでである 例. (?:(?i)a|b) は (?:(?i:a|b)) と解釈される、(?:(?i:a)|b)ではない + 孤立オプションはその前の式に対して透過的ではない 例. /a(?i)*/ は文法エラーとなる + 不完全な繰り返し範囲指定子は通常の文字列として許可される 例. /{/, /({)/, /a{2,3/ + 否定的POSIXブラケット [:^xxxx:] を追加 + POSIXブラケット [:ascii:] を追加 + 先読みの繰り返しは不許可 例. /(?=a)*/, /(?!b){5}/ + 数値で指定された文字に対しても、大文字小文字照合オプションは有効 例. /\x61/i =~ "A" + 繰り返し回数指定で、最低回数の省略(0回)ができる /a{,n}/ == /a{0,n}/ 最低回数と最大回数の同時省略は許されない。(/a{,}/) + /a{n}?/は無欲な演算子ではない。 /a{n}?/ == /(?:a{n})?/ + 無効な後方参照をチェックしてエラーにする。 /\1/, /(a)\2/ + 無限繰り返しの中で、長さ零での照合成功は繰り返しを中断させるが、 このとき、中断すべきかどうかの判定として、捕獲式集合の捕獲状態の 変化まで考慮している /(?:()|())*\1\2/ =~ "" /(?:\1a|())*/ =~ "a" 補記 5. 実装されているが、既定値では有効にしていない機能 + 捕獲履歴参照 (?@...) と (?@...) 例. /(?@a)*/.match("aaa") ==> [<0-1>, <1-2>, <2-3>] 使用方法は、sample/listcap.cを参照 有効にしていない理由は、どの程度役に立つかはっきりしないため。 補記 6. 問題点 + エンコーディングバイト値が適正な価かどうかのチェックは行なっていない。 例: UTF-8 * 先頭バイトとして不正なバイトを一文字とみなす /./u =~ "\xa3" * 不完全なバイトシーケンスのチェックをしない /\w+/u =~ "a\xf3\x8ec" これを調べることは可能ではあるが、遅くなるので行なわない。 文字列として、そのようなバイト列を指定した場合の動作は保証しない。 終り ================================================ FILE: src/Onigmo/doc/UnicodeProps.txt ================================================ Onigmo (Oniguruma-mod) Unicode Properties Version 5.13.1 2012/02/01 * POSIX brackets Alpha Blank Cntrl Digit Graph Lower Print Punct Space Upper XDigit Word Alnum ASCII * Special Any Assigned * Major and General Categories C Cc Cf Cn Co Cs L LC Ll Lm Lo Lt Lu M Mc Me Mn N Nd Nl No P Pc Pd Pe Pf Pi Po Ps S Sc Sk Sm So Z Zl Zp Zs * Scripts Arabic Armenian Avestan Balinese Bamum Batak Bengali Bopomofo Brahmi Braille Buginese Buhid Canadian_Aboriginal Carian Chakma Cham Cherokee Common Coptic Cuneiform Cypriot Cyrillic Deseret Devanagari Egyptian_Hieroglyphs Ethiopic Georgian Glagolitic Gothic Greek Gujarati Gurmukhi Han Hangul Hanunoo Hebrew Hiragana Imperial_Aramaic Inherited Inscriptional_Pahlavi Inscriptional_Parthian Javanese Kaithi Kannada Katakana Kayah_Li Kharoshthi Khmer Lao Latin Lepcha Limbu Linear_B Lisu Lycian Lydian Malayalam Mandaic Meetei_Mayek Meroitic_Cursive Meroitic_Hieroglyphs Miao Mongolian Myanmar New_Tai_Lue Nko Ogham Ol_Chiki Old_Italic Old_Persian Old_South_Arabian Old_Turkic Oriya Osmanya Phags_Pa Phoenician Rejang Runic Samaritan Saurashtra Sharada Shavian Sinhala Sora_Sompeng Sundanese Syloti_Nagri Syriac Tagalog Tagbanwa Tai_Le Tai_Tham Tai_Viet Takri Tamil Telugu Thaana Thai Tibetan Tifinagh Ugaritic Unknown Vai Yi * DerivedCoreProperties Alphabetic Case_Ignorable Cased Changes_When_Casefolded Changes_When_Casemapped Changes_When_Lowercased Changes_When_Titlecased Changes_When_Uppercased Default_Ignorable_Code_Point Grapheme_Base Grapheme_Extend Grapheme_Link ID_Continue ID_Start Lowercase Math Uppercase XID_Continue XID_Start * PropList ASCII_Hex_Digit Bidi_Control Dash Deprecated Diacritic Extender Hex_Digit Hyphen IDS_Binary_Operator IDS_Trinary_Operator Ideographic Join_Control Logical_Order_Exception Noncharacter_Code_Point Other_Alphabetic Other_Default_Ignorable_Code_Point Other_Grapheme_Extend Other_ID_Continue Other_ID_Start Other_Lowercase Other_Math Other_Uppercase Pattern_Syntax Pattern_White_Space Quotation_Mark Radical STerm Soft_Dotted Terminal_Punctuation Unified_Ideograph Variation_Selector White_Space * PropertyAliases AHex Bidi_C CI CWCF CWCM CWL CWT CWU Dep DI Dia Ext Gr_Base Gr_Ext Gr_Link Hex IDC Ideo IDS IDSB IDST Join_C LOE NChar OAlpha ODI OGr_Ext OIDC OIDS OLower OMath OUpper Pat_Syn Pat_WS QMark SD Term UIdeo VS WSpace XIDC XIDS * PropertyValueAliases (General_Category) Other Control Format Unassigned Private_Use Surrogate Letter Cased_Letter Lowercase_Letter Modifier_Letter Other_Letter Titlecase_Letter Uppercase_Letter Mark Spacing_Mark Enclosing_Mark Nonspacing_Mark Number Decimal_Number Letter_Number Other_Number Punctuation Connector_Punctation Dash_Punctation Close_Punctation Final_Punctation Initial_Punctation Other_Punctation Open_Punctation Symbol Currency_Symbol Modifier_Symbol Math_Symbol Other_Symbol Separator Line_Separator Paragraph_Separator Space_Separator * PropertyValueAliases (Script) Arab Armi Armn Avst Bali Bamu Batk Beng Bopo Brah Brai Bugi Buhd Cans Cari Cher Copt Qaac Cprt Cyrl Deva Dsrt Egyp Ethi Geor Glag Goth Grek Gujr Guru Hang Hani Hano Hebr Hira Ital Java Kali Kana Khar Khmr Knda Kthi Lana Laoo Latn Lepc Limb Linb Lyci Lydi Mand Mlym Mong Mtei Mymr Nkoo Ogam Olck Orkh Orya Osma Phag Phli Phnx Prti Rjng Runr Samr Sarb Saur Shaw Sinh Sund Sylo Syrc Tagb Tale Talu Taml Tavt Telu Tfng Tglg Thaa Tibt Ugar Vaii Xpeo Xsux Yiii Zinh Qaai Zyyy Zzzz * DerivedAges Age=1.1 Age=2.0 Age=2.1 Age=3.0 Age=3.1 Age=3.2 Age=4.0 Age=4.1 Age=5.0 Age=5.1 Age=5.2 Age=6.0 Age=6.1 * Blocks In_Basic_Latin In_Latin_1_Supplement In_Latin_Extended_A In_Latin_Extended_B In_IPA_Extensions In_Spacing_Modifier_Letters In_Combining_Diacritical_Marks In_Greek_and_Coptic In_Cyrillic In_Cyrillic_Supplement In_Armenian In_Hebrew In_Arabic In_Syriac In_Arabic_Supplement In_Thaana In_NKo In_Samaritan In_Mandaic In_Arabic_Extended_A In_Devanagari In_Bengali In_Gurmukhi In_Gujarati In_Oriya In_Tamil In_Telugu In_Kannada In_Malayalam In_Sinhala In_Thai In_Lao In_Tibetan In_Myanmar In_Georgian In_Hangul_Jamo In_Ethiopic In_Ethiopic_Supplement In_Cherokee In_Unified_Canadian_Aboriginal_Syllabics In_Ogham In_Runic In_Tagalog In_Hanunoo In_Buhid In_Tagbanwa In_Khmer In_Mongolian In_Unified_Canadian_Aboriginal_Syllabics_Extended In_Limbu In_Tai_Le In_New_Tai_Lue In_Khmer_Symbols In_Buginese In_Tai_Tham In_Balinese In_Sundanese In_Batak In_Lepcha In_Ol_Chiki In_Sundanese_Supplement In_Vedic_Extensions In_Phonetic_Extensions In_Phonetic_Extensions_Supplement In_Combining_Diacritical_Marks_Supplement In_Latin_Extended_Additional In_Greek_Extended In_General_Punctuation In_Superscripts_and_Subscripts In_Currency_Symbols In_Combining_Diacritical_Marks_for_Symbols In_Letterlike_Symbols In_Number_Forms In_Arrows In_Mathematical_Operators In_Miscellaneous_Technical In_Control_Pictures In_Optical_Character_Recognition In_Enclosed_Alphanumerics In_Box_Drawing In_Block_Elements In_Geometric_Shapes In_Miscellaneous_Symbols In_Dingbats In_Miscellaneous_Mathematical_Symbols_A In_Supplemental_Arrows_A In_Braille_Patterns In_Supplemental_Arrows_B In_Miscellaneous_Mathematical_Symbols_B In_Supplemental_Mathematical_Operators In_Miscellaneous_Symbols_and_Arrows In_Glagolitic In_Latin_Extended_C In_Coptic In_Georgian_Supplement In_Tifinagh In_Ethiopic_Extended In_Cyrillic_Extended_A In_Supplemental_Punctuation In_CJK_Radicals_Supplement In_Kangxi_Radicals In_Ideographic_Description_Characters In_CJK_Symbols_and_Punctuation In_Hiragana In_Katakana In_Bopomofo In_Hangul_Compatibility_Jamo In_Kanbun In_Bopomofo_Extended In_CJK_Strokes In_Katakana_Phonetic_Extensions In_Enclosed_CJK_Letters_and_Months In_CJK_Compatibility In_CJK_Unified_Ideographs_Extension_A In_Yijing_Hexagram_Symbols In_CJK_Unified_Ideographs In_Yi_Syllables In_Yi_Radicals In_Lisu In_Vai In_Cyrillic_Extended_B In_Bamum In_Modifier_Tone_Letters In_Latin_Extended_D In_Syloti_Nagri In_Common_Indic_Number_Forms In_Phags_pa In_Saurashtra In_Devanagari_Extended In_Kayah_Li In_Rejang In_Hangul_Jamo_Extended_A In_Javanese In_Cham In_Myanmar_Extended_A In_Tai_Viet In_Meetei_Mayek_Extensions In_Ethiopic_Extended_A In_Meetei_Mayek In_Hangul_Syllables In_Hangul_Jamo_Extended_B In_High_Surrogates In_High_Private_Use_Surrogates In_Low_Surrogates In_Private_Use_Area In_CJK_Compatibility_Ideographs In_Alphabetic_Presentation_Forms In_Arabic_Presentation_Forms_A In_Variation_Selectors In_Vertical_Forms In_Combining_Half_Marks In_CJK_Compatibility_Forms In_Small_Form_Variants In_Arabic_Presentation_Forms_B In_Halfwidth_and_Fullwidth_Forms In_Specials In_Linear_B_Syllabary In_Linear_B_Ideograms In_Aegean_Numbers In_Ancient_Greek_Numbers In_Ancient_Symbols In_Phaistos_Disc In_Lycian In_Carian In_Old_Italic In_Gothic In_Ugaritic In_Old_Persian In_Deseret In_Shavian In_Osmanya In_Cypriot_Syllabary In_Imperial_Aramaic In_Phoenician In_Lydian In_Meroitic_Hieroglyphs In_Meroitic_Cursive In_Kharoshthi In_Old_South_Arabian In_Avestan In_Inscriptional_Parthian In_Inscriptional_Pahlavi In_Old_Turkic In_Rumi_Numeral_Symbols In_Brahmi In_Kaithi In_Sora_Sompeng In_Chakma In_Sharada In_Takri In_Cuneiform In_Cuneiform_Numbers_and_Punctuation In_Egyptian_Hieroglyphs In_Bamum_Supplement In_Miao In_Kana_Supplement In_Byzantine_Musical_Symbols In_Musical_Symbols In_Ancient_Greek_Musical_Notation In_Tai_Xuan_Jing_Symbols In_Counting_Rod_Numerals In_Mathematical_Alphanumeric_Symbols In_Arabic_Mathematical_Alphabetic_Symbols In_Mahjong_Tiles In_Domino_Tiles In_Playing_Cards In_Enclosed_Alphanumeric_Supplement In_Enclosed_Ideographic_Supplement In_Miscellaneous_Symbols_And_Pictographs In_Emoticons In_Transport_And_Map_Symbols In_Alchemical_Symbols In_CJK_Unified_Ideographs_Extension_B In_CJK_Unified_Ideographs_Extension_C In_CJK_Unified_Ideographs_Extension_D In_CJK_Compatibility_Ideographs_Supplement In_Tags In_Variation_Selectors_Supplement In_Supplementary_Private_Use_Area_A In_Supplementary_Private_Use_Area_B In_No_Block ================================================ FILE: src/Onigmo/enc/ascii.c ================================================ /********************************************************************** ascii.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2006 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regenc.h" OnigEncodingType OnigEncodingASCII = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "US-ASCII", /* name */ 1, /* max byte length */ 1, /* min byte length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, onigenc_ascii_mbc_case_fold, onigenc_ascii_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, onigenc_ascii_is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/big5.c ================================================ /********************************************************************** big5.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" static const int EncLen_BIG5[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }; static int big5_mbc_enc_len(const UChar* p) { return EncLen_BIG5[*p]; } static int big5_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_BIG5[ONIG_CHARAT(p)]; } static OnigCodePoint big5_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_BIG5, p, end); } static OnigCodePoint big5_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { return onigenc_mbn_mbc_to_code_se(it, ONIG_ENCODING_BIG5, p, end); } static int big5_code_to_mbc(OnigCodePoint code, UChar *buf) { return onigenc_mb2_code_to_mbc(ONIG_ENCODING_BIG5, code, buf); } static int big5_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* lower) { return onigenc_mbn_mbc_case_fold(ONIG_ENCODING_BIG5, flag, pp, end, lower); } static int big5_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* lower) { return onigenc_mbn_mbc_case_fold_se(it, ONIG_ENCODING_BIG5, flag, pp, end, lower); } #if 0 static int big5_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_BIG5, flag, pp, end); } #endif static int big5_is_code_ctype(OnigCodePoint code, unsigned int ctype) { return onigenc_mb2_is_code_ctype(ONIG_ENCODING_BIG5, code, ctype); } static const char BIG5_CAN_BE_TRAIL_TABLE[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; #define BIG5_ISMB_FIRST(byte) (EncLen_BIG5[byte] > 1) #define BIG5_ISMB_TRAIL(byte) BIG5_CAN_BE_TRAIL_TABLE[(byte)] static UChar* big5_left_adjust_char_head(const UChar* start, const UChar* s) { const UChar *p; int len; if (s <= start) return (UChar* )s; p = s; if (BIG5_ISMB_TRAIL(*p)) { while (p > start) { if (! BIG5_ISMB_FIRST(*--p)) { p++; break; } } } len = enclen(ONIG_ENCODING_BIG5, p); if (p + len > s) return (UChar* )p; p += len; return (UChar* )(p + ((s - p) & ~1)); } static OnigPosition big5_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { OnigPosition p; int len; if (s <= start) return s; p = s; if (BIG5_ISMB_TRAIL(ONIG_CHARAT(p))) { while (p > start) { if (! BIG5_ISMB_FIRST(ONIG_CHARAT(--p))) { p++; break; } } } len = enclen_se(it, ONIG_ENCODING_BIG5, p); if (p + len > s) return p; p += len; return (p + ((s - p) & ~1)); } static int big5_is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { const UChar c = *s; return (BIG5_ISMB_TRAIL(c) ? FALSE : TRUE); } OnigEncodingType OnigEncodingBIG5 = { big5_mbc_enc_len, big5_mbc_enc_len_se, "Big5", /* name */ 2, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, big5_mbc_to_code, big5_mbc_to_code_se, onigenc_mb2_code_to_mbclen, big5_code_to_mbc, big5_mbc_case_fold, big5_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, big5_is_code_ctype, onigenc_not_support_get_ctype_code_range, big5_left_adjust_char_head, big5_left_adjust_char_head_se, big5_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/cp1251.c ================================================ /********************************************************************** cp1251.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2006-2007 Byte * K.Kosako * 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. */ #include "regenc.h" #define ENC_CP1251_TO_LOWER_CASE(c) EncCP1251_ToLowerCaseTable[c] #define ENC_IS_CP1251_CTYPE(code,ctype) \ ((EncCP1251_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncCP1251_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\220', '\203', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\232', '\213', '\234', '\235', '\236', '\237', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\242', '\242', '\274', '\244', '\264', '\246', '\247', '\270', '\251', '\272', '\253', '\254', '\255', '\256', '\277', '\260', '\261', '\263', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\276', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncCP1251_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x428c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x34a2, 0x34a2, 0x01a0, 0x30e2, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x0000, 0x01a0, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x0008, 0x0000, 0x30e2, 0x01a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x0280, 0x34a2, 0x30e2, 0x34a2, 0x01a0, 0x34a2, 0x01a0, 0x01a0, 0x34a2, 0x01a0, 0x34a2, 0x01a0, 0x01a0, 0x01a0, 0x01a0, 0x34a2, 0x01a0, 0x01a0, 0x34a2, 0x30e2, 0x30e2, 0x31e2, 0x01a0, 0x01a0, 0x30e2, 0x0000, 0x30e2, 0x01a0, 0x30e2, 0x34a2, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int cp1251_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; *lower = ENC_CP1251_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int cp1251_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); *lower = ENC_CP1251_TO_LOWER_CASE(c); (*pp)++; return 1; } static int cp1251_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_CP1251_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xb8, 0xa8 }, { 0xe0, 0xc0 }, { 0xe1, 0xc1 }, { 0xe2, 0xc2 }, { 0xe3, 0xc3 }, { 0xe4, 0xc4 }, { 0xe5, 0xc5 }, { 0xe6, 0xc6 }, { 0xe7, 0xc7 }, { 0xe8, 0xc8 }, { 0xe9, 0xc9 }, { 0xea, 0xca }, { 0xeb, 0xcb }, { 0xec, 0xcc }, { 0xed, 0xcd }, { 0xee, 0xce }, { 0xef, 0xcf }, { 0xf0, 0xd0 }, { 0xf1, 0xd1 }, { 0xf2, 0xd2 }, { 0xf3, 0xd3 }, { 0xf4, 0xd4 }, { 0xf5, 0xd5 }, { 0xf6, 0xd6 }, { 0xf7, 0xd7 }, { 0xf8, 0xd8 }, { 0xf9, 0xd9 }, { 0xfa, 0xda }, { 0xfb, 0xdb }, { 0xfc, 0xdc }, { 0xfd, 0xdd }, { 0xfe, 0xde }, { 0xff, 0xdf } }; static int cp1251_apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static int cp1251_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, p, end, items); } OnigEncodingType OnigEncodingCP1251 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "CP1251", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, cp1251_mbc_case_fold, cp1251_mbc_case_fold_se, cp1251_apply_all_case_fold, cp1251_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, cp1251_is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/cp932.c ================================================ /********************************************************************** cp932.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2009 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #define ENC_CP932 #include "sjis.c" ================================================ FILE: src/Onigmo/enc/euc_jp.c ================================================ /********************************************************************** euc_jp.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" #define eucjp_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1) static const int EncLen_EUCJP[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }; static const OnigPairCaseFoldCodes CaseFoldMap[] = { /* Fullwidth Alphabet */ { 0xa3c1, 0xa3e1 }, { 0xa3c2, 0xa3e2 }, { 0xa3c3, 0xa3e3 }, { 0xa3c4, 0xa3e4 }, { 0xa3c5, 0xa3e5 }, { 0xa3c6, 0xa3e6 }, { 0xa3c7, 0xa3e7 }, { 0xa3c8, 0xa3e8 }, { 0xa3c9, 0xa3e9 }, { 0xa3ca, 0xa3ea }, { 0xa3cb, 0xa3eb }, { 0xa3cc, 0xa3ec }, { 0xa3cd, 0xa3ed }, { 0xa3ce, 0xa3ee }, { 0xa3cf, 0xa3ef }, { 0xa3d0, 0xa3f0 }, { 0xa3d1, 0xa3f1 }, { 0xa3d2, 0xa3f2 }, { 0xa3d3, 0xa3f3 }, { 0xa3d4, 0xa3f4 }, { 0xa3d5, 0xa3f5 }, { 0xa3d6, 0xa3f6 }, { 0xa3d7, 0xa3f7 }, { 0xa3d8, 0xa3f8 }, { 0xa3d9, 0xa3f9 }, { 0xa3da, 0xa3fa }, /* Greek */ { 0xa6a1, 0xa6c1 }, { 0xa6a2, 0xa6c2 }, { 0xa6a3, 0xa6c3 }, { 0xa6a4, 0xa6c4 }, { 0xa6a5, 0xa6c5 }, { 0xa6a6, 0xa6c6 }, { 0xa6a7, 0xa6c7 }, { 0xa6a8, 0xa6c8 }, { 0xa6a9, 0xa6c9 }, { 0xa6aa, 0xa6ca }, { 0xa6ab, 0xa6cb }, { 0xa6ac, 0xa6cc }, { 0xa6ad, 0xa6cd }, { 0xa6ae, 0xa6ce }, { 0xa6af, 0xa6cf }, { 0xa6b0, 0xa6d0 }, { 0xa6b1, 0xa6d1 }, { 0xa6b2, 0xa6d2 }, { 0xa6b3, 0xa6d3 }, { 0xa6b4, 0xa6d4 }, { 0xa6b5, 0xa6d5 }, { 0xa6b6, 0xa6d6 }, { 0xa6b7, 0xa6d7 }, { 0xa6b8, 0xa6d8 }, /* Cyrillic */ { 0xa7a1, 0xa7d1 }, { 0xa7a2, 0xa7d2 }, { 0xa7a3, 0xa7d3 }, { 0xa7a4, 0xa7d4 }, { 0xa7a5, 0xa7d5 }, { 0xa7a6, 0xa7d6 }, { 0xa7a7, 0xa7d7 }, { 0xa7a8, 0xa7d8 }, { 0xa7a9, 0xa7d9 }, { 0xa7aa, 0xa7da }, { 0xa7ab, 0xa7db }, { 0xa7ac, 0xa7dc }, { 0xa7ad, 0xa7dd }, { 0xa7ae, 0xa7de }, { 0xa7af, 0xa7df }, { 0xa7b0, 0xa7e0 }, { 0xa7b1, 0xa7e1 }, { 0xa7b2, 0xa7e2 }, { 0xa7b3, 0xa7e3 }, { 0xa7b4, 0xa7e4 }, { 0xa7b5, 0xa7e5 }, { 0xa7b6, 0xa7e6 }, { 0xa7b7, 0xa7e7 }, { 0xa7b8, 0xa7e8 }, { 0xa7b9, 0xa7e9 }, { 0xa7ba, 0xa7ea }, { 0xa7bb, 0xa7eb }, { 0xa7bc, 0xa7ec }, { 0xa7bd, 0xa7ed }, { 0xa7be, 0xa7ee }, { 0xa7bf, 0xa7ef }, { 0xa7c0, 0xa7f0 }, { 0xa7c1, 0xa7f1 }, }; static int mbc_enc_len(const UChar* p) { return EncLen_EUCJP[*p]; } static int mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_EUCJP[ONIG_CHARAT(p)]; } static OnigCodePoint mbc_to_code(const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; len = mbc_enc_len(p); n = (OnigCodePoint )*p++; if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = *p++; n <<= 8; n += c; } return n; } static OnigCodePoint mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { int c, i, len; OnigCodePoint n; len = mbc_enc_len_se(it, p); n = (OnigCodePoint )ONIG_CHARAT(p++); if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = ONIG_CHARAT(p++); n <<= 8; n += c; } return n; } static int code_to_mbclen(OnigCodePoint code) { if (ONIGENC_IS_CODE_ASCII(code)) return 1; else if ((code & 0xff808080) == 0x00808080) return 3; else if ((code & 0xffff8080) == 0x00008080) return 2; else return ONIGERR_INVALID_CODE_POINT_VALUE; } #if 0 static int code_to_mbc_first(OnigCodePoint code) { int first; if ((code & 0xff0000) != 0) { first = (code >> 16) & 0xff; } else if ((code & 0xff00) != 0) { first = (code >> 8) & 0xff; } else { return (int )code; } return first; } #endif static int code_to_mbc(OnigCodePoint code, UChar *buf) { UChar *p = buf; if ((code & 0xff0000) != 0) *p++ = (UChar )(((code >> 16) & 0xff)); if ((code & 0xff00) != 0) *p++ = (UChar )(((code >> 8) & 0xff)); *p++ = (UChar )(code & 0xff); #if 1 if (mbc_enc_len(buf) != (p - buf)) return ONIGERR_INVALID_CODE_POINT_VALUE; #endif return (int )(p - buf); } static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static OnigCodePoint get_lower_case(OnigCodePoint code) { if (ONIGENC_IS_IN_RANGE(code, 0xa3c1, 0xa3da)) { /* Fullwidth Alphabet */ return (OnigCodePoint )(code + 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0xa6a1, 0xa6b8)) { /* Greek */ return (OnigCodePoint )(code + 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0xa7a1, 0xa7c1)) { /* Cyrillic */ return (OnigCodePoint )(code + 0x0030); } return code; } static OnigCodePoint get_upper_case(OnigCodePoint code) { if (ONIGENC_IS_IN_RANGE(code, 0xa3e1, 0xa3fa)) { /* Fullwidth Alphabet */ return (OnigCodePoint )(code - 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0xa6c1, 0xa6d8)) { /* Greek */ return (OnigCodePoint )(code - 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0xa7d1, 0xa7f1)) { /* Cyrillic */ return (OnigCodePoint )(code - 0x0030); } return code; } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { int len; OnigCodePoint code, code_lo, code_up; code = mbc_to_code(p, end); if (ONIGENC_IS_ASCII_CODE(code)) return onigenc_ascii_get_case_fold_codes_by_str(flag, p, end, items); len = mbc_enc_len(p); code_lo = get_lower_case(code); code_up = get_upper_case(code); if (code != code_lo) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = code_lo; return 1; } else if (code != code_up) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = code_up; return 1; } return 0; } static int mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); (*pp)++; return 1; } else { OnigCodePoint code; int len; code = get_lower_case(mbc_to_code(p, end)); len = code_to_mbc(code, lower); (*pp) += len; return len; /* return byte length of converted char to lower */ } } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (ONIGENC_IS_MBC_ASCII_SE(c)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); (*pp)++; return 1; } else { OnigCodePoint code; int len; code = get_lower_case(mbc_to_code_se(it, *pp, end)); len = code_to_mbc(code, lower); (*pp) += len; return len; /* return byte length of converted char to lower */ } } static UChar* left_adjust_char_head(const UChar* start, const UChar* s) { /* In this encoding mb-trail bytes doesn't mix with single bytes. */ const UChar *p; int len; if (s <= start) return (UChar* )s; p = s; while (!eucjp_islead(*p) && p > start) p--; len = mbc_enc_len(p); if (p + len > s) return (UChar* )p; p += len; return (UChar* )(p + ((s - p) & ~1)); } static OnigPosition left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { /* In this encoding mb-trail bytes doesn't mix with single bytes. */ OnigPosition p; int len; if (s <= start) return s; p = s; while (!eucjp_islead(ONIG_CHARAT(p)) && p > start) p--; len = mbc_enc_len_se(it, p); if (p + len > s) return p; p += len; return (p + ((s - p) & ~1)); } static int is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { const UChar c = *s; if (c <= 0x7e || c == 0x8e || c == 0x8f) return TRUE; else return FALSE; } static int PropertyInited = 0; static const OnigCodePoint** PropertyList; static int PropertyListNum; static int PropertyListSize; static hash_table_type* PropertyNameTable; static const OnigCodePoint CR_Hiragana[] = { 1, #ifdef ENC_EUC_JIS_2004 0xa4a1, 0xa4fb #else 0xa4a1, 0xa4f3 #endif }; /* CR_Hiragana */ #ifdef ENC_EUC_JIS_2004 static const OnigCodePoint CR_Katakana[] = { 5, 0x8ea6, 0x8eaf, /* JIS X 0201 Katakana */ 0x8eb1, 0x8edd, /* JIS X 0201 Katakana */ 0xa5a1, 0xa5fe, 0xa6ee, 0xa6fe, 0xa7f2, 0xa7f5, }; /* CR_Katakana */ #else static const OnigCodePoint CR_Katakana[] = { 3, 0x8ea6, 0x8eaf, /* JIS X 0201 Katakana */ 0x8eb1, 0x8edd, /* JIS X 0201 Katakana */ 0xa5a1, 0xa5f6, }; /* CR_Katakana */ #endif #ifdef ENC_EUC_JIS_2004 static const OnigCodePoint CR_Han[] = { /* EUC-JIS-2004 (JIS X 0213:2004) */ 7, /* plane 1 */ 0xa1b8, 0xa1b8, 0xaea1, 0xfefe, /* Kanji level 1, 2 and 3 */ /* plane 2 */ 0x8fa1a1, 0x8fa1fe, /* row 1 */ 0x8fa3a1, 0x8fa5fe, /* row 3 .. 5 */ 0x8fa8a1, 0x8fa8fe, /* row 8 */ 0x8faca1, 0x8faffe, /* row 12 .. 15 */ 0x8feea1, 0x8ffef6, /* row 78 .. 94 */ }; /* CR_Han */ #else static const OnigCodePoint CR_Han[] = { /* EUC-JP (JIS X 0208 based) */ 4, 0xa1b8, 0xa1b8, 0xb0a1, 0xcfd3, /* Kanji level 1 */ 0xd0a1, 0xf4a6, /* Kanji level 2 */ 0x8fb0a1, 0x8fedf3 /* JIS X 0212 Supplemental Kanji (row 16 .. 77) */ }; /* CR_Han */ #endif static const OnigCodePoint CR_Latin[] = { 4, 0x0041, 0x005a, 0x0061, 0x007a, 0xa3c1, 0xa3da, 0xa3e1, 0xa3fa, /* TODO: add raw 8 .. 11 to support EUC-JIS-2004 */ /* TODO: add JIS X 0212 row 9 .. 11 */ }; /* CR_Latin */ static const OnigCodePoint CR_Greek[] = { 2, 0xa6a1, 0xa6b8, #ifdef ENC_EUC_JIS_2004 0xa6c1, 0xa6d9, #else 0xa6c1, 0xa6d8, /* TODO: add JIS X 0212 row 6 */ #endif }; /* CR_Greek */ static const OnigCodePoint CR_Cyrillic[] = { 2, 0xa7a1, 0xa7c1, 0xa7d1, 0xa7f1, /* TODO: add JIS X 0212 row 7 */ }; /* CR_Cyrillic */ static int init_property_list(void) { int r; PROPERTY_LIST_ADD_PROP("hiragana", CR_Hiragana); PROPERTY_LIST_ADD_PROP("katakana", CR_Katakana); PROPERTY_LIST_ADD_PROP("han", CR_Han); PROPERTY_LIST_ADD_PROP("latin", CR_Latin); PROPERTY_LIST_ADD_PROP("greek", CR_Greek); PROPERTY_LIST_ADD_PROP("cyrillic", CR_Cyrillic); PropertyInited = 1; end: return r; } static int property_name_to_ctype(OnigEncoding enc, UChar* p, UChar* end) { hash_data_type ctype; UChar *s, *e; PROPERTY_LIST_INIT_CHECK; s = e = xalloca(end - p + 1); for (; p < end; p++) { *e++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); } if (onig_st_lookup_strend(PropertyNameTable, s, e, &ctype) == 0) { return onigenc_minimum_property_name_to_ctype(enc, s, e); } return (int )ctype; } static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (ctype <= ONIGENC_MAX_STD_CTYPE) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { if (CTYPE_IS_WORD_GRAPH_PRINT(ctype)) { return (code_to_mbclen(code) > 1 ? TRUE : FALSE); } } } else { PROPERTY_LIST_INIT_CHECK; ctype -= (ONIGENC_MAX_STD_CTYPE + 1); if (ctype >= (unsigned int )PropertyListNum) return ONIGERR_TYPE_BUG; return onig_is_in_code_range((UChar* )PropertyList[ctype], code); } return FALSE; } static int get_ctype_code_range(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[]) { if (ctype <= ONIGENC_MAX_STD_CTYPE) { return ONIG_NO_SUPPORT_CONFIG; } else { *sb_out = 0x80; PROPERTY_LIST_INIT_CHECK; ctype -= (ONIGENC_MAX_STD_CTYPE + 1); if (ctype >= (OnigCtype )PropertyListNum) return ONIGERR_TYPE_BUG; *ranges = PropertyList[ctype]; return 0; } } OnigEncodingType OnigEncodingEUC_JP = { mbc_enc_len, mbc_enc_len_se, "EUC-JP", /* name */ 3, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, mbc_to_code, mbc_to_code_se, code_to_mbclen, code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, property_name_to_ctype, is_code_ctype, get_ctype_code_range, left_adjust_char_head, left_adjust_char_head_se, is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/euc_kr.c ================================================ /********************************************************************** euc_kr.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" static const int EncLen_EUCKR[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }; static int euckr_mbc_enc_len(const UChar* p) { return EncLen_EUCKR[*p]; } static int euckr_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_EUCKR[ONIG_CHARAT(p)]; } static OnigCodePoint euckr_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_EUC_KR, p, end); } static OnigCodePoint euckr_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { return onigenc_mbn_mbc_to_code_se(it, ONIG_ENCODING_EUC_KR, p, end); } static int euckr_code_to_mbc(OnigCodePoint code, UChar *buf) { return onigenc_mb2_code_to_mbc(ONIG_ENCODING_EUC_KR, code, buf); } static int euckr_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* lower) { return onigenc_mbn_mbc_case_fold(ONIG_ENCODING_EUC_KR, flag, pp, end, lower); } static int euckr_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* lower) { return onigenc_mbn_mbc_case_fold_se(it, ONIG_ENCODING_EUC_KR, flag, pp, end, lower); } #if 0 static int euckr_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_EUC_KR, flag, pp, end); } #endif static int euckr_is_code_ctype(OnigCodePoint code, unsigned int ctype) { return onigenc_mb2_is_code_ctype(ONIG_ENCODING_EUC_KR, code, ctype); } #define euckr_islead(c) ((c) < 0xa1 || (c) == 0xff) static UChar* euckr_left_adjust_char_head(const UChar* start, const UChar* s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ const UChar *p; int len; if (s <= start) return (UChar* )s; p = s; while (!euckr_islead(*p) && p > start) p--; len = enclen(ONIG_ENCODING_EUC_KR, p); if (p + len > s) return (UChar* )p; p += len; return (UChar* )(p + ((s - p) & ~1)); } static OnigPosition euckr_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ OnigPosition p; int len; if (s <= start) return s; p = s; while (!euckr_islead(ONIG_CHARAT(p)) && p > start) p--; len = enclen_se(it, ONIG_ENCODING_EUC_KR, p); if (p + len > s) return p; p += len; return (p + ((s - p) & ~1)); } static int euckr_is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { const UChar c = *s; if (c <= 0x7e) return TRUE; else return FALSE; } OnigEncodingType OnigEncodingEUC_KR = { euckr_mbc_enc_len, euckr_mbc_enc_len_se, "EUC-KR", /* name */ 2, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, euckr_mbc_to_code, euckr_mbc_to_code_se, onigenc_mb2_code_to_mbclen, euckr_code_to_mbc, euckr_mbc_case_fold, euckr_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, euckr_is_code_ctype, onigenc_not_support_get_ctype_code_range, euckr_left_adjust_char_head, euckr_left_adjust_char_head_se, euckr_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; /* Same with OnigEncodingEUC_KR except the name */ OnigEncodingType OnigEncodingEUC_CN = { euckr_mbc_enc_len, euckr_mbc_enc_len_se, "EUC-CN", /* name */ 2, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, euckr_mbc_to_code, euckr_mbc_to_code_se, onigenc_mb2_code_to_mbclen, euckr_code_to_mbc, euckr_mbc_case_fold, euckr_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, euckr_is_code_ctype, onigenc_not_support_get_ctype_code_range, euckr_left_adjust_char_head, euckr_left_adjust_char_head_se, euckr_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/euc_tw.c ================================================ /********************************************************************** euc_tw.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regenc.h" static const int EncLen_EUCTW[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }; static int euctw_mbc_enc_len(const UChar* p) { return EncLen_EUCTW[*p]; } static int euctw_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_EUCTW[ONIG_CHARAT(p)]; } static OnigCodePoint euctw_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_EUC_TW, p, end); } static OnigCodePoint euctw_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { return onigenc_mbn_mbc_to_code_se(it, ONIG_ENCODING_EUC_TW, p, end); } static int euctw_code_to_mbc(OnigCodePoint code, UChar *buf) { return onigenc_mb4_code_to_mbc(ONIG_ENCODING_EUC_TW, code, buf); } static int euctw_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* lower) { return onigenc_mbn_mbc_case_fold(ONIG_ENCODING_EUC_TW, flag, pp, end, lower); } static int euctw_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* lower) { return onigenc_mbn_mbc_case_fold_se(it, ONIG_ENCODING_EUC_TW, flag, pp, end, lower); } static int euctw_is_code_ctype(OnigCodePoint code, unsigned int ctype) { return onigenc_mb4_is_code_ctype(ONIG_ENCODING_EUC_TW, code, ctype); } #define euctw_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1) static UChar* euctw_left_adjust_char_head(const UChar* start, const UChar* s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ const UChar *p; int len; if (s <= start) return (UChar* )s; p = s; while (!euctw_islead(*p) && p > start) p--; len = enclen(ONIG_ENCODING_EUC_TW, p); if (p + len > s) return (UChar* )p; p += len; return (UChar* )(p + ((s - p) & ~1)); } static OnigPosition euctw_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { /* Assumed in this encoding, mb-trail bytes don't mix with single bytes. */ OnigPosition p; int len; if (s <= start) return s; p = s; while (!euctw_islead(ONIG_CHARAT(p)) && p > start) p--; len = enclen_se(it, ONIG_ENCODING_EUC_TW, p); if (p + len > s) return p; p += len; return (p + ((s - p) & ~1)); } static int euctw_is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { const UChar c = *s; if (c <= 0x7e) return TRUE; else return FALSE; } OnigEncodingType OnigEncodingEUC_TW = { euctw_mbc_enc_len, euctw_mbc_enc_len_se, "EUC-TW", /* name */ 4, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, euctw_mbc_to_code, euctw_mbc_to_code_se, onigenc_mb4_code_to_mbclen, euctw_code_to_mbc, euctw_mbc_case_fold, euctw_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, euctw_is_code_ctype, onigenc_not_support_get_ctype_code_range, euctw_left_adjust_char_head, euctw_left_adjust_char_head_se, euctw_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/gb18030.c ================================================ /********************************************************************** gb18030.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2005-2007 KUBO Takehiro * K.Kosako * 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. */ #include "regenc.h" #if 1 #define DEBUG_GB18030(arg) #else #define DEBUG_GB18030(arg) printf arg #endif enum { C1, /* one-byte char */ C2, /* one-byte or second of two-byte char */ C4, /* one-byte or second or fourth of four-byte char */ CM /* first of two- or four-byte char or second of two-byte char */ }; static const char GB18030_MAP[] = { C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C1, C4, C4, C4, C4, C4, C4, C4, C4, C4, C4, C1, C1, C1, C1, C1, C1, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C2, C1, C2, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, CM, C1 }; static int gb18030_mbc_enc_len(const UChar* p) { if (GB18030_MAP[*p] != CM) return 1; p++; if (GB18030_MAP[*p] == C4) return 4; if (GB18030_MAP[*p] == C1) return 1; /* illegal sequence */ return 2; } static int gb18030_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { UChar c0, c1; c0 = ONIG_CHARAT(p); if (GB18030_MAP[c0] != CM) return 1; c1 = ONIG_CHARAT(p+1); if (GB18030_MAP[c1] == C4) return 4; if (GB18030_MAP[c1] == C1) return 1; /* illegal sequence */ return 2; } static OnigCodePoint gb18030_mbc_to_code(const UChar* p, const UChar* end) { return onigenc_mbn_mbc_to_code(ONIG_ENCODING_GB18030, p, end); } static OnigCodePoint gb18030_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { return onigenc_mbn_mbc_to_code_se(it, ONIG_ENCODING_GB18030, p, end); } static int gb18030_code_to_mbc(OnigCodePoint code, UChar *buf) { return onigenc_mb4_code_to_mbc(ONIG_ENCODING_GB18030, code, buf); } static int gb18030_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* lower) { return onigenc_mbn_mbc_case_fold(ONIG_ENCODING_GB18030, flag, pp, end, lower); } static int gb18030_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* lower) { return onigenc_mbn_mbc_case_fold_se(it, ONIG_ENCODING_GB18030, flag, pp, end, lower); } #if 0 static int gb18030_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_GB18030, flag, pp, end); } #endif static int gb18030_is_code_ctype(OnigCodePoint code, unsigned int ctype) { return onigenc_mb4_is_code_ctype(ONIG_ENCODING_GB18030, code, ctype); } enum state { S_START, S_one_C2, S_one_C4, S_one_CM, S_odd_CM_one_CX, S_even_CM_one_CX, /* CMC4 : pair of "CM C4" */ S_one_CMC4, S_odd_CMC4, S_one_C4_odd_CMC4, S_even_CMC4, S_one_C4_even_CMC4, S_odd_CM_odd_CMC4, S_even_CM_odd_CMC4, S_odd_CM_even_CMC4, S_even_CM_even_CMC4, /* C4CM : pair of "C4 CM" */ S_odd_C4CM, S_one_CM_odd_C4CM, S_even_C4CM, S_one_CM_even_C4CM, S_even_CM_odd_C4CM, S_odd_CM_odd_C4CM, S_even_CM_even_C4CM, S_odd_CM_even_C4CM, }; static UChar* gb18030_left_adjust_char_head(const UChar* start, const UChar* s) { const UChar *p; enum state state = S_START; DEBUG_GB18030(("----------------\n")); for (p = s; p >= start; p--) { DEBUG_GB18030(("state %d --(%02x)-->\n", state, *p)); switch (state) { case S_START: switch (GB18030_MAP[*p]) { case C1: return (UChar *)s; case C2: state = S_one_C2; /* C2 */ break; case C4: state = S_one_C4; /* C4 */ break; case CM: state = S_one_CM; /* CM */ break; } break; case S_one_C2: /* C2 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)s; case CM: state = S_odd_CM_one_CX; /* CM C2 */ break; } break; case S_one_C4: /* C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)s; case CM: state = S_one_CMC4; break; } break; case S_one_CM: /* CM */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)s; case C4: state = S_odd_C4CM; break; case CM: state = S_odd_CM_one_CX; /* CM CM */ break; } break; case S_odd_CM_one_CX: /* CM C2 */ /* CM CM */ /* CM CM CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 1); case CM: state = S_even_CM_one_CX; break; } break; case S_even_CM_one_CX: /* CM CM C2 */ /* CM CM CM */ /* CM CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)s; case CM: state = S_odd_CM_one_CX; break; } break; case S_one_CMC4: /* CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)(s - 1); case C4: state = S_one_C4_odd_CMC4; /* C4 CM C4 */ break; case CM: state = S_even_CM_one_CX; /* CM CM C4 */ break; } break; case S_odd_CMC4: /* CM C4 CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)(s - 1); case C4: state = S_one_C4_odd_CMC4; break; case CM: state = S_odd_CM_odd_CMC4; break; } break; case S_one_C4_odd_CMC4: /* C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 1); case CM: state = S_even_CMC4; /* CM C4 CM C4 */ break; } break; case S_even_CMC4: /* CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)(s - 3); case C4: state = S_one_C4_even_CMC4; break; case CM: state = S_odd_CM_even_CMC4; break; } break; case S_one_C4_even_CMC4: /* C4 CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 3); case CM: state = S_odd_CMC4; break; } break; case S_odd_CM_odd_CMC4: /* CM CM C4 CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 3); case CM: state = S_even_CM_odd_CMC4; break; } break; case S_even_CM_odd_CMC4: /* CM CM CM C4 CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 1); case CM: state = S_odd_CM_odd_CMC4; break; } break; case S_odd_CM_even_CMC4: /* CM CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 1); case CM: state = S_even_CM_even_CMC4; break; } break; case S_even_CM_even_CMC4: /* CM CM CM C4 CM C4 */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 3); case CM: state = S_odd_CM_even_CMC4; break; } break; case S_odd_C4CM: /* C4 CM */ /* C4 CM C4 CM C4 CM*/ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)s; case CM: state = S_one_CM_odd_C4CM; /* CM C4 CM */ break; } break; case S_one_CM_odd_C4CM: /* CM C4 CM */ /* CM C4 CM C4 CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)(s - 2); /* |CM C4 CM */ case C4: state = S_even_C4CM; break; case CM: state = S_even_CM_odd_C4CM; break; } break; case S_even_C4CM: /* C4 CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 2); /* C4|CM C4 CM */ case CM: state = S_one_CM_even_C4CM; break; } break; case S_one_CM_even_C4CM: /* CM C4 CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: return (UChar *)(s - 0); /*|CM C4 CM C4|CM */ case C4: state = S_odd_C4CM; break; case CM: state = S_even_CM_even_C4CM; break; } break; case S_even_CM_odd_C4CM: /* CM CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 0); /* |CM CM|C4|CM */ case CM: state = S_odd_CM_odd_C4CM; break; } break; case S_odd_CM_odd_C4CM: /* CM CM CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 2); /* |CM CM|CM C4 CM */ case CM: state = S_even_CM_odd_C4CM; break; } break; case S_even_CM_even_C4CM: /* CM CM C4 CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 2); /* |CM CM|C4|CM C4 CM */ case CM: state = S_odd_CM_even_C4CM; break; } break; case S_odd_CM_even_C4CM: /* CM CM CM C4 CM C4 CM */ switch (GB18030_MAP[*p]) { case C1: case C2: case C4: return (UChar *)(s - 0); /* |CM CM|CM C4 CM C4|CM */ case CM: state = S_even_CM_even_C4CM; break; } break; } } DEBUG_GB18030(("state %d\n", state)); switch (state) { case S_START: return (UChar *)(s - 0); case S_one_C2: return (UChar *)(s - 0); case S_one_C4: return (UChar *)(s - 0); case S_one_CM: return (UChar *)(s - 0); case S_odd_CM_one_CX: return (UChar *)(s - 1); case S_even_CM_one_CX: return (UChar *)(s - 0); case S_one_CMC4: return (UChar *)(s - 1); case S_odd_CMC4: return (UChar *)(s - 1); case S_one_C4_odd_CMC4: return (UChar *)(s - 1); case S_even_CMC4: return (UChar *)(s - 3); case S_one_C4_even_CMC4: return (UChar *)(s - 3); case S_odd_CM_odd_CMC4: return (UChar *)(s - 3); case S_even_CM_odd_CMC4: return (UChar *)(s - 1); case S_odd_CM_even_CMC4: return (UChar *)(s - 1); case S_even_CM_even_CMC4: return (UChar *)(s - 3); case S_odd_C4CM: return (UChar *)(s - 0); case S_one_CM_odd_C4CM: return (UChar *)(s - 2); case S_even_C4CM: return (UChar *)(s - 2); case S_one_CM_even_C4CM: return (UChar *)(s - 0); case S_even_CM_odd_C4CM: return (UChar *)(s - 0); case S_odd_CM_odd_C4CM: return (UChar *)(s - 2); case S_even_CM_even_C4CM: return (UChar *)(s - 2); case S_odd_CM_even_C4CM: return (UChar *)(s - 0); } return (UChar* )s; /* never come here. (escape warning) */ } static OnigPosition gb18030_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { OnigPosition p; UChar c; enum state state = S_START; DEBUG_GB18030(("----------------\n")); for (p = s; p >= start; p--) { c = ONIG_CHARAT(p); DEBUG_GB18030(("state %d --(%02x)-->\n", state, c)); switch (state) { case S_START: switch (GB18030_MAP[c]) { case C1: return s; case C2: state = S_one_C2; /* C2 */ break; case C4: state = S_one_C4; /* C4 */ break; case CM: state = S_one_CM; /* CM */ break; } break; case S_one_C2: /* C2 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return s; case CM: state = S_odd_CM_one_CX; /* CM C2 */ break; } break; case S_one_C4: /* C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return s; case CM: state = S_one_CMC4; break; } break; case S_one_CM: /* CM */ switch (GB18030_MAP[c]) { case C1: case C2: return s; case C4: state = S_odd_C4CM; break; case CM: state = S_odd_CM_one_CX; /* CM CM */ break; } break; case S_odd_CM_one_CX: /* CM C2 */ /* CM CM */ /* CM CM CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 1); case CM: state = S_even_CM_one_CX; break; } break; case S_even_CM_one_CX: /* CM CM C2 */ /* CM CM CM */ /* CM CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return s; case CM: state = S_odd_CM_one_CX; break; } break; case S_one_CMC4: /* CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: return (s - 1); case C4: state = S_one_C4_odd_CMC4; /* C4 CM C4 */ break; case CM: state = S_even_CM_one_CX; /* CM CM C4 */ break; } break; case S_odd_CMC4: /* CM C4 CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: return (s - 1); case C4: state = S_one_C4_odd_CMC4; break; case CM: state = S_odd_CM_odd_CMC4; break; } break; case S_one_C4_odd_CMC4: /* C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 1); case CM: state = S_even_CMC4; /* CM C4 CM C4 */ break; } break; case S_even_CMC4: /* CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: return (s - 3); case C4: state = S_one_C4_even_CMC4; break; case CM: state = S_odd_CM_even_CMC4; break; } break; case S_one_C4_even_CMC4: /* C4 CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 3); case CM: state = S_odd_CMC4; break; } break; case S_odd_CM_odd_CMC4: /* CM CM C4 CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 3); case CM: state = S_even_CM_odd_CMC4; break; } break; case S_even_CM_odd_CMC4: /* CM CM CM C4 CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 1); case CM: state = S_odd_CM_odd_CMC4; break; } break; case S_odd_CM_even_CMC4: /* CM CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 1); case CM: state = S_even_CM_even_CMC4; break; } break; case S_even_CM_even_CMC4: /* CM CM CM C4 CM C4 */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 3); case CM: state = S_odd_CM_even_CMC4; break; } break; case S_odd_C4CM: /* C4 CM */ /* C4 CM C4 CM C4 CM*/ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return s; case CM: state = S_one_CM_odd_C4CM; /* CM C4 CM */ break; } break; case S_one_CM_odd_C4CM: /* CM C4 CM */ /* CM C4 CM C4 CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: return (s - 2); /* |CM C4 CM */ case C4: state = S_even_C4CM; break; case CM: state = S_even_CM_odd_C4CM; break; } break; case S_even_C4CM: /* C4 CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 2); /* C4|CM C4 CM */ case CM: state = S_one_CM_even_C4CM; break; } break; case S_one_CM_even_C4CM: /* CM C4 CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: return (s - 0); /*|CM C4 CM C4|CM */ case C4: state = S_odd_C4CM; break; case CM: state = S_even_CM_even_C4CM; break; } break; case S_even_CM_odd_C4CM: /* CM CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 0); /* |CM CM|C4|CM */ case CM: state = S_odd_CM_odd_C4CM; break; } break; case S_odd_CM_odd_C4CM: /* CM CM CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 2); /* |CM CM|CM C4 CM */ case CM: state = S_even_CM_odd_C4CM; break; } break; case S_even_CM_even_C4CM: /* CM CM C4 CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 2); /* |CM CM|C4|CM C4 CM */ case CM: state = S_odd_CM_even_C4CM; break; } break; case S_odd_CM_even_C4CM: /* CM CM CM C4 CM C4 CM */ switch (GB18030_MAP[c]) { case C1: case C2: case C4: return (s - 0); /* |CM CM|CM C4 CM C4|CM */ case CM: state = S_even_CM_even_C4CM; break; } break; } } DEBUG_GB18030(("state %d\n", state)); switch (state) { case S_START: return (s - 0); case S_one_C2: return (s - 0); case S_one_C4: return (s - 0); case S_one_CM: return (s - 0); case S_odd_CM_one_CX: return (s - 1); case S_even_CM_one_CX: return (s - 0); case S_one_CMC4: return (s - 1); case S_odd_CMC4: return (s - 1); case S_one_C4_odd_CMC4: return (s - 1); case S_even_CMC4: return (s - 3); case S_one_C4_even_CMC4: return (s - 3); case S_odd_CM_odd_CMC4: return (s - 3); case S_even_CM_odd_CMC4: return (s - 1); case S_odd_CM_even_CMC4: return (s - 1); case S_even_CM_even_CMC4: return (s - 3); case S_odd_C4CM: return (s - 0); case S_one_CM_odd_C4CM: return (s - 2); case S_even_C4CM: return (s - 2); case S_one_CM_even_C4CM: return (s - 0); case S_even_CM_odd_C4CM: return (s - 0); case S_odd_CM_odd_C4CM: return (s - 2); case S_even_CM_even_C4CM: return (s - 2); case S_odd_CM_even_C4CM: return (s - 0); } return s; /* never come here. (escape warning) */ } static int gb18030_is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { return GB18030_MAP[*s] == C1 ? TRUE : FALSE; } OnigEncodingType OnigEncodingGB18030 = { gb18030_mbc_enc_len, gb18030_mbc_enc_len_se, "GB18030", /* name */ 4, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, gb18030_mbc_to_code, gb18030_mbc_to_code_se, onigenc_mb4_code_to_mbclen, gb18030_code_to_mbc, gb18030_mbc_case_fold, gb18030_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, gb18030_is_code_ctype, onigenc_not_support_get_ctype_code_range, gb18030_left_adjust_char_head, gb18030_left_adjust_char_head_se, gb18030_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_1.c ================================================ /********************************************************************** iso8859_1.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_IS_ISO_8859_1_CTYPE(code,ctype) \ ((EncISO_8859_1_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const unsigned short EncISO_8859_1_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x30e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x30e2, 0x00a0, 0x01a0, 0x00a0, 0x10a0, 0x30e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag ARG_UNUSED, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { if (0x41 <= *p && *p <= 0x5a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p + 0x20); if (*p == 0x53 && end > p + 1 && (*(p+1) == 0x53 || *(p+1) == 0x73)) { /* SS */ items[1].byte_len = 2; items[1].code_len = 1; items[1].code[0] = (OnigCodePoint )0xdf; return 2; } else return 1; } else if (0x61 <= *p && *p <= 0x7a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p - 0x20); if (*p == 0x73 && end > p + 1 && (*(p+1) == 0x73 || *(p+1) == 0x53)) { /* ss */ items[1].byte_len = 2; items[1].code_len = 1; items[1].code[0] = (OnigCodePoint )0xdf; return 2; } else return 1; } else if (0xc0 <= *p && *p <= 0xcf) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p + 0x20); return 1; } else if (0xd0 <= *p && *p <= 0xdf) { if (*p == 0xdf) { items[0].byte_len = 1; items[0].code_len = 2; items[0].code[0] = (OnigCodePoint )'s'; items[0].code[1] = (OnigCodePoint )'s'; items[1].byte_len = 1; items[1].code_len = 2; items[1].code[0] = (OnigCodePoint )'S'; items[1].code[1] = (OnigCodePoint )'S'; items[2].byte_len = 1; items[2].code_len = 2; items[2].code[0] = (OnigCodePoint )'s'; items[2].code[1] = (OnigCodePoint )'S'; items[3].byte_len = 1; items[3].code_len = 2; items[3].code[0] = (OnigCodePoint )'S'; items[3].code[1] = (OnigCodePoint )'s'; return 4; } else if (*p != 0xd7) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p + 0x20); return 1; } } else if (0xe0 <= *p && *p <= 0xef) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p - 0x20); return 1; } else if (0xf0 <= *p && *p <= 0xfe) { if (*p != 0xf7) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p - 0x20); return 1; } } return 0; } static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ONIGENC_ISO_8859_1_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_1_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xdf, 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (*p >= 0xaa && *p <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_1_CTYPE(code, ctype); else return FALSE; } OnigEncodingType OnigEncodingISO_8859_1 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-1", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_10.c ================================================ /********************************************************************** iso8859_10.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_10_TO_LOWER_CASE(c) EncISO_8859_10_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_10_CTYPE(code,ctype) \ ((EncISO_8859_10_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_10_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\261', '\262', '\263', '\264', '\265', '\266', '\247', '\270', '\271', '\272', '\273', '\274', '\255', '\276', '\277', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_10_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x01a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x01a0, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_10_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_10_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_10_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_10_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xb1 }, { 0xa2, 0xb2 }, { 0xa3, 0xb3 }, { 0xa4, 0xb4 }, { 0xa5, 0xb5 }, { 0xa6, 0xb6 }, { 0xa8, 0xb8 }, { 0xa9, 0xb9 }, { 0xaa, 0xba }, { 0xab, 0xbb }, { 0xac, 0xbc }, { 0xae, 0xbe }, { 0xaf, 0xbf }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_10 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-10", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_11.c ================================================ /********************************************************************** iso8859_11.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_IS_ISO_8859_11_CTYPE(code,ctype) \ ((EncISO_8859_11_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const unsigned short EncISO_8859_11_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x0000, 0x0000, 0x0000, 0x0000 }; static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_11_CTYPE(code, ctype); else return FALSE; } OnigEncodingType OnigEncodingISO_8859_11 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-11", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, onigenc_ascii_mbc_case_fold, onigenc_ascii_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_13.c ================================================ /********************************************************************** iso8859_13.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_13_TO_LOWER_CASE(c) EncISO_8859_13_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_13_CTYPE(code,ctype) \ ((EncISO_8859_13_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_13_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\270', '\251', '\272', '\253', '\254', '\255', '\256', '\277', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_13_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, 0x34a2, 0x00a0, 0x34a2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x34a2, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x01a0, 0x30e2, 0x00a0, 0x01a0, 0x30e2, 0x10a0, 0x30e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x01a0 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_13_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_13_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_13_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xdf, 0xb5 are lower case letter, but can't convert. */ if (*p == 0xb5) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_13_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_13 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-13", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_14.c ================================================ /********************************************************************** iso8859_14.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_14_TO_LOWER_CASE(c) EncISO_8859_14_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_14_CTYPE(code,ctype) \ ((EncISO_8859_14_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_14_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\242', '\242', '\243', '\245', '\245', '\253', '\247', '\270', '\251', '\272', '\253', '\274', '\255', '\256', '\377', '\261', '\261', '\263', '\263', '\265', '\265', '\266', '\271', '\270', '\271', '\272', '\277', '\274', '\276', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_14_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x30e2, 0x00a0, 0x34a2, 0x30e2, 0x34a2, 0x00a0, 0x34a2, 0x00a0, 0x34a2, 0x30e2, 0x34a2, 0x01a0, 0x00a0, 0x34a2, 0x34a2, 0x30e2, 0x34a2, 0x30e2, 0x34a2, 0x30e2, 0x00a0, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x34a2, 0x30e2, 0x34a2, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_14_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_14_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_14_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_14_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xa2 }, { 0xa4, 0xa5 }, { 0xa6, 0xab }, { 0xa8, 0xb8 }, { 0xaa, 0xba }, { 0xac, 0xbc }, { 0xaf, 0xff }, { 0xb0, 0xb1 }, { 0xb2, 0xb3 }, { 0xb4, 0xb5 }, { 0xb7, 0xb9 }, { 0xbb, 0xbf }, { 0xbd, 0xbe }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_14 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-14", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_15.c ================================================ /********************************************************************** iso8859_15.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_15_TO_LOWER_CASE(c) EncISO_8859_15_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_15_CTYPE(code,ctype) \ ((EncISO_8859_15_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_15_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\250', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\270', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\275', '\275', '\377', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_15_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x34a2, 0x00a0, 0x30e2, 0x00a0, 0x30e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x34a2, 0x30e2, 0x00a0, 0x01a0, 0x30e2, 0x10a0, 0x30e2, 0x01a0, 0x34a2, 0x30e2, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_15_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_15_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_15_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xdf etc.. are lower case letter, but can't convert. */ if (*p == 0xaa || *p == 0xb5 || *p == 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_15_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa6, 0xa8 }, { 0xb4, 0xb8 }, { 0xbc, 0xbd }, { 0xbe, 0xff }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_15 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-15", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_16.c ================================================ /********************************************************************** iso8859_16.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_16_TO_LOWER_CASE(c) EncISO_8859_16_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_16_CTYPE(code,ctype) \ ((EncISO_8859_16_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_16_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\242', '\242', '\263', '\245', '\245', '\250', '\247', '\250', '\251', '\272', '\253', '\256', '\255', '\256', '\277', '\260', '\261', '\271', '\263', '\270', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\275', '\275', '\377', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_16_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x30e2, 0x34a2, 0x00a0, 0x01a0, 0x34a2, 0x00a0, 0x30e2, 0x00a0, 0x34a2, 0x01a0, 0x34a2, 0x01a0, 0x30e2, 0x34a2, 0x00a0, 0x00a0, 0x34a2, 0x30e2, 0x34a2, 0x01a0, 0x00a0, 0x01a0, 0x30e2, 0x30e2, 0x30e2, 0x01a0, 0x34a2, 0x30e2, 0x34a2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_16_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_16_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_16_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_16_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xa2 }, { 0xa3, 0xb3 }, { 0xa6, 0xa8 }, { 0xaa, 0xba }, { 0xac, 0xae }, { 0xaf, 0xbf }, { 0xb2, 0xb9 }, { 0xb4, 0xb8 }, { 0xbc, 0xbd }, { 0xbe, 0xff }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_16 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-16", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_2.c ================================================ /********************************************************************** iso8859_2.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_2_TO_LOWER_CASE(c) EncISO_8859_2_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_2_CTYPE(code,ctype) \ ((EncISO_8859_2_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_2_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\261', '\242', '\263', '\244', '\265', '\266', '\247', '\250', '\271', '\272', '\273', '\274', '\255', '\276', '\277', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_2_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x00a0, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x00a0, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x00a0, 0x30e2, 0x00a0, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x00a0, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_2_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_2_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_2_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xb1 }, { 0xa3, 0xb3 }, { 0xa5, 0xb5 }, { 0xa6, 0xb6 }, { 0xa9, 0xb9 }, { 0xaa, 0xba }, { 0xab, 0xbb }, { 0xac, 0xbc }, { 0xae, 0xbe }, { 0xaf, 0xbf }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_2_CTYPE(code, ctype); else return FALSE; } OnigEncodingType OnigEncodingISO_8859_2 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-2", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_3.c ================================================ /********************************************************************** iso8859_3.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_3_TO_LOWER_CASE(c) EncISO_8859_3_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_3_CTYPE(code,ctype) \ ((EncISO_8859_3_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_3_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\261', '\242', '\243', '\244', '\245', '\266', '\247', '\250', '\271', '\272', '\273', '\274', '\255', '\256', '\277', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\303', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\320', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_3_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x00a0, 0x00a0, 0x00a0, 0x0000, 0x34a2, 0x00a0, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x0000, 0x34a2, 0x00a0, 0x30e2, 0x10a0, 0x10a0, 0x00a0, 0x30e2, 0x30e2, 0x01a0, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x11a0, 0x0000, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x0000, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x0000, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x0000, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x0000, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_3_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_3_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_3_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (*p == 0xb5) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_3_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xb1 }, { 0xa6, 0xb6 }, { 0xa9, 0xb9 }, { 0xaa, 0xba }, { 0xab, 0xbb }, { 0xac, 0xbc }, { 0xaf, 0xbf }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_3 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-3", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_4.c ================================================ /********************************************************************** iso8859_4.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_4_TO_LOWER_CASE(c) EncISO_8859_4_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_4_CTYPE(code,ctype) \ ((EncISO_8859_4_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_4_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\261', '\242', '\263', '\244', '\265', '\266', '\247', '\250', '\271', '\272', '\273', '\274', '\255', '\276', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\277', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_4_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x30e2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x00a0, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x34a2, 0x00a0, 0x00a0, 0x30e2, 0x00a0, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x00a0, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x34a2, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_4_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_4_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_4_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { if (*p == 0xa2) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_4_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xb1 }, { 0xa3, 0xb3 }, { 0xa5, 0xb5 }, { 0xa6, 0xb6 }, { 0xa9, 0xb9 }, { 0xaa, 0xba }, { 0xab, 0xbb }, { 0xac, 0xbc }, { 0xae, 0xbe }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_4 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-4", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_5.c ================================================ /********************************************************************** iso8859_5.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_5_TO_LOWER_CASE(c) EncISO_8859_5_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_5_CTYPE(code,ctype) \ ((EncISO_8859_5_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_5_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\255', '\376', '\377', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_5_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; *lower = ENC_ISO_8859_5_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); *lower = ENC_ISO_8859_5_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; (*pp)++; v = (EncISO_8859_5_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_5_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa1, 0xf1 }, { 0xa2, 0xf2 }, { 0xa3, 0xf3 }, { 0xa4, 0xf4 }, { 0xa5, 0xf5 }, { 0xa6, 0xf6 }, { 0xa7, 0xf7 }, { 0xa8, 0xf8 }, { 0xa9, 0xf9 }, { 0xaa, 0xfa }, { 0xab, 0xfb }, { 0xac, 0xfc }, { 0xae, 0xfe }, { 0xaf, 0xff }, { 0xb0, 0xd0 }, { 0xb1, 0xd1 }, { 0xb2, 0xd2 }, { 0xb3, 0xd3 }, { 0xb4, 0xd4 }, { 0xb5, 0xd5 }, { 0xb6, 0xd6 }, { 0xb7, 0xd7 }, { 0xb8, 0xd8 }, { 0xb9, 0xd9 }, { 0xba, 0xda }, { 0xbb, 0xdb }, { 0xbc, 0xdc }, { 0xbd, 0xdd }, { 0xbe, 0xde }, { 0xbf, 0xdf }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_5 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-5", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_6.c ================================================ /********************************************************************** iso8859_6.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_IS_ISO_8859_6_CTYPE(code,ctype) \ ((EncISO_8859_6_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const unsigned short EncISO_8859_6_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x0000, 0x0000, 0x0000, 0x00a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01a0, 0x01a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01a0, 0x0000, 0x0000, 0x0000, 0x01a0, 0x0000, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_6_CTYPE(code, ctype); else return FALSE; } OnigEncodingType OnigEncodingISO_8859_6 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-6", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, onigenc_ascii_mbc_case_fold, onigenc_ascii_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_7.c ================================================ /********************************************************************** iso8859_7.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_7_TO_LOWER_CASE(c) EncISO_8859_7_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_7_CTYPE(code,ctype) \ ((EncISO_8859_7_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_7_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\334', '\267', '\335', '\336', '\337', '\273', '\374', '\275', '\375', '\376', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\322', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_7_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x01a0, 0x00a0, 0x0000, 0x0000, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x0000, 0x01a0, 0x00a0, 0x01a0, 0x0000, 0x01a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x00a0, 0x34a2, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x01a0, 0x34a2, 0x10a0, 0x34a2, 0x34a2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x0000, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x0000 }; static int mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; *lower = ENC_ISO_8859_7_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); *lower = ENC_ISO_8859_7_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; (*pp)++; v = (EncISO_8859_7_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { if (*p == 0xc0 || *p == 0xe0) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_7_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xb6, 0xdc }, { 0xb8, 0xdd }, { 0xb9, 0xde }, { 0xba, 0xdf }, { 0xbc, 0xfc }, { 0xbe, 0xfd }, { 0xbf, 0xfe }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_7 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-7", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_8.c ================================================ /********************************************************************** iso8859_8.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_IS_ISO_8859_8_CTYPE(code,ctype) \ ((EncISO_8859_8_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const unsigned short EncISO_8859_8_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x0000, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x30e2, 0x00a0, 0x01a0, 0x00a0, 0x10a0, 0x00a0, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01a0, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x30a2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_8_CTYPE(code, ctype); else return FALSE; } OnigEncodingType OnigEncodingISO_8859_8 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-8", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, onigenc_ascii_mbc_case_fold, onigenc_ascii_mbc_case_fold_se, onigenc_ascii_apply_all_case_fold, onigenc_ascii_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/iso8859_9.c ================================================ /********************************************************************** iso8859_9.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_ISO_8859_9_TO_LOWER_CASE(c) EncISO_8859_9_ToLowerCaseTable[c] #define ENC_IS_ISO_8859_9_CTYPE(code,ctype) \ ((EncISO_8859_9_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncISO_8859_9_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\335', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; static const unsigned short EncISO_8859_9_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x30e2, 0x01a0, 0x00a0, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x30e2, 0x00a0, 0x01a0, 0x00a0, 0x10a0, 0x30e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_9_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (c == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { *lower++ = 's'; *lower = 's'; (*pp)++; return 2; } *lower = ENC_ISO_8859_9_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { (*pp)++; return TRUE; } (*pp)++; v = (EncISO_8859_9_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xdf etc.. are lower case letter, but can't convert. */ if (*p >= 0xaa && *p <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } #endif static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_ISO_8859_9_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe } }; static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, f, arg); } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 1, flag, p, end, items); } OnigEncodingType OnigEncodingISO_8859_9 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "ISO-8859-9", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/koi8.c ================================================ /********************************************************************** koi8.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regenc.h" #define ENC_KOI8_TO_LOWER_CASE(c) EncKOI8_ToLowerCaseTable[c] #define ENC_IS_KOI8_CTYPE(code,ctype) \ ((EncKOI8_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncKOI8_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337' }; static const unsigned short EncKOI8_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2 }; static int koi8_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; *lower = ENC_KOI8_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int koi8_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); *lower = ENC_KOI8_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int koi8_is_mbc_ambiguous(OnigAmbigType flag, const OnigUChar** pp, const OnigUChar* end) { const OnigUChar* p = *pp; (*pp)++; if (((flag & ONIGENC_CASE_FOLD_ASCII_CASE) != 0 && ONIGENC_IS_MBC_ASCII(p)) || ((flag & ONIGENC_CASE_FOLD_NONASCII_CASE) != 0 && !ONIGENC_IS_MBC_ASCII(p))) { int v = (EncKOI8_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); return (v != 0 ? TRUE : FALSE); } return FALSE; } #endif static int koi8_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_KOI8_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe }, { 0xdf, 0xff }, { 0xe0, 0xc0 }, { 0xe1, 0xc1 }, { 0xe2, 0xc2 }, { 0xe3, 0xc3 }, { 0xe4, 0xc4 }, { 0xe5, 0xc5 }, { 0xe6, 0xc6 }, { 0xe7, 0xc7 }, { 0xe8, 0xc8 }, { 0xe9, 0xc9 }, { 0xea, 0xca }, { 0xeb, 0xcb }, { 0xec, 0xcc }, { 0xed, 0xcd }, { 0xee, 0xce }, { 0xef, 0xcf }, { 0xf0, 0xd0 }, { 0xf1, 0xd1 }, { 0xf2, 0xd2 }, { 0xf3, 0xd3 }, { 0xf4, 0xd4 }, { 0xf5, 0xd5 }, { 0xf6, 0xd6 }, { 0xf7, 0xd7 }, { 0xf8, 0xd8 }, { 0xf9, 0xd9 }, { 0xfa, 0xda }, { 0xfb, 0xdb }, { 0xfc, 0xdc }, { 0xfe, 0xde }, { 0xff, 0xdf } }; static int koi8_apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static int koi8_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, p, end, items); } OnigEncodingType OnigEncodingKOI8 = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "KOI8", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, koi8_mbc_case_fold, koi8_mbc_case_fold_se, koi8_apply_all_case_fold, koi8_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, koi8_is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/koi8_r.c ================================================ /********************************************************************** koi8_r.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define ENC_KOI8_R_TO_LOWER_CASE(c) EncKOI8_R_ToLowerCaseTable[c] #define ENC_IS_KOI8_R_CTYPE(code,ctype) \ ((EncKOI8_R_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) static const UChar EncKOI8_R_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\243', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337' }; static const unsigned short EncKOI8_R_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x0284, 0x00a0, 0x00a0, 0x10a0, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x30e2, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x34a2, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2 }; static int koi8_r_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { const UChar* p = *pp; *lower = ENC_KOI8_R_TO_LOWER_CASE(*p); (*pp)++; return 1; } static int koi8_r_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); *lower = ENC_KOI8_R_TO_LOWER_CASE(c); (*pp)++; return 1; } #if 0 static int koi8_r_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { int v; const UChar* p = *pp; (*pp)++; v = (EncKOI8_R_CtypeTable[*p] & (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); return (v != 0 ? TRUE : FALSE); } #endif static int koi8_r_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 256) return ENC_IS_KOI8_R_CTYPE(code, ctype); else return FALSE; } static const OnigPairCaseFoldCodes CaseFoldMap[] = { { 0xa3, 0xb3 }, { 0xc0, 0xe0 }, { 0xc1, 0xe1 }, { 0xc2, 0xe2 }, { 0xc3, 0xe3 }, { 0xc4, 0xe4 }, { 0xc5, 0xe5 }, { 0xc6, 0xe6 }, { 0xc7, 0xe7 }, { 0xc8, 0xe8 }, { 0xc9, 0xe9 }, { 0xca, 0xea }, { 0xcb, 0xeb }, { 0xcc, 0xec }, { 0xcd, 0xed }, { 0xce, 0xee }, { 0xcf, 0xef }, { 0xd0, 0xf0 }, { 0xd1, 0xf1 }, { 0xd2, 0xf2 }, { 0xd3, 0xf3 }, { 0xd4, 0xf4 }, { 0xd5, 0xf5 }, { 0xd6, 0xf6 }, { 0xd7, 0xf7 }, { 0xd8, 0xf8 }, { 0xd9, 0xf9 }, { 0xda, 0xfa }, { 0xdb, 0xfb }, { 0xdc, 0xfc }, { 0xdd, 0xfd }, { 0xde, 0xfe }, { 0xdf, 0xff } }; static int koi8_r_apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static int koi8_r_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_get_case_fold_codes_by_str_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, p, end, items); } OnigEncodingType OnigEncodingKOI8_R = { onigenc_single_byte_mbc_enc_len, onigenc_single_byte_mbc_enc_len_se, "KOI8-R", /* name */ 1, /* max enc length */ 1, /* min enc length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, onigenc_single_byte_mbc_to_code, onigenc_single_byte_mbc_to_code_se, onigenc_single_byte_code_to_mbclen, onigenc_single_byte_code_to_mbc, koi8_r_mbc_case_fold, koi8_r_mbc_case_fold_se, koi8_r_apply_all_case_fold, koi8_r_get_case_fold_codes_by_str, onigenc_minimum_property_name_to_ctype, koi8_r_is_code_ctype, onigenc_not_support_get_ctype_code_range, onigenc_single_byte_left_adjust_char_head, onigenc_single_byte_left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; ================================================ FILE: src/Onigmo/enc/mktable.c ================================================ /********************************************************************** mktable.c **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include #include #include #define __USE_ISOC99 #include #include "regenc.h" #define ASCII 0 #define UNICODE_ISO_8859_1 1 #define ISO_8859_1 2 #define ISO_8859_2 3 #define ISO_8859_3 4 #define ISO_8859_4 5 #define ISO_8859_5 6 #define ISO_8859_6 7 #define ISO_8859_7 8 #define ISO_8859_8 9 #define ISO_8859_9 10 #define ISO_8859_10 11 #define ISO_8859_11 12 #define ISO_8859_13 13 #define ISO_8859_14 14 #define ISO_8859_15 15 #define ISO_8859_16 16 #define KOI8 17 #define KOI8_R 18 typedef struct { int num; const char* name; } ENC_INFO; static ENC_INFO Info[] = { { ASCII, "ASCII" }, { UNICODE_ISO_8859_1, "UNICODE_ISO_8859_1" }, { ISO_8859_1, "ISO_8859_1" }, { ISO_8859_2, "ISO_8859_2" }, { ISO_8859_3, "ISO_8859_3" }, { ISO_8859_4, "ISO_8859_4" }, { ISO_8859_5, "ISO_8859_5" }, { ISO_8859_6, "ISO_8859_6" }, { ISO_8859_7, "ISO_8859_7" }, { ISO_8859_8, "ISO_8859_8" }, { ISO_8859_9, "ISO_8859_9" }, { ISO_8859_10, "ISO_8859_10" }, { ISO_8859_11, "ISO_8859_11" }, { ISO_8859_13, "ISO_8859_13" }, { ISO_8859_14, "ISO_8859_14" }, { ISO_8859_15, "ISO_8859_15" }, { ISO_8859_16, "ISO_8859_16" }, { KOI8, "KOI8" }, { KOI8_R, "KOI8_R" } }; static int IsAlpha(int enc, int c) { if (enc == ASCII) return isalpha(c); if (c >= 0x41 && c <= 0x5a) return 1; if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; if (c == 0xb5) return 1; if (c == 0xba) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; break; case ISO_8859_2: if (c == 0xa1 || c == 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c >= 0xae && c <= 0xaf) return 1; if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_3: if (c == 0xa1) return 1; if (c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xaf) return 1; if (c == 0xb1) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c == 0xbf) return 1; if (c >= 0xc0 && c <= 0xc2) return 1; if (c >= 0xc4 && c <= 0xcf) return 1; if (c >= 0xd1 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xe2) return 1; if (c >= 0xe4 && c <= 0xef) return 1; if (c >= 0xf1 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_4: if (c >= 0xa1 && c <= 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xae) return 1; if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_5: if (c >= 0xa1 && c <= 0xcf && c != 0xad) return 1; if (c >= 0xd0 && c <= 0xff && c != 0xf0 && c != 0xfd) return 1; break; case ISO_8859_6: if (c >= 0xc1 && c <= 0xda) return 1; if (c >= 0xe0 && c <= 0xf2) return 1; break; case ISO_8859_7: if (c == 0xb6) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c == 0xc0) return 1; if (c >= 0xc1 && c <= 0xdb && c != 0xd2) return 1; if (c >= 0xdc && c <= 0xfe) return 1; break; case ISO_8859_8: if (c == 0xb5) return 1; if (c >= 0xe0 && c <= 0xfa) return 1; break; case ISO_8859_10: if (c >= 0xa1 && c <= 0xa6) return 1; if (c >= 0xa8 && c <= 0xac) return 1; if (c == 0xae || c == 0xaf) return 1; if (c >= 0xb1 && c <= 0xb6) return 1; if (c >= 0xb8 && c <= 0xbc) return 1; if (c >= 0xbe && c <= 0xff) return 1; break; case ISO_8859_11: if (c >= 0xa1 && c <= 0xda) return 1; if (c >= 0xdf && c <= 0xfb) return 1; break; case ISO_8859_13: if (c == 0xa8) return 1; if (c == 0xaa) return 1; if (c == 0xaf) return 1; if (c == 0xb5) return 1; if (c == 0xb8) return 1; if (c == 0xba) return 1; if (c >= 0xbf && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_14: if (c == 0xa1 || c == 0xa2) return 1; if (c == 0xa4 || c == 0xa5) return 1; if (c == 0xa6 || c == 0xa8) return 1; if (c >= 0xaa && c <= 0xac) return 1; if (c >= 0xaf && c <= 0xb5) return 1; if (c >= 0xb7 && c <= 0xff) return 1; break; case ISO_8859_15: if (c == 0xaa) return 1; if (c == 0xb5) return 1; if (c == 0xba) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; if (c == 0xa6) return 1; if (c == 0xa8) return 1; if (c == 0xb4) return 1; if (c == 0xb8) return 1; if (c == 0xbc) return 1; if (c == 0xbd) return 1; if (c == 0xbe) return 1; break; case ISO_8859_16: if (c == 0xa1) return 1; if (c == 0xa2) return 1; if (c == 0xa3) return 1; if (c == 0xa6) return 1; if (c == 0xa8) return 1; if (c == 0xaa) return 1; if (c == 0xac) return 1; if (c == 0xae) return 1; if (c == 0xaf) return 1; if (c == 0xb2) return 1; if (c == 0xb3) return 1; if (c == 0xb4) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbc) return 1; if (c == 0xbd) return 1; if (c == 0xbe) return 1; if (c == 0xbf) return 1; if (c >= 0xc0 && c <= 0xde) return 1; if (c >= 0xdf && c <= 0xff) return 1; break; case KOI8_R: if (c == 0xa3 || c == 0xb3) return 1; /* fall */ case KOI8: if (c >= 0xc0 && c <= 0xff) return 1; break; default: exit(-1); } return 0; } static int IsBlank(int enc, int c) { if (enc == ASCII) return isblank(c); if (c == 0x09 || c == 0x20) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: case ISO_8859_4: case ISO_8859_5: case ISO_8859_6: case ISO_8859_7: case ISO_8859_8: case ISO_8859_9: case ISO_8859_10: case ISO_8859_11: case ISO_8859_13: case ISO_8859_14: case ISO_8859_15: case ISO_8859_16: case KOI8: if (c == 0xa0) return 1; break; case KOI8_R: if (c == 0x9a) return 1; break; default: exit(-1); } return 0; } static int IsCntrl(int enc, int c) { if (enc == ASCII) return iscntrl(c); if (c >= 0x00 && c <= 0x1F) return 1; switch (enc) { case UNICODE_ISO_8859_1: if (c == 0xad) return 1; /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: case ISO_8859_4: case ISO_8859_5: case ISO_8859_6: case ISO_8859_7: case ISO_8859_8: case ISO_8859_9: case ISO_8859_10: case ISO_8859_11: case ISO_8859_13: case ISO_8859_14: case ISO_8859_15: case ISO_8859_16: case KOI8: if (c >= 0x7f && c <= 0x9F) return 1; break; case KOI8_R: if (c == 0x7f) return 1; break; default: exit(-1); } return 0; } static int IsDigit(int enc ARG_UNUSED, int c) { if (c >= 0x30 && c <= 0x39) return 1; return 0; } static int IsGraph(int enc, int c) { if (enc == ASCII) return isgraph(c); if (c >= 0x21 && c <= 0x7e) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_2: case ISO_8859_4: case ISO_8859_5: case ISO_8859_9: case ISO_8859_10: case ISO_8859_13: case ISO_8859_14: case ISO_8859_15: case ISO_8859_16: if (c >= 0xa1 && c <= 0xff) return 1; break; case ISO_8859_3: if (c >= 0xa1) { if (c == 0xa5 || c == 0xae || c == 0xbe || c == 0xc3 || c == 0xd0 || c == 0xe3 || c == 0xf0) return 0; else return 1; } break; case ISO_8859_6: if (c == 0xa4 || c == 0xac || c == 0xad || c == 0xbb || c == 0xbf) return 1; if (c >= 0xc1 && c <= 0xda) return 1; if (c >= 0xe0 && c <= 0xf2) return 1; break; case ISO_8859_7: if (c >= 0xa1 && c <= 0xfe && c != 0xa4 && c != 0xa5 && c != 0xaa && c != 0xae && c != 0xd2) return 1; break; case ISO_8859_8: if (c >= 0xa2 && c <= 0xfa) { if (c >= 0xbf && c <= 0xde) return 0; return 1; } break; case ISO_8859_11: if (c >= 0xa1 && c <= 0xda) return 1; if (c >= 0xdf && c <= 0xfb) return 1; break; case KOI8: if (c >= 0xc0 && c <= 0xff) return 1; break; case KOI8_R: if (c >= 0x80 && c <= 0xff && c != 0x9a) return 1; break; default: exit(-1); } return 0; } static int IsLower(int enc, int c) { if (enc == ASCII) return islower(c); if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; if (c == 0xb5) return 1; if (c == 0xba) return 1; if (c >= 0xdf && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; break; case ISO_8859_2: if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c >= 0xdf && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_3: if (c == 0xb1) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c == 0xbf) return 1; if (c == 0xdf) return 1; if (c >= 0xe0 && c <= 0xe2) return 1; if (c >= 0xe4 && c <= 0xef) return 1; if (c >= 0xf1 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_4: if (c == 0xa2) return 1; if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c == 0xdf) return 1; if (c >= 0xe0 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_5: if (c >= 0xd0 && c <= 0xff && c != 0xf0 && c != 0xfd) return 1; break; case ISO_8859_6: break; case ISO_8859_7: if (c == 0xc0) return 1; if (c >= 0xdc && c <= 0xfe) return 1; break; case ISO_8859_8: if (c == 0xb5) return 1; break; case ISO_8859_10: if (c >= 0xb1 && c <= 0xb6) return 1; if (c >= 0xb8 && c <= 0xbc) return 1; if (c == 0xbe || c == 0xbf) return 1; if (c >= 0xdf && c <= 0xff) return 1; break; case ISO_8859_11: break; case ISO_8859_13: if (c == 0xb5) return 1; if (c == 0xb8) return 1; if (c == 0xba) return 1; if (c == 0xbf) return 1; if (c >= 0xdf && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_14: if (c == 0xa2) return 1; if (c == 0xa5) return 1; if (c == 0xab) return 1; if (c == 0xb1 || c == 0xb3 || c == 0xb5) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbc) return 1; if (c == 0xbe || c == 0xbf) return 1; if (c >= 0xdf && c <= 0xff) return 1; break; case ISO_8859_15: if (c == 0xaa) return 1; if (c == 0xb5) return 1; if (c == 0xba) return 1; if (c >= 0xdf && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; if (c == 0xa8) return 1; if (c == 0xb8) return 1; if (c == 0xbd) return 1; break; case ISO_8859_16: if (c == 0xa2) return 1; if (c == 0xa8) return 1; if (c == 0xae) return 1; if (c == 0xb3) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbd) return 1; if (c == 0xbf) return 1; if (c >= 0xdf && c <= 0xff) return 1; break; case KOI8_R: if (c == 0xa3) return 1; /* fall */ case KOI8: if (c >= 0xc0 && c <= 0xdf) return 1; break; default: exit(-1); } return 0; } static int IsPrint(int enc, int c) { if (enc == ASCII) return isprint(c); if (c >= 0x20 && c <= 0x7e) return 1; switch (enc) { case UNICODE_ISO_8859_1: /* if (c >= 0x09 && c <= 0x0d) return 1; */ if (c == 0x85) return 1; /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_4: case ISO_8859_5: case ISO_8859_9: case ISO_8859_10: case ISO_8859_13: case ISO_8859_14: case ISO_8859_15: case ISO_8859_16: if (c >= 0xa0 && c <= 0xff) return 1; break; case ISO_8859_3: if (c >= 0xa0) { if (c == 0xa5 || c == 0xae || c == 0xbe || c == 0xc3 || c == 0xd0 || c == 0xe3 || c == 0xf0) return 0; else return 1; } break; case ISO_8859_6: if (c == 0xa0) return 1; if (c == 0xa4 || c == 0xac || c == 0xad || c == 0xbb || c == 0xbf) return 1; if (c >= 0xc1 && c <= 0xda) return 1; if (c >= 0xe0 && c <= 0xf2) return 1; break; case ISO_8859_7: if (c >= 0xa0 && c <= 0xfe && c != 0xa4 && c != 0xa5 && c != 0xaa && c != 0xae && c != 0xd2) return 1; break; case ISO_8859_8: if (c >= 0xa0 && c <= 0xfa) { if (c >= 0xbf && c <= 0xde) return 0; if (c == 0xa1) return 0; return 1; } break; case ISO_8859_11: if (c >= 0xa0 && c <= 0xda) return 1; if (c >= 0xdf && c <= 0xfb) return 1; break; case KOI8: if (c == 0xa0) return 1; if (c >= 0xc0 && c <= 0xff) return 1; break; case KOI8_R: if (c >= 0x80 && c <= 0xff) return 1; break; default: exit(-1); } return 0; } static int IsPunct(int enc, int c) { if (enc == ASCII) return ispunct(c); if (enc == UNICODE_ISO_8859_1) { if (c == 0x24 || c == 0x2b || c == 0x5e || c == 0x60 || c == 0x7c || c == 0x7e) return 1; if (c >= 0x3c && c <= 0x3e) return 1; } if (c >= 0x21 && c <= 0x2f) return 1; if (c >= 0x3a && c <= 0x40) return 1; if (c >= 0x5b && c <= 0x60) return 1; if (c >= 0x7b && c <= 0x7e) return 1; switch (enc) { case ISO_8859_1: case ISO_8859_9: case ISO_8859_15: if (c == 0xad) return 1; /* fall */ case UNICODE_ISO_8859_1: if (c == 0xa1) return 1; if (c == 0xab) return 1; if (c == 0xb7) return 1; if (c == 0xbb) return 1; if (c == 0xbf) return 1; break; case ISO_8859_2: case ISO_8859_4: case ISO_8859_5: case ISO_8859_14: if (c == 0xad) return 1; break; case ISO_8859_3: case ISO_8859_10: if (c == 0xad) return 1; if (c == 0xb7) return 1; if (c == 0xbd) return 1; break; case ISO_8859_6: if (c == 0xac) return 1; if (c == 0xad) return 1; if (c == 0xbb) return 1; if (c == 0xbf) return 1; break; case ISO_8859_7: if (c == 0xa1 || c == 0xa2) return 1; if (c == 0xab) return 1; if (c == 0xaf) return 1; if (c == 0xad) return 1; if (c == 0xb7 || c == 0xbb) return 1; break; case ISO_8859_8: if (c == 0xab) return 1; if (c == 0xad) return 1; if (c == 0xb7) return 1; if (c == 0xbb) return 1; if (c == 0xdf) return 1; break; case ISO_8859_13: if (c == 0xa1 || c == 0xa5) return 1; if (c == 0xab || c == 0xad) return 1; if (c == 0xb4 || c == 0xb7) return 1; if (c == 0xbb) return 1; if (c == 0xff) return 1; break; case ISO_8859_16: if (c == 0xa5) return 1; if (c == 0xab) return 1; if (c == 0xad) return 1; if (c == 0xb5) return 1; if (c == 0xb7) return 1; if (c == 0xbb) return 1; break; case KOI8_R: if (c == 0x9e) return 1; break; case ISO_8859_11: case KOI8: break; default: exit(-1); } return 0; } static int IsSpace(int enc, int c) { if (enc == ASCII) return isspace(c); if (c >= 0x09 && c <= 0x0d) return 1; if (c == 0x20) return 1; switch (enc) { case UNICODE_ISO_8859_1: if (c == 0x85) return 1; /* fall */ case ISO_8859_1: case ISO_8859_2: case ISO_8859_3: case ISO_8859_4: case ISO_8859_5: case ISO_8859_6: case ISO_8859_7: case ISO_8859_8: case ISO_8859_9: case ISO_8859_10: case ISO_8859_11: case ISO_8859_13: case ISO_8859_14: case ISO_8859_15: case ISO_8859_16: case KOI8: if (c == 0xa0) return 1; break; case KOI8_R: if (c == 0x9a) return 1; break; default: exit(-1); } return 0; } static int IsUpper(int enc, int c) { if (enc == ASCII) return isupper(c); if (c >= 0x41 && c <= 0x5a) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; break; case ISO_8859_2: if (c == 0xa1 || c == 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c >= 0xae && c <= 0xaf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; break; case ISO_8859_3: if (c == 0xa1) return 1; if (c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xaf) return 1; if (c >= 0xc0 && c <= 0xc2) return 1; if (c >= 0xc4 && c <= 0xcf) return 1; if (c >= 0xd1 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; break; case ISO_8859_4: if (c == 0xa1 || c == 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xae) return 1; if (c == 0xbd) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; break; case ISO_8859_5: if (c >= 0xa1 && c <= 0xcf && c != 0xad) return 1; break; case ISO_8859_6: break; case ISO_8859_7: if (c == 0xb6) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c >= 0xc1 && c <= 0xdb && c != 0xd2) return 1; break; case ISO_8859_8: case ISO_8859_11: break; case ISO_8859_10: if (c >= 0xa1 && c <= 0xa6) return 1; if (c >= 0xa8 && c <= 0xac) return 1; if (c == 0xae || c == 0xaf) return 1; if (c >= 0xc0 && c <= 0xde) return 1; break; case ISO_8859_13: if (c == 0xa8) return 1; if (c == 0xaa) return 1; if (c == 0xaf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; break; case ISO_8859_14: if (c == 0xa1) return 1; if (c == 0xa4 || c == 0xa6) return 1; if (c == 0xa8) return 1; if (c == 0xaa || c == 0xac) return 1; if (c == 0xaf || c == 0xb0) return 1; if (c == 0xb2 || c == 0xb4 || c == 0xb7) return 1; if (c == 0xbb || c == 0xbd) return 1; if (c >= 0xc0 && c <= 0xde) return 1; break; case ISO_8859_15: if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xde) return 1; if (c == 0xa6) return 1; if (c == 0xb4) return 1; if (c == 0xbc) return 1; if (c == 0xbe) return 1; break; case ISO_8859_16: if (c == 0xa1) return 1; if (c == 0xa3) return 1; if (c == 0xa6) return 1; if (c == 0xaa) return 1; if (c == 0xac) return 1; if (c == 0xaf) return 1; if (c == 0xb2) return 1; if (c == 0xb4) return 1; if (c == 0xbc) return 1; if (c == 0xbe) return 1; if (c >= 0xc0 && c <= 0xde) return 1; break; case KOI8_R: if (c == 0xb3) return 1; /* fall */ case KOI8: if (c >= 0xe0 && c <= 0xff) return 1; break; default: exit(-1); } return 0; } static int IsXDigit(int enc, int c) { if (enc == ASCII) return isxdigit(c); if (c >= 0x30 && c <= 0x39) return 1; if (c >= 0x41 && c <= 0x46) return 1; if (c >= 0x61 && c <= 0x66) return 1; return 0; } static int IsWord(int enc, int c) { if (enc == ASCII) { return (isalpha(c) || isdigit(c) || c == 0x5f); } if (c >= 0x30 && c <= 0x39) return 1; if (c >= 0x41 && c <= 0x5a) return 1; if (c == 0x5f) return 1; if (c >= 0x61 && c <= 0x7a) return 1; switch (enc) { case UNICODE_ISO_8859_1: case ISO_8859_1: case ISO_8859_9: if (c == 0xaa) return 1; if (c >= 0xb2 && c <= 0xb3) return 1; if (c == 0xb5) return 1; if (c >= 0xb9 && c <= 0xba) return 1; if (c >= 0xbc && c <= 0xbe) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; break; case ISO_8859_2: if (c == 0xa1 || c == 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c >= 0xae && c <= 0xaf) return 1; if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbc) return 1; if (c >= 0xbe && c <= 0xbf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_3: if (c == 0xa1) return 1; if (c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xaf) return 1; if (c >= 0xb1 && c <= 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbd) return 1; if (c == 0xbf) return 1; if (c >= 0xc0 && c <= 0xc2) return 1; if (c >= 0xc4 && c <= 0xcf) return 1; if (c >= 0xd1 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xe2) return 1; if (c >= 0xe4 && c <= 0xef) return 1; if (c >= 0xf1 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_4: if (c >= 0xa1 && c <= 0xa3) return 1; if (c == 0xa5 || c == 0xa6) return 1; if (c >= 0xa9 && c <= 0xac) return 1; if (c == 0xae) return 1; if (c == 0xb1 || c == 0xb3) return 1; if (c == 0xb5 || c == 0xb6) return 1; if (c >= 0xb9 && c <= 0xbf) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_5: if (c >= 0xa1 && c <= 0xcf && c != 0xad) return 1; if (c >= 0xd0 && c <= 0xff && c != 0xf0 && c != 0xfd) return 1; break; case ISO_8859_6: if (c >= 0xc1 && c <= 0xda) return 1; if (c >= 0xe0 && c <= 0xea) return 1; if (c >= 0xeb && c <= 0xf2) return 1; break; case ISO_8859_7: if (c == 0xb2 || c == 0xb3) return 1; if (c == 0xb6) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c >= 0xbc && c <= 0xbf) return 1; if (c == 0xc0) return 1; if (c >= 0xc1 && c <= 0xdb && c != 0xd2) return 1; if (c >= 0xdc && c <= 0xfe) return 1; break; case ISO_8859_8: if (c == 0xb2 || c == 0xb3 || c == 0xb5 || c == 0xb9) return 1; if (c >= 0xbc && c <= 0xbe) return 1; if (c >= 0xe0 && c <= 0xfa) return 1; break; case ISO_8859_10: if (c >= 0xa1 && c <= 0xff) { if (c != 0xa7 && c != 0xad && c != 0xb0 && c != 0xb7 && c != 0xbd) return 1; } break; case ISO_8859_11: if (c >= 0xa1 && c <= 0xda) return 1; if (c >= 0xdf && c <= 0xfb) return 1; break; case ISO_8859_13: if (c == 0xa8) return 1; if (c == 0xaa) return 1; if (c == 0xaf) return 1; if (c == 0xb2 || c == 0xb3 || c == 0xb5 || c == 0xb9) return 1; if (c >= 0xbc && c <= 0xbe) return 1; if (c == 0xb8) return 1; if (c == 0xba) return 1; if (c >= 0xbf && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xfe) return 1; break; case ISO_8859_14: if (c >= 0xa1 && c <= 0xff) { if (c == 0xa3 || c == 0xa7 || c == 0xa9 || c == 0xad || c == 0xae || c == 0xb6) return 0; return 1; } break; case ISO_8859_15: if (c == 0xaa) return 1; if (c >= 0xb2 && c <= 0xb3) return 1; if (c == 0xb5) return 1; if (c >= 0xb9 && c <= 0xba) return 1; if (c >= 0xbc && c <= 0xbe) return 1; if (c >= 0xc0 && c <= 0xd6) return 1; if (c >= 0xd8 && c <= 0xf6) return 1; if (c >= 0xf8 && c <= 0xff) return 1; if (c == 0xa6) return 1; if (c == 0xa8) return 1; if (c == 0xb4) return 1; if (c == 0xb8) return 1; break; case ISO_8859_16: if (c == 0xa1) return 1; if (c == 0xa2) return 1; if (c == 0xa3) return 1; if (c == 0xa6) return 1; if (c == 0xa8) return 1; if (c == 0xaa) return 1; if (c == 0xac) return 1; if (c == 0xae) return 1; if (c == 0xaf) return 1; if (c == 0xb2) return 1; if (c == 0xb3) return 1; if (c == 0xb4) return 1; if (c >= 0xb8 && c <= 0xba) return 1; if (c == 0xbc) return 1; if (c == 0xbd) return 1; if (c == 0xbe) return 1; if (c == 0xbf) return 1; if (c >= 0xc0 && c <= 0xde) return 1; if (c >= 0xdf && c <= 0xff) return 1; break; case KOI8_R: if (c == 0x9d) return 1; if (c == 0xa3 || c == 0xb3) return 1; /* fall */ case KOI8: if (c >= 0xc0 && c <= 0xff) return 1; break; default: exit(-1); } return 0; } static int IsAscii(int enc ARG_UNUSED, int c) { if (c >= 0x00 && c <= 0x7f) return 1; return 0; } static int IsNewline(int enc ARG_UNUSED, int c) { if (c == 0x0a) return 1; return 0; } static int exec(FILE* fp, ENC_INFO* einfo) { #define NCOL 8 int c, val, enc; enc = einfo->num; fprintf(fp, "static const unsigned short Enc%s_CtypeTable[256] = {\n", einfo->name); for (c = 0; c < 256; c++) { val = 0; if (IsNewline(enc, c)) val |= BIT_CTYPE_NEWLINE; if (IsAlpha (enc, c)) val |= (BIT_CTYPE_ALPHA | BIT_CTYPE_ALNUM); if (IsBlank (enc, c)) val |= BIT_CTYPE_BLANK; if (IsCntrl (enc, c)) val |= BIT_CTYPE_CNTRL; if (IsDigit (enc, c)) val |= (BIT_CTYPE_DIGIT | BIT_CTYPE_ALNUM); if (IsGraph (enc, c)) val |= BIT_CTYPE_GRAPH; if (IsLower (enc, c)) val |= BIT_CTYPE_LOWER; if (IsPrint (enc, c)) val |= BIT_CTYPE_PRINT; if (IsPunct (enc, c)) val |= BIT_CTYPE_PUNCT; if (IsSpace (enc, c)) val |= BIT_CTYPE_SPACE; if (IsUpper (enc, c)) val |= BIT_CTYPE_UPPER; if (IsXDigit(enc, c)) val |= BIT_CTYPE_XDIGIT; if (IsWord (enc, c)) val |= BIT_CTYPE_WORD; if (IsAscii (enc, c)) val |= BIT_CTYPE_ASCII; if (c % NCOL == 0) fputs(" ", fp); fprintf(fp, "0x%04x", val); if (c != 255) fputs(",", fp); if (c != 0 && c % NCOL == (NCOL-1)) fputs("\n", fp); else fputs(" ", fp); } fprintf(fp, "};\n"); return 0; } extern int main(int argc ARG_UNUSED, char* argv[] ARG_UNUSED) { int i; FILE* fp = stdout; setlocale(LC_ALL, "C"); /* setlocale(LC_ALL, "POSIX"); */ /* setlocale(LC_ALL, "en_GB.iso88591"); */ /* setlocale(LC_ALL, "de_BE.iso88591"); */ /* setlocale(LC_ALL, "fr_FR.iso88591"); */ for (i = 0; i < (int )(sizeof(Info)/sizeof(ENC_INFO)); i++) { exec(fp, &Info[i]); } return 0; } ================================================ FILE: src/Onigmo/enc/sjis.c ================================================ /********************************************************************** sjis.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" #ifdef ENC_CP932 #define ONIG_ENCODING_SELF ONIG_ENCODING_CP932 #else #define ONIG_ENCODING_SELF ONIG_ENCODING_SJIS #endif static const int EncLen_SJIS[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1 }; static const char SJIS_CAN_BE_TRAIL_TABLE[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; static const OnigPairCaseFoldCodes CaseFoldMap[] = { /* Fullwidth Alphabet */ { 0x8260, 0x8281 }, { 0x8261, 0x8282 }, { 0x8262, 0x8283 }, { 0x8263, 0x8284 }, { 0x8264, 0x8285 }, { 0x8265, 0x8286 }, { 0x8266, 0x8287 }, { 0x8267, 0x8288 }, { 0x8268, 0x8289 }, { 0x8269, 0x828a }, { 0x826a, 0x828b }, { 0x826b, 0x828c }, { 0x826c, 0x828d }, { 0x826d, 0x828e }, { 0x826e, 0x828f }, { 0x826f, 0x8290 }, { 0x8270, 0x8291 }, { 0x8271, 0x8292 }, { 0x8272, 0x8293 }, { 0x8273, 0x8294 }, { 0x8274, 0x8295 }, { 0x8275, 0x8296 }, { 0x8276, 0x8297 }, { 0x8277, 0x8298 }, { 0x8278, 0x8299 }, { 0x8279, 0x829a }, /* Greek */ { 0x839f, 0x83bf }, { 0x83a0, 0x83c0 }, { 0x83a1, 0x83c1 }, { 0x83a2, 0x83c2 }, { 0x83a3, 0x83c3 }, { 0x83a4, 0x83c4 }, { 0x83a5, 0x83c5 }, { 0x83a6, 0x83c6 }, { 0x83a7, 0x83c7 }, { 0x83a8, 0x83c8 }, { 0x83a9, 0x83c9 }, { 0x83aa, 0x83ca }, { 0x83ab, 0x83cb }, { 0x83ac, 0x83cc }, { 0x83ad, 0x83cd }, { 0x83ae, 0x83ce }, { 0x83af, 0x83cf }, { 0x83b0, 0x83d0 }, { 0x83b1, 0x83d1 }, { 0x83b2, 0x83d2 }, { 0x83b3, 0x83d3 }, { 0x83b4, 0x83d4 }, { 0x83b5, 0x83d5 }, { 0x83b6, 0x83d6 }, /* Cyrillic */ { 0x8440, 0x8470 }, { 0x8441, 0x8471 }, { 0x8442, 0x8472 }, { 0x8443, 0x8473 }, { 0x8444, 0x8474 }, { 0x8445, 0x8475 }, { 0x8446, 0x8476 }, { 0x8447, 0x8477 }, { 0x8448, 0x8478 }, { 0x8449, 0x8479 }, { 0x844a, 0x847a }, { 0x844b, 0x847b }, { 0x844c, 0x847c }, { 0x844d, 0x847d }, { 0x844e, 0x847e }, { 0x844f, 0x8480 }, { 0x8450, 0x8481 }, { 0x8451, 0x8482 }, { 0x8452, 0x8483 }, { 0x8453, 0x8484 }, { 0x8454, 0x8485 }, { 0x8455, 0x8486 }, { 0x8456, 0x8487 }, { 0x8457, 0x8488 }, { 0x8458, 0x8489 }, { 0x8459, 0x848a }, { 0x845a, 0x848b }, { 0x845b, 0x848c }, { 0x845c, 0x848d }, { 0x845d, 0x848e }, { 0x845e, 0x848f }, { 0x845f, 0x8490 }, { 0x8460, 0x8491 }, }; #define SJIS_ISMB_FIRST(byte) (EncLen_SJIS[byte] > 1) #define SJIS_ISMB_TRAIL(byte) SJIS_CAN_BE_TRAIL_TABLE[(byte)] static int mbc_enc_len(const UChar* p) { return EncLen_SJIS[*p]; } static int mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_SJIS[ONIG_CHARAT(p)]; } static int code_to_mbclen(OnigCodePoint code) { if (code < 256) { if (EncLen_SJIS[(int )code] == 1) return 1; else return 0; } else if (code <= 0xffff) { int low = code & 0xff; if (! SJIS_ISMB_TRAIL(low)) return ONIGERR_INVALID_CODE_POINT_VALUE; return 2; } else return ONIGERR_INVALID_CODE_POINT_VALUE; } static OnigCodePoint mbc_to_code(const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; len = mbc_enc_len(p); c = *p++; n = c; if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = *p++; n <<= 8; n += c; } return n; } static OnigCodePoint mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end) { int c, i, len; OnigCodePoint n; len = mbc_enc_len_se(it, p); c = ONIG_CHARAT(p++); n = c; if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = ONIG_CHARAT(p++); n <<= 8; n += c; } return n; } static int code_to_mbc(OnigCodePoint code, UChar *buf) { UChar *p = buf; if ((code & 0xff00) != 0) *p++ = (UChar )(((code >> 8) & 0xff)); *p++ = (UChar )(code & 0xff); #if 0 if (mbc_enc_len(buf) != (p - buf)) return REGERR_INVALID_CODE_POINT_VALUE; #endif return (int )(p - buf); } static int apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { return onigenc_apply_all_case_fold_with_map( sizeof(CaseFoldMap)/sizeof(OnigPairCaseFoldCodes), CaseFoldMap, 0, flag, f, arg); } static OnigCodePoint get_lower_case(OnigCodePoint code) { if (ONIGENC_IS_IN_RANGE(code, 0x8260, 0x8279)) { /* Fullwidth Alphabet */ return (OnigCodePoint )(code + 0x0021); } else if (ONIGENC_IS_IN_RANGE(code, 0x839f, 0x83b6)) { /* Greek */ return (OnigCodePoint )(code + 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0x8440, 0x8460)) { /* Cyrillic */ int d = (code >= 0x844f) ? 1 : 0; return (OnigCodePoint )(code + (0x0030 + d)); } return code; } static OnigCodePoint get_upper_case(OnigCodePoint code) { if (ONIGENC_IS_IN_RANGE(code, 0x8281, 0x829a)) { /* Fullwidth Alphabet */ return (OnigCodePoint )(code - 0x0021); } else if (ONIGENC_IS_IN_RANGE(code, 0x83bf, 0x83d6)) { /* Greek */ return (OnigCodePoint )(code - 0x0020); } else if (ONIGENC_IS_IN_RANGE(code, 0x8470, 0x847e) || ONIGENC_IS_IN_RANGE(code, 0x8480, 0x8491)) { /* Cyrillic */ int d = (code >= 0x8480) ? 1 : 0; return (OnigCodePoint )(code - (0x0030 - d)); } return code; } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { int len; OnigCodePoint code, code_lo, code_up; code = mbc_to_code(p, end); if (ONIGENC_IS_ASCII_CODE(code)) return onigenc_ascii_get_case_fold_codes_by_str(flag, p, end, items); len = mbc_enc_len(p); code_lo = get_lower_case(code); code_up = get_upper_case(code); if (code != code_lo) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = code_lo; return 1; } else if (code != code_up) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = code_up; return 1; } return 0; } static int mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end, UChar* lower) { const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); (*pp)++; return 1; } else { OnigCodePoint code; int len; code = get_lower_case(mbc_to_code(p, end)); len = code_to_mbc(code, lower); (*pp) += len; return len; /* return byte length of converted char to lower */ } } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end, UChar* lower) { const UChar c = ONIG_CHARAT(*pp); if (ONIGENC_IS_MBC_ASCII_SE(c)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); (*pp)++; return 1; } else { OnigCodePoint code; int len; code = get_lower_case(mbc_to_code_se(it, *pp, end)); len = code_to_mbc(code, lower); (*pp) += len; return len; /* return byte length of converted char to lower */ } } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { return onigenc_mbn_is_mbc_ambiguous(ONIG_ENCODING_SELF, flag, pp, end); } #endif #if 0 static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { if (CTYPE_IS_WORD_GRAPH_PRINT(ctype)) { return (code_to_mbclen(code) > 1 ? TRUE : FALSE); } } return FALSE; } #endif static UChar* left_adjust_char_head(const UChar* start, const UChar* s) { const UChar *p; int len; if (s <= start) return (UChar* )s; p = s; if (SJIS_ISMB_TRAIL(*p)) { while (p > start) { if (! SJIS_ISMB_FIRST(*--p)) { p++; break; } } } len = mbc_enc_len(p); if (p + len > s) return (UChar* )p; p += len; return (UChar* )(p + ((s - p) & ~1)); } static OnigPosition left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { OnigPosition p; int len; if (s <= start) return s; p = s; if (SJIS_ISMB_TRAIL(ONIG_CHARAT(p))) { while (p > start) { if (! SJIS_ISMB_FIRST(ONIG_CHARAT(--p))) { p++; break; } } } len = mbc_enc_len_se(it, p); if (p + len > s) return p; p += len; return (p + ((s - p) & ~1)); } static int is_allowed_reverse_match(const UChar* s, const UChar* end ARG_UNUSED) { const UChar c = *s; return (SJIS_ISMB_TRAIL(c) ? FALSE : TRUE); } static int PropertyInited = 0; static const OnigCodePoint** PropertyList; static int PropertyListNum; static int PropertyListSize; static hash_table_type* PropertyNameTable; static const OnigCodePoint CR_Hiragana[] = { 1, 0x829f, 0x82f1 }; /* CR_Hiragana */ static const OnigCodePoint CR_Katakana[] = { 4, 0x00a6, 0x00af, 0x00b1, 0x00dd, 0x8340, 0x837e, 0x8380, 0x8396, }; /* CR_Katakana */ #ifdef ENC_CP932 static const OnigCodePoint CR_Han[] = { 6, 0x8157, 0x8157, 0x889f, 0x9872, /* Kanji level 1 */ 0x989f, 0x9ffc, /* Kanji level 2 */ 0xe040, 0xeaa4, /* Kanji level 2 */ 0xed40, 0xeeec, /* NEC-selected IBM extended characters (without symbols) */ 0xfa5c, 0xfc4b, /* IBM extended characters (without symbols) */ }; /* CR_Han */ #else static const OnigCodePoint CR_Han[] = { 4, 0x8157, 0x8157, 0x889f, 0x9872, /* Kanji level 1 */ 0x989f, 0x9ffc, /* Kanji level 2 */ 0xe040, 0xeaa4, /* Kanji level 2 */ }; /* CR_Han */ #endif static const OnigCodePoint CR_Latin[] = { 4, 0x0041, 0x005a, 0x0061, 0x007a, 0x8260, 0x8279, 0x8281, 0x829a, }; /* CR_Latin */ static const OnigCodePoint CR_Greek[] = { 2, 0x839f, 0x83b6, 0x83bf, 0x83d6, }; /* CR_Greek */ static const OnigCodePoint CR_Cyrillic[] = { 3, 0x8440, 0x8460, 0x8470, 0x847f, 0x8480, 0x8491, }; /* CR_Cyrillic */ static int init_property_list(void) { int r; PROPERTY_LIST_ADD_PROP("hiragana", CR_Hiragana); PROPERTY_LIST_ADD_PROP("katakana", CR_Katakana); PROPERTY_LIST_ADD_PROP("han", CR_Han); PROPERTY_LIST_ADD_PROP("latin", CR_Latin); PROPERTY_LIST_ADD_PROP("greek", CR_Greek); PROPERTY_LIST_ADD_PROP("cyrillic", CR_Cyrillic); PropertyInited = 1; end: return r; } static int property_name_to_ctype(OnigEncoding enc, UChar* p, UChar* end) { hash_data_type ctype; UChar *s, *e; PROPERTY_LIST_INIT_CHECK; s = e = xalloca(end - p + 1); for (; p < end; p++) { *e++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); } if (onig_st_lookup_strend(PropertyNameTable, s, e, &ctype) == 0) { return onigenc_minimum_property_name_to_ctype(enc, s, e); } return (int )ctype; } static int is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (ctype <= ONIGENC_MAX_STD_CTYPE) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { if (CTYPE_IS_WORD_GRAPH_PRINT(ctype)) { return (code_to_mbclen(code) > 1 ? TRUE : FALSE); } } } else { PROPERTY_LIST_INIT_CHECK; ctype -= (ONIGENC_MAX_STD_CTYPE + 1); if (ctype >= (unsigned int )PropertyListNum) return ONIGERR_TYPE_BUG; return onig_is_in_code_range((UChar* )PropertyList[ctype], code); } return FALSE; } static int get_ctype_code_range(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[]) { if (ctype <= ONIGENC_MAX_STD_CTYPE) { return ONIG_NO_SUPPORT_CONFIG; } else { *sb_out = 0x80; PROPERTY_LIST_INIT_CHECK; ctype -= (ONIGENC_MAX_STD_CTYPE + 1); if (ctype >= (OnigCtype )PropertyListNum) return ONIGERR_TYPE_BUG; *ranges = PropertyList[ctype]; return 0; } } #ifdef ENC_CP932 OnigEncodingType OnigEncodingCP932 = { mbc_enc_len, mbc_enc_len_se, "CP932", /* name */ 2, /* max byte length */ 1, /* min byte length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, mbc_to_code, mbc_to_code_se, code_to_mbclen, code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, property_name_to_ctype, is_code_ctype, get_ctype_code_range, left_adjust_char_head, left_adjust_char_head_se, is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; #else OnigEncodingType OnigEncodingSJIS = { mbc_enc_len, mbc_enc_len_se, "Shift_JIS", /* name */ 2, /* max byte length */ 1, /* min byte length */ onigenc_is_mbc_newline_0x0a, onigenc_is_mbc_newline_0x0a_se, mbc_to_code, mbc_to_code_se, code_to_mbclen, code_to_mbc, mbc_case_fold, mbc_case_fold_se, apply_all_case_fold, get_case_fold_codes_by_str, property_name_to_ctype, is_code_ctype, get_ctype_code_range, left_adjust_char_head, left_adjust_char_head_se, is_allowed_reverse_match, ONIGENC_FLAG_NONE, }; #endif ================================================ FILE: src/Onigmo/enc/unicode/casefold.h ================================================ /* DO NOT EDIT THIS FILE. */ /* Generated by tool/CaseFolding.py */ static const CaseFold_11_Type CaseFold[] = { { 0x0041, {1, {0x0061}}}, { 0x0042, {1, {0x0062}}}, { 0x0043, {1, {0x0063}}}, { 0x0044, {1, {0x0064}}}, { 0x0045, {1, {0x0065}}}, { 0x0046, {1, {0x0066}}}, { 0x0047, {1, {0x0067}}}, { 0x0048, {1, {0x0068}}}, { 0x004a, {1, {0x006a}}}, { 0x004b, {1, {0x006b}}}, { 0x004c, {1, {0x006c}}}, { 0x004d, {1, {0x006d}}}, { 0x004e, {1, {0x006e}}}, { 0x004f, {1, {0x006f}}}, { 0x0050, {1, {0x0070}}}, { 0x0051, {1, {0x0071}}}, { 0x0052, {1, {0x0072}}}, { 0x0053, {1, {0x0073}}}, { 0x0054, {1, {0x0074}}}, { 0x0055, {1, {0x0075}}}, { 0x0056, {1, {0x0076}}}, { 0x0057, {1, {0x0077}}}, { 0x0058, {1, {0x0078}}}, { 0x0059, {1, {0x0079}}}, { 0x005a, {1, {0x007a}}}, { 0x00b5, {1, {0x03bc}}}, { 0x00c0, {1, {0x00e0}}}, { 0x00c1, {1, {0x00e1}}}, { 0x00c2, {1, {0x00e2}}}, { 0x00c3, {1, {0x00e3}}}, { 0x00c4, {1, {0x00e4}}}, { 0x00c5, {1, {0x00e5}}}, { 0x00c6, {1, {0x00e6}}}, { 0x00c7, {1, {0x00e7}}}, { 0x00c8, {1, {0x00e8}}}, { 0x00c9, {1, {0x00e9}}}, { 0x00ca, {1, {0x00ea}}}, { 0x00cb, {1, {0x00eb}}}, { 0x00cc, {1, {0x00ec}}}, { 0x00cd, {1, {0x00ed}}}, { 0x00ce, {1, {0x00ee}}}, { 0x00cf, {1, {0x00ef}}}, { 0x00d0, {1, {0x00f0}}}, { 0x00d1, {1, {0x00f1}}}, { 0x00d2, {1, {0x00f2}}}, { 0x00d3, {1, {0x00f3}}}, { 0x00d4, {1, {0x00f4}}}, { 0x00d5, {1, {0x00f5}}}, { 0x00d6, {1, {0x00f6}}}, { 0x00d8, {1, {0x00f8}}}, { 0x00d9, {1, {0x00f9}}}, { 0x00da, {1, {0x00fa}}}, { 0x00db, {1, {0x00fb}}}, { 0x00dc, {1, {0x00fc}}}, { 0x00dd, {1, {0x00fd}}}, { 0x00de, {1, {0x00fe}}}, { 0x00df, {2, {0x0073, 0x0073}}}, { 0x0100, {1, {0x0101}}}, { 0x0102, {1, {0x0103}}}, { 0x0104, {1, {0x0105}}}, { 0x0106, {1, {0x0107}}}, { 0x0108, {1, {0x0109}}}, { 0x010a, {1, {0x010b}}}, { 0x010c, {1, {0x010d}}}, { 0x010e, {1, {0x010f}}}, { 0x0110, {1, {0x0111}}}, { 0x0112, {1, {0x0113}}}, { 0x0114, {1, {0x0115}}}, { 0x0116, {1, {0x0117}}}, { 0x0118, {1, {0x0119}}}, { 0x011a, {1, {0x011b}}}, { 0x011c, {1, {0x011d}}}, { 0x011e, {1, {0x011f}}}, { 0x0120, {1, {0x0121}}}, { 0x0122, {1, {0x0123}}}, { 0x0124, {1, {0x0125}}}, { 0x0126, {1, {0x0127}}}, { 0x0128, {1, {0x0129}}}, { 0x012a, {1, {0x012b}}}, { 0x012c, {1, {0x012d}}}, { 0x012e, {1, {0x012f}}}, { 0x0132, {1, {0x0133}}}, { 0x0134, {1, {0x0135}}}, { 0x0136, {1, {0x0137}}}, { 0x0139, {1, {0x013a}}}, { 0x013b, {1, {0x013c}}}, { 0x013d, {1, {0x013e}}}, { 0x013f, {1, {0x0140}}}, { 0x0141, {1, {0x0142}}}, { 0x0143, {1, {0x0144}}}, { 0x0145, {1, {0x0146}}}, { 0x0147, {1, {0x0148}}}, { 0x0149, {2, {0x02bc, 0x006e}}}, { 0x014a, {1, {0x014b}}}, { 0x014c, {1, {0x014d}}}, { 0x014e, {1, {0x014f}}}, { 0x0150, {1, {0x0151}}}, { 0x0152, {1, {0x0153}}}, { 0x0154, {1, {0x0155}}}, { 0x0156, {1, {0x0157}}}, { 0x0158, {1, {0x0159}}}, { 0x015a, {1, {0x015b}}}, { 0x015c, {1, {0x015d}}}, { 0x015e, {1, {0x015f}}}, { 0x0160, {1, {0x0161}}}, { 0x0162, {1, {0x0163}}}, { 0x0164, {1, {0x0165}}}, { 0x0166, {1, {0x0167}}}, { 0x0168, {1, {0x0169}}}, { 0x016a, {1, {0x016b}}}, { 0x016c, {1, {0x016d}}}, { 0x016e, {1, {0x016f}}}, { 0x0170, {1, {0x0171}}}, { 0x0172, {1, {0x0173}}}, { 0x0174, {1, {0x0175}}}, { 0x0176, {1, {0x0177}}}, { 0x0178, {1, {0x00ff}}}, { 0x0179, {1, {0x017a}}}, { 0x017b, {1, {0x017c}}}, { 0x017d, {1, {0x017e}}}, { 0x017f, {1, {0x0073}}}, { 0x0181, {1, {0x0253}}}, { 0x0182, {1, {0x0183}}}, { 0x0184, {1, {0x0185}}}, { 0x0186, {1, {0x0254}}}, { 0x0187, {1, {0x0188}}}, { 0x0189, {1, {0x0256}}}, { 0x018a, {1, {0x0257}}}, { 0x018b, {1, {0x018c}}}, { 0x018e, {1, {0x01dd}}}, { 0x018f, {1, {0x0259}}}, { 0x0190, {1, {0x025b}}}, { 0x0191, {1, {0x0192}}}, { 0x0193, {1, {0x0260}}}, { 0x0194, {1, {0x0263}}}, { 0x0196, {1, {0x0269}}}, { 0x0197, {1, {0x0268}}}, { 0x0198, {1, {0x0199}}}, { 0x019c, {1, {0x026f}}}, { 0x019d, {1, {0x0272}}}, { 0x019f, {1, {0x0275}}}, { 0x01a0, {1, {0x01a1}}}, { 0x01a2, {1, {0x01a3}}}, { 0x01a4, {1, {0x01a5}}}, { 0x01a6, {1, {0x0280}}}, { 0x01a7, {1, {0x01a8}}}, { 0x01a9, {1, {0x0283}}}, { 0x01ac, {1, {0x01ad}}}, { 0x01ae, {1, {0x0288}}}, { 0x01af, {1, {0x01b0}}}, { 0x01b1, {1, {0x028a}}}, { 0x01b2, {1, {0x028b}}}, { 0x01b3, {1, {0x01b4}}}, { 0x01b5, {1, {0x01b6}}}, { 0x01b7, {1, {0x0292}}}, { 0x01b8, {1, {0x01b9}}}, { 0x01bc, {1, {0x01bd}}}, { 0x01c4, {1, {0x01c6}}}, { 0x01c5, {1, {0x01c6}}}, { 0x01c7, {1, {0x01c9}}}, { 0x01c8, {1, {0x01c9}}}, { 0x01ca, {1, {0x01cc}}}, { 0x01cb, {1, {0x01cc}}}, { 0x01cd, {1, {0x01ce}}}, { 0x01cf, {1, {0x01d0}}}, { 0x01d1, {1, {0x01d2}}}, { 0x01d3, {1, {0x01d4}}}, { 0x01d5, {1, {0x01d6}}}, { 0x01d7, {1, {0x01d8}}}, { 0x01d9, {1, {0x01da}}}, { 0x01db, {1, {0x01dc}}}, { 0x01de, {1, {0x01df}}}, { 0x01e0, {1, {0x01e1}}}, { 0x01e2, {1, {0x01e3}}}, { 0x01e4, {1, {0x01e5}}}, { 0x01e6, {1, {0x01e7}}}, { 0x01e8, {1, {0x01e9}}}, { 0x01ea, {1, {0x01eb}}}, { 0x01ec, {1, {0x01ed}}}, { 0x01ee, {1, {0x01ef}}}, { 0x01f0, {2, {0x006a, 0x030c}}}, { 0x01f1, {1, {0x01f3}}}, { 0x01f2, {1, {0x01f3}}}, { 0x01f4, {1, {0x01f5}}}, { 0x01f6, {1, {0x0195}}}, { 0x01f7, {1, {0x01bf}}}, { 0x01f8, {1, {0x01f9}}}, { 0x01fa, {1, {0x01fb}}}, { 0x01fc, {1, {0x01fd}}}, { 0x01fe, {1, {0x01ff}}}, { 0x0200, {1, {0x0201}}}, { 0x0202, {1, {0x0203}}}, { 0x0204, {1, {0x0205}}}, { 0x0206, {1, {0x0207}}}, { 0x0208, {1, {0x0209}}}, { 0x020a, {1, {0x020b}}}, { 0x020c, {1, {0x020d}}}, { 0x020e, {1, {0x020f}}}, { 0x0210, {1, {0x0211}}}, { 0x0212, {1, {0x0213}}}, { 0x0214, {1, {0x0215}}}, { 0x0216, {1, {0x0217}}}, { 0x0218, {1, {0x0219}}}, { 0x021a, {1, {0x021b}}}, { 0x021c, {1, {0x021d}}}, { 0x021e, {1, {0x021f}}}, { 0x0220, {1, {0x019e}}}, { 0x0222, {1, {0x0223}}}, { 0x0224, {1, {0x0225}}}, { 0x0226, {1, {0x0227}}}, { 0x0228, {1, {0x0229}}}, { 0x022a, {1, {0x022b}}}, { 0x022c, {1, {0x022d}}}, { 0x022e, {1, {0x022f}}}, { 0x0230, {1, {0x0231}}}, { 0x0232, {1, {0x0233}}}, { 0x023a, {1, {0x2c65}}}, { 0x023b, {1, {0x023c}}}, { 0x023d, {1, {0x019a}}}, { 0x023e, {1, {0x2c66}}}, { 0x0241, {1, {0x0242}}}, { 0x0243, {1, {0x0180}}}, { 0x0244, {1, {0x0289}}}, { 0x0245, {1, {0x028c}}}, { 0x0246, {1, {0x0247}}}, { 0x0248, {1, {0x0249}}}, { 0x024a, {1, {0x024b}}}, { 0x024c, {1, {0x024d}}}, { 0x024e, {1, {0x024f}}}, { 0x0345, {1, {0x03b9}}}, { 0x0370, {1, {0x0371}}}, { 0x0372, {1, {0x0373}}}, { 0x0376, {1, {0x0377}}}, { 0x0386, {1, {0x03ac}}}, { 0x0388, {1, {0x03ad}}}, { 0x0389, {1, {0x03ae}}}, { 0x038a, {1, {0x03af}}}, { 0x038c, {1, {0x03cc}}}, { 0x038e, {1, {0x03cd}}}, { 0x038f, {1, {0x03ce}}}, { 0x0390, {3, {0x03b9, 0x0308, 0x0301}}}, { 0x0391, {1, {0x03b1}}}, { 0x0392, {1, {0x03b2}}}, { 0x0393, {1, {0x03b3}}}, { 0x0394, {1, {0x03b4}}}, { 0x0395, {1, {0x03b5}}}, { 0x0396, {1, {0x03b6}}}, { 0x0397, {1, {0x03b7}}}, { 0x0398, {1, {0x03b8}}}, { 0x0399, {1, {0x03b9}}}, { 0x039a, {1, {0x03ba}}}, { 0x039b, {1, {0x03bb}}}, { 0x039c, {1, {0x03bc}}}, { 0x039d, {1, {0x03bd}}}, { 0x039e, {1, {0x03be}}}, { 0x039f, {1, {0x03bf}}}, { 0x03a0, {1, {0x03c0}}}, { 0x03a1, {1, {0x03c1}}}, { 0x03a3, {1, {0x03c3}}}, { 0x03a4, {1, {0x03c4}}}, { 0x03a5, {1, {0x03c5}}}, { 0x03a6, {1, {0x03c6}}}, { 0x03a7, {1, {0x03c7}}}, { 0x03a8, {1, {0x03c8}}}, { 0x03a9, {1, {0x03c9}}}, { 0x03aa, {1, {0x03ca}}}, { 0x03ab, {1, {0x03cb}}}, { 0x03b0, {3, {0x03c5, 0x0308, 0x0301}}}, { 0x03c2, {1, {0x03c3}}}, { 0x03cf, {1, {0x03d7}}}, { 0x03d0, {1, {0x03b2}}}, { 0x03d1, {1, {0x03b8}}}, { 0x03d5, {1, {0x03c6}}}, { 0x03d6, {1, {0x03c0}}}, { 0x03d8, {1, {0x03d9}}}, { 0x03da, {1, {0x03db}}}, { 0x03dc, {1, {0x03dd}}}, { 0x03de, {1, {0x03df}}}, { 0x03e0, {1, {0x03e1}}}, { 0x03e2, {1, {0x03e3}}}, { 0x03e4, {1, {0x03e5}}}, { 0x03e6, {1, {0x03e7}}}, { 0x03e8, {1, {0x03e9}}}, { 0x03ea, {1, {0x03eb}}}, { 0x03ec, {1, {0x03ed}}}, { 0x03ee, {1, {0x03ef}}}, { 0x03f0, {1, {0x03ba}}}, { 0x03f1, {1, {0x03c1}}}, { 0x03f4, {1, {0x03b8}}}, { 0x03f5, {1, {0x03b5}}}, { 0x03f7, {1, {0x03f8}}}, { 0x03f9, {1, {0x03f2}}}, { 0x03fa, {1, {0x03fb}}}, { 0x03fd, {1, {0x037b}}}, { 0x03fe, {1, {0x037c}}}, { 0x03ff, {1, {0x037d}}}, { 0x0400, {1, {0x0450}}}, { 0x0401, {1, {0x0451}}}, { 0x0402, {1, {0x0452}}}, { 0x0403, {1, {0x0453}}}, { 0x0404, {1, {0x0454}}}, { 0x0405, {1, {0x0455}}}, { 0x0406, {1, {0x0456}}}, { 0x0407, {1, {0x0457}}}, { 0x0408, {1, {0x0458}}}, { 0x0409, {1, {0x0459}}}, { 0x040a, {1, {0x045a}}}, { 0x040b, {1, {0x045b}}}, { 0x040c, {1, {0x045c}}}, { 0x040d, {1, {0x045d}}}, { 0x040e, {1, {0x045e}}}, { 0x040f, {1, {0x045f}}}, { 0x0410, {1, {0x0430}}}, { 0x0411, {1, {0x0431}}}, { 0x0412, {1, {0x0432}}}, { 0x0413, {1, {0x0433}}}, { 0x0414, {1, {0x0434}}}, { 0x0415, {1, {0x0435}}}, { 0x0416, {1, {0x0436}}}, { 0x0417, {1, {0x0437}}}, { 0x0418, {1, {0x0438}}}, { 0x0419, {1, {0x0439}}}, { 0x041a, {1, {0x043a}}}, { 0x041b, {1, {0x043b}}}, { 0x041c, {1, {0x043c}}}, { 0x041d, {1, {0x043d}}}, { 0x041e, {1, {0x043e}}}, { 0x041f, {1, {0x043f}}}, { 0x0420, {1, {0x0440}}}, { 0x0421, {1, {0x0441}}}, { 0x0422, {1, {0x0442}}}, { 0x0423, {1, {0x0443}}}, { 0x0424, {1, {0x0444}}}, { 0x0425, {1, {0x0445}}}, { 0x0426, {1, {0x0446}}}, { 0x0427, {1, {0x0447}}}, { 0x0428, {1, {0x0448}}}, { 0x0429, {1, {0x0449}}}, { 0x042a, {1, {0x044a}}}, { 0x042b, {1, {0x044b}}}, { 0x042c, {1, {0x044c}}}, { 0x042d, {1, {0x044d}}}, { 0x042e, {1, {0x044e}}}, { 0x042f, {1, {0x044f}}}, { 0x0460, {1, {0x0461}}}, { 0x0462, {1, {0x0463}}}, { 0x0464, {1, {0x0465}}}, { 0x0466, {1, {0x0467}}}, { 0x0468, {1, {0x0469}}}, { 0x046a, {1, {0x046b}}}, { 0x046c, {1, {0x046d}}}, { 0x046e, {1, {0x046f}}}, { 0x0470, {1, {0x0471}}}, { 0x0472, {1, {0x0473}}}, { 0x0474, {1, {0x0475}}}, { 0x0476, {1, {0x0477}}}, { 0x0478, {1, {0x0479}}}, { 0x047a, {1, {0x047b}}}, { 0x047c, {1, {0x047d}}}, { 0x047e, {1, {0x047f}}}, { 0x0480, {1, {0x0481}}}, { 0x048a, {1, {0x048b}}}, { 0x048c, {1, {0x048d}}}, { 0x048e, {1, {0x048f}}}, { 0x0490, {1, {0x0491}}}, { 0x0492, {1, {0x0493}}}, { 0x0494, {1, {0x0495}}}, { 0x0496, {1, {0x0497}}}, { 0x0498, {1, {0x0499}}}, { 0x049a, {1, {0x049b}}}, { 0x049c, {1, {0x049d}}}, { 0x049e, {1, {0x049f}}}, { 0x04a0, {1, {0x04a1}}}, { 0x04a2, {1, {0x04a3}}}, { 0x04a4, {1, {0x04a5}}}, { 0x04a6, {1, {0x04a7}}}, { 0x04a8, {1, {0x04a9}}}, { 0x04aa, {1, {0x04ab}}}, { 0x04ac, {1, {0x04ad}}}, { 0x04ae, {1, {0x04af}}}, { 0x04b0, {1, {0x04b1}}}, { 0x04b2, {1, {0x04b3}}}, { 0x04b4, {1, {0x04b5}}}, { 0x04b6, {1, {0x04b7}}}, { 0x04b8, {1, {0x04b9}}}, { 0x04ba, {1, {0x04bb}}}, { 0x04bc, {1, {0x04bd}}}, { 0x04be, {1, {0x04bf}}}, { 0x04c0, {1, {0x04cf}}}, { 0x04c1, {1, {0x04c2}}}, { 0x04c3, {1, {0x04c4}}}, { 0x04c5, {1, {0x04c6}}}, { 0x04c7, {1, {0x04c8}}}, { 0x04c9, {1, {0x04ca}}}, { 0x04cb, {1, {0x04cc}}}, { 0x04cd, {1, {0x04ce}}}, { 0x04d0, {1, {0x04d1}}}, { 0x04d2, {1, {0x04d3}}}, { 0x04d4, {1, {0x04d5}}}, { 0x04d6, {1, {0x04d7}}}, { 0x04d8, {1, {0x04d9}}}, { 0x04da, {1, {0x04db}}}, { 0x04dc, {1, {0x04dd}}}, { 0x04de, {1, {0x04df}}}, { 0x04e0, {1, {0x04e1}}}, { 0x04e2, {1, {0x04e3}}}, { 0x04e4, {1, {0x04e5}}}, { 0x04e6, {1, {0x04e7}}}, { 0x04e8, {1, {0x04e9}}}, { 0x04ea, {1, {0x04eb}}}, { 0x04ec, {1, {0x04ed}}}, { 0x04ee, {1, {0x04ef}}}, { 0x04f0, {1, {0x04f1}}}, { 0x04f2, {1, {0x04f3}}}, { 0x04f4, {1, {0x04f5}}}, { 0x04f6, {1, {0x04f7}}}, { 0x04f8, {1, {0x04f9}}}, { 0x04fa, {1, {0x04fb}}}, { 0x04fc, {1, {0x04fd}}}, { 0x04fe, {1, {0x04ff}}}, { 0x0500, {1, {0x0501}}}, { 0x0502, {1, {0x0503}}}, { 0x0504, {1, {0x0505}}}, { 0x0506, {1, {0x0507}}}, { 0x0508, {1, {0x0509}}}, { 0x050a, {1, {0x050b}}}, { 0x050c, {1, {0x050d}}}, { 0x050e, {1, {0x050f}}}, { 0x0510, {1, {0x0511}}}, { 0x0512, {1, {0x0513}}}, { 0x0514, {1, {0x0515}}}, { 0x0516, {1, {0x0517}}}, { 0x0518, {1, {0x0519}}}, { 0x051a, {1, {0x051b}}}, { 0x051c, {1, {0x051d}}}, { 0x051e, {1, {0x051f}}}, { 0x0520, {1, {0x0521}}}, { 0x0522, {1, {0x0523}}}, { 0x0524, {1, {0x0525}}}, { 0x0526, {1, {0x0527}}}, { 0x0531, {1, {0x0561}}}, { 0x0532, {1, {0x0562}}}, { 0x0533, {1, {0x0563}}}, { 0x0534, {1, {0x0564}}}, { 0x0535, {1, {0x0565}}}, { 0x0536, {1, {0x0566}}}, { 0x0537, {1, {0x0567}}}, { 0x0538, {1, {0x0568}}}, { 0x0539, {1, {0x0569}}}, { 0x053a, {1, {0x056a}}}, { 0x053b, {1, {0x056b}}}, { 0x053c, {1, {0x056c}}}, { 0x053d, {1, {0x056d}}}, { 0x053e, {1, {0x056e}}}, { 0x053f, {1, {0x056f}}}, { 0x0540, {1, {0x0570}}}, { 0x0541, {1, {0x0571}}}, { 0x0542, {1, {0x0572}}}, { 0x0543, {1, {0x0573}}}, { 0x0544, {1, {0x0574}}}, { 0x0545, {1, {0x0575}}}, { 0x0546, {1, {0x0576}}}, { 0x0547, {1, {0x0577}}}, { 0x0548, {1, {0x0578}}}, { 0x0549, {1, {0x0579}}}, { 0x054a, {1, {0x057a}}}, { 0x054b, {1, {0x057b}}}, { 0x054c, {1, {0x057c}}}, { 0x054d, {1, {0x057d}}}, { 0x054e, {1, {0x057e}}}, { 0x054f, {1, {0x057f}}}, { 0x0550, {1, {0x0580}}}, { 0x0551, {1, {0x0581}}}, { 0x0552, {1, {0x0582}}}, { 0x0553, {1, {0x0583}}}, { 0x0554, {1, {0x0584}}}, { 0x0555, {1, {0x0585}}}, { 0x0556, {1, {0x0586}}}, { 0x0587, {2, {0x0565, 0x0582}}}, { 0x10a0, {1, {0x2d00}}}, { 0x10a1, {1, {0x2d01}}}, { 0x10a2, {1, {0x2d02}}}, { 0x10a3, {1, {0x2d03}}}, { 0x10a4, {1, {0x2d04}}}, { 0x10a5, {1, {0x2d05}}}, { 0x10a6, {1, {0x2d06}}}, { 0x10a7, {1, {0x2d07}}}, { 0x10a8, {1, {0x2d08}}}, { 0x10a9, {1, {0x2d09}}}, { 0x10aa, {1, {0x2d0a}}}, { 0x10ab, {1, {0x2d0b}}}, { 0x10ac, {1, {0x2d0c}}}, { 0x10ad, {1, {0x2d0d}}}, { 0x10ae, {1, {0x2d0e}}}, { 0x10af, {1, {0x2d0f}}}, { 0x10b0, {1, {0x2d10}}}, { 0x10b1, {1, {0x2d11}}}, { 0x10b2, {1, {0x2d12}}}, { 0x10b3, {1, {0x2d13}}}, { 0x10b4, {1, {0x2d14}}}, { 0x10b5, {1, {0x2d15}}}, { 0x10b6, {1, {0x2d16}}}, { 0x10b7, {1, {0x2d17}}}, { 0x10b8, {1, {0x2d18}}}, { 0x10b9, {1, {0x2d19}}}, { 0x10ba, {1, {0x2d1a}}}, { 0x10bb, {1, {0x2d1b}}}, { 0x10bc, {1, {0x2d1c}}}, { 0x10bd, {1, {0x2d1d}}}, { 0x10be, {1, {0x2d1e}}}, { 0x10bf, {1, {0x2d1f}}}, { 0x10c0, {1, {0x2d20}}}, { 0x10c1, {1, {0x2d21}}}, { 0x10c2, {1, {0x2d22}}}, { 0x10c3, {1, {0x2d23}}}, { 0x10c4, {1, {0x2d24}}}, { 0x10c5, {1, {0x2d25}}}, { 0x10c7, {1, {0x2d27}}}, { 0x10cd, {1, {0x2d2d}}}, { 0x1e00, {1, {0x1e01}}}, { 0x1e02, {1, {0x1e03}}}, { 0x1e04, {1, {0x1e05}}}, { 0x1e06, {1, {0x1e07}}}, { 0x1e08, {1, {0x1e09}}}, { 0x1e0a, {1, {0x1e0b}}}, { 0x1e0c, {1, {0x1e0d}}}, { 0x1e0e, {1, {0x1e0f}}}, { 0x1e10, {1, {0x1e11}}}, { 0x1e12, {1, {0x1e13}}}, { 0x1e14, {1, {0x1e15}}}, { 0x1e16, {1, {0x1e17}}}, { 0x1e18, {1, {0x1e19}}}, { 0x1e1a, {1, {0x1e1b}}}, { 0x1e1c, {1, {0x1e1d}}}, { 0x1e1e, {1, {0x1e1f}}}, { 0x1e20, {1, {0x1e21}}}, { 0x1e22, {1, {0x1e23}}}, { 0x1e24, {1, {0x1e25}}}, { 0x1e26, {1, {0x1e27}}}, { 0x1e28, {1, {0x1e29}}}, { 0x1e2a, {1, {0x1e2b}}}, { 0x1e2c, {1, {0x1e2d}}}, { 0x1e2e, {1, {0x1e2f}}}, { 0x1e30, {1, {0x1e31}}}, { 0x1e32, {1, {0x1e33}}}, { 0x1e34, {1, {0x1e35}}}, { 0x1e36, {1, {0x1e37}}}, { 0x1e38, {1, {0x1e39}}}, { 0x1e3a, {1, {0x1e3b}}}, { 0x1e3c, {1, {0x1e3d}}}, { 0x1e3e, {1, {0x1e3f}}}, { 0x1e40, {1, {0x1e41}}}, { 0x1e42, {1, {0x1e43}}}, { 0x1e44, {1, {0x1e45}}}, { 0x1e46, {1, {0x1e47}}}, { 0x1e48, {1, {0x1e49}}}, { 0x1e4a, {1, {0x1e4b}}}, { 0x1e4c, {1, {0x1e4d}}}, { 0x1e4e, {1, {0x1e4f}}}, { 0x1e50, {1, {0x1e51}}}, { 0x1e52, {1, {0x1e53}}}, { 0x1e54, {1, {0x1e55}}}, { 0x1e56, {1, {0x1e57}}}, { 0x1e58, {1, {0x1e59}}}, { 0x1e5a, {1, {0x1e5b}}}, { 0x1e5c, {1, {0x1e5d}}}, { 0x1e5e, {1, {0x1e5f}}}, { 0x1e60, {1, {0x1e61}}}, { 0x1e62, {1, {0x1e63}}}, { 0x1e64, {1, {0x1e65}}}, { 0x1e66, {1, {0x1e67}}}, { 0x1e68, {1, {0x1e69}}}, { 0x1e6a, {1, {0x1e6b}}}, { 0x1e6c, {1, {0x1e6d}}}, { 0x1e6e, {1, {0x1e6f}}}, { 0x1e70, {1, {0x1e71}}}, { 0x1e72, {1, {0x1e73}}}, { 0x1e74, {1, {0x1e75}}}, { 0x1e76, {1, {0x1e77}}}, { 0x1e78, {1, {0x1e79}}}, { 0x1e7a, {1, {0x1e7b}}}, { 0x1e7c, {1, {0x1e7d}}}, { 0x1e7e, {1, {0x1e7f}}}, { 0x1e80, {1, {0x1e81}}}, { 0x1e82, {1, {0x1e83}}}, { 0x1e84, {1, {0x1e85}}}, { 0x1e86, {1, {0x1e87}}}, { 0x1e88, {1, {0x1e89}}}, { 0x1e8a, {1, {0x1e8b}}}, { 0x1e8c, {1, {0x1e8d}}}, { 0x1e8e, {1, {0x1e8f}}}, { 0x1e90, {1, {0x1e91}}}, { 0x1e92, {1, {0x1e93}}}, { 0x1e94, {1, {0x1e95}}}, { 0x1e96, {2, {0x0068, 0x0331}}}, { 0x1e97, {2, {0x0074, 0x0308}}}, { 0x1e98, {2, {0x0077, 0x030a}}}, { 0x1e99, {2, {0x0079, 0x030a}}}, { 0x1e9a, {2, {0x0061, 0x02be}}}, { 0x1e9b, {1, {0x1e61}}}, { 0x1e9e, {2, {0x0073, 0x0073}}}, { 0x1ea0, {1, {0x1ea1}}}, { 0x1ea2, {1, {0x1ea3}}}, { 0x1ea4, {1, {0x1ea5}}}, { 0x1ea6, {1, {0x1ea7}}}, { 0x1ea8, {1, {0x1ea9}}}, { 0x1eaa, {1, {0x1eab}}}, { 0x1eac, {1, {0x1ead}}}, { 0x1eae, {1, {0x1eaf}}}, { 0x1eb0, {1, {0x1eb1}}}, { 0x1eb2, {1, {0x1eb3}}}, { 0x1eb4, {1, {0x1eb5}}}, { 0x1eb6, {1, {0x1eb7}}}, { 0x1eb8, {1, {0x1eb9}}}, { 0x1eba, {1, {0x1ebb}}}, { 0x1ebc, {1, {0x1ebd}}}, { 0x1ebe, {1, {0x1ebf}}}, { 0x1ec0, {1, {0x1ec1}}}, { 0x1ec2, {1, {0x1ec3}}}, { 0x1ec4, {1, {0x1ec5}}}, { 0x1ec6, {1, {0x1ec7}}}, { 0x1ec8, {1, {0x1ec9}}}, { 0x1eca, {1, {0x1ecb}}}, { 0x1ecc, {1, {0x1ecd}}}, { 0x1ece, {1, {0x1ecf}}}, { 0x1ed0, {1, {0x1ed1}}}, { 0x1ed2, {1, {0x1ed3}}}, { 0x1ed4, {1, {0x1ed5}}}, { 0x1ed6, {1, {0x1ed7}}}, { 0x1ed8, {1, {0x1ed9}}}, { 0x1eda, {1, {0x1edb}}}, { 0x1edc, {1, {0x1edd}}}, { 0x1ede, {1, {0x1edf}}}, { 0x1ee0, {1, {0x1ee1}}}, { 0x1ee2, {1, {0x1ee3}}}, { 0x1ee4, {1, {0x1ee5}}}, { 0x1ee6, {1, {0x1ee7}}}, { 0x1ee8, {1, {0x1ee9}}}, { 0x1eea, {1, {0x1eeb}}}, { 0x1eec, {1, {0x1eed}}}, { 0x1eee, {1, {0x1eef}}}, { 0x1ef0, {1, {0x1ef1}}}, { 0x1ef2, {1, {0x1ef3}}}, { 0x1ef4, {1, {0x1ef5}}}, { 0x1ef6, {1, {0x1ef7}}}, { 0x1ef8, {1, {0x1ef9}}}, { 0x1efa, {1, {0x1efb}}}, { 0x1efc, {1, {0x1efd}}}, { 0x1efe, {1, {0x1eff}}}, { 0x1f08, {1, {0x1f00}}}, { 0x1f09, {1, {0x1f01}}}, { 0x1f0a, {1, {0x1f02}}}, { 0x1f0b, {1, {0x1f03}}}, { 0x1f0c, {1, {0x1f04}}}, { 0x1f0d, {1, {0x1f05}}}, { 0x1f0e, {1, {0x1f06}}}, { 0x1f0f, {1, {0x1f07}}}, { 0x1f18, {1, {0x1f10}}}, { 0x1f19, {1, {0x1f11}}}, { 0x1f1a, {1, {0x1f12}}}, { 0x1f1b, {1, {0x1f13}}}, { 0x1f1c, {1, {0x1f14}}}, { 0x1f1d, {1, {0x1f15}}}, { 0x1f28, {1, {0x1f20}}}, { 0x1f29, {1, {0x1f21}}}, { 0x1f2a, {1, {0x1f22}}}, { 0x1f2b, {1, {0x1f23}}}, { 0x1f2c, {1, {0x1f24}}}, { 0x1f2d, {1, {0x1f25}}}, { 0x1f2e, {1, {0x1f26}}}, { 0x1f2f, {1, {0x1f27}}}, { 0x1f38, {1, {0x1f30}}}, { 0x1f39, {1, {0x1f31}}}, { 0x1f3a, {1, {0x1f32}}}, { 0x1f3b, {1, {0x1f33}}}, { 0x1f3c, {1, {0x1f34}}}, { 0x1f3d, {1, {0x1f35}}}, { 0x1f3e, {1, {0x1f36}}}, { 0x1f3f, {1, {0x1f37}}}, { 0x1f48, {1, {0x1f40}}}, { 0x1f49, {1, {0x1f41}}}, { 0x1f4a, {1, {0x1f42}}}, { 0x1f4b, {1, {0x1f43}}}, { 0x1f4c, {1, {0x1f44}}}, { 0x1f4d, {1, {0x1f45}}}, { 0x1f50, {2, {0x03c5, 0x0313}}}, { 0x1f52, {3, {0x03c5, 0x0313, 0x0300}}}, { 0x1f54, {3, {0x03c5, 0x0313, 0x0301}}}, { 0x1f56, {3, {0x03c5, 0x0313, 0x0342}}}, { 0x1f59, {1, {0x1f51}}}, { 0x1f5b, {1, {0x1f53}}}, { 0x1f5d, {1, {0x1f55}}}, { 0x1f5f, {1, {0x1f57}}}, { 0x1f68, {1, {0x1f60}}}, { 0x1f69, {1, {0x1f61}}}, { 0x1f6a, {1, {0x1f62}}}, { 0x1f6b, {1, {0x1f63}}}, { 0x1f6c, {1, {0x1f64}}}, { 0x1f6d, {1, {0x1f65}}}, { 0x1f6e, {1, {0x1f66}}}, { 0x1f6f, {1, {0x1f67}}}, { 0x1f80, {2, {0x1f00, 0x03b9}}}, { 0x1f81, {2, {0x1f01, 0x03b9}}}, { 0x1f82, {2, {0x1f02, 0x03b9}}}, { 0x1f83, {2, {0x1f03, 0x03b9}}}, { 0x1f84, {2, {0x1f04, 0x03b9}}}, { 0x1f85, {2, {0x1f05, 0x03b9}}}, { 0x1f86, {2, {0x1f06, 0x03b9}}}, { 0x1f87, {2, {0x1f07, 0x03b9}}}, { 0x1f88, {2, {0x1f00, 0x03b9}}}, { 0x1f89, {2, {0x1f01, 0x03b9}}}, { 0x1f8a, {2, {0x1f02, 0x03b9}}}, { 0x1f8b, {2, {0x1f03, 0x03b9}}}, { 0x1f8c, {2, {0x1f04, 0x03b9}}}, { 0x1f8d, {2, {0x1f05, 0x03b9}}}, { 0x1f8e, {2, {0x1f06, 0x03b9}}}, { 0x1f8f, {2, {0x1f07, 0x03b9}}}, { 0x1f90, {2, {0x1f20, 0x03b9}}}, { 0x1f91, {2, {0x1f21, 0x03b9}}}, { 0x1f92, {2, {0x1f22, 0x03b9}}}, { 0x1f93, {2, {0x1f23, 0x03b9}}}, { 0x1f94, {2, {0x1f24, 0x03b9}}}, { 0x1f95, {2, {0x1f25, 0x03b9}}}, { 0x1f96, {2, {0x1f26, 0x03b9}}}, { 0x1f97, {2, {0x1f27, 0x03b9}}}, { 0x1f98, {2, {0x1f20, 0x03b9}}}, { 0x1f99, {2, {0x1f21, 0x03b9}}}, { 0x1f9a, {2, {0x1f22, 0x03b9}}}, { 0x1f9b, {2, {0x1f23, 0x03b9}}}, { 0x1f9c, {2, {0x1f24, 0x03b9}}}, { 0x1f9d, {2, {0x1f25, 0x03b9}}}, { 0x1f9e, {2, {0x1f26, 0x03b9}}}, { 0x1f9f, {2, {0x1f27, 0x03b9}}}, { 0x1fa0, {2, {0x1f60, 0x03b9}}}, { 0x1fa1, {2, {0x1f61, 0x03b9}}}, { 0x1fa2, {2, {0x1f62, 0x03b9}}}, { 0x1fa3, {2, {0x1f63, 0x03b9}}}, { 0x1fa4, {2, {0x1f64, 0x03b9}}}, { 0x1fa5, {2, {0x1f65, 0x03b9}}}, { 0x1fa6, {2, {0x1f66, 0x03b9}}}, { 0x1fa7, {2, {0x1f67, 0x03b9}}}, { 0x1fa8, {2, {0x1f60, 0x03b9}}}, { 0x1fa9, {2, {0x1f61, 0x03b9}}}, { 0x1faa, {2, {0x1f62, 0x03b9}}}, { 0x1fab, {2, {0x1f63, 0x03b9}}}, { 0x1fac, {2, {0x1f64, 0x03b9}}}, { 0x1fad, {2, {0x1f65, 0x03b9}}}, { 0x1fae, {2, {0x1f66, 0x03b9}}}, { 0x1faf, {2, {0x1f67, 0x03b9}}}, { 0x1fb2, {2, {0x1f70, 0x03b9}}}, { 0x1fb3, {2, {0x03b1, 0x03b9}}}, { 0x1fb4, {2, {0x03ac, 0x03b9}}}, { 0x1fb6, {2, {0x03b1, 0x0342}}}, { 0x1fb7, {3, {0x03b1, 0x0342, 0x03b9}}}, { 0x1fb8, {1, {0x1fb0}}}, { 0x1fb9, {1, {0x1fb1}}}, { 0x1fba, {1, {0x1f70}}}, { 0x1fbb, {1, {0x1f71}}}, { 0x1fbc, {2, {0x03b1, 0x03b9}}}, { 0x1fbe, {1, {0x03b9}}}, { 0x1fc2, {2, {0x1f74, 0x03b9}}}, { 0x1fc3, {2, {0x03b7, 0x03b9}}}, { 0x1fc4, {2, {0x03ae, 0x03b9}}}, { 0x1fc6, {2, {0x03b7, 0x0342}}}, { 0x1fc7, {3, {0x03b7, 0x0342, 0x03b9}}}, { 0x1fc8, {1, {0x1f72}}}, { 0x1fc9, {1, {0x1f73}}}, { 0x1fca, {1, {0x1f74}}}, { 0x1fcb, {1, {0x1f75}}}, { 0x1fcc, {2, {0x03b7, 0x03b9}}}, { 0x1fd2, {3, {0x03b9, 0x0308, 0x0300}}}, { 0x1fd3, {3, {0x03b9, 0x0308, 0x0301}}}, { 0x1fd6, {2, {0x03b9, 0x0342}}}, { 0x1fd7, {3, {0x03b9, 0x0308, 0x0342}}}, { 0x1fd8, {1, {0x1fd0}}}, { 0x1fd9, {1, {0x1fd1}}}, { 0x1fda, {1, {0x1f76}}}, { 0x1fdb, {1, {0x1f77}}}, { 0x1fe2, {3, {0x03c5, 0x0308, 0x0300}}}, { 0x1fe3, {3, {0x03c5, 0x0308, 0x0301}}}, { 0x1fe4, {2, {0x03c1, 0x0313}}}, { 0x1fe6, {2, {0x03c5, 0x0342}}}, { 0x1fe7, {3, {0x03c5, 0x0308, 0x0342}}}, { 0x1fe8, {1, {0x1fe0}}}, { 0x1fe9, {1, {0x1fe1}}}, { 0x1fea, {1, {0x1f7a}}}, { 0x1feb, {1, {0x1f7b}}}, { 0x1fec, {1, {0x1fe5}}}, { 0x1ff2, {2, {0x1f7c, 0x03b9}}}, { 0x1ff3, {2, {0x03c9, 0x03b9}}}, { 0x1ff4, {2, {0x03ce, 0x03b9}}}, { 0x1ff6, {2, {0x03c9, 0x0342}}}, { 0x1ff7, {3, {0x03c9, 0x0342, 0x03b9}}}, { 0x1ff8, {1, {0x1f78}}}, { 0x1ff9, {1, {0x1f79}}}, { 0x1ffa, {1, {0x1f7c}}}, { 0x1ffb, {1, {0x1f7d}}}, { 0x1ffc, {2, {0x03c9, 0x03b9}}}, { 0x2126, {1, {0x03c9}}}, { 0x212a, {1, {0x006b}}}, { 0x212b, {1, {0x00e5}}}, { 0x2132, {1, {0x214e}}}, { 0x2160, {1, {0x2170}}}, { 0x2161, {1, {0x2171}}}, { 0x2162, {1, {0x2172}}}, { 0x2163, {1, {0x2173}}}, { 0x2164, {1, {0x2174}}}, { 0x2165, {1, {0x2175}}}, { 0x2166, {1, {0x2176}}}, { 0x2167, {1, {0x2177}}}, { 0x2168, {1, {0x2178}}}, { 0x2169, {1, {0x2179}}}, { 0x216a, {1, {0x217a}}}, { 0x216b, {1, {0x217b}}}, { 0x216c, {1, {0x217c}}}, { 0x216d, {1, {0x217d}}}, { 0x216e, {1, {0x217e}}}, { 0x216f, {1, {0x217f}}}, { 0x2183, {1, {0x2184}}}, { 0x24b6, {1, {0x24d0}}}, { 0x24b7, {1, {0x24d1}}}, { 0x24b8, {1, {0x24d2}}}, { 0x24b9, {1, {0x24d3}}}, { 0x24ba, {1, {0x24d4}}}, { 0x24bb, {1, {0x24d5}}}, { 0x24bc, {1, {0x24d6}}}, { 0x24bd, {1, {0x24d7}}}, { 0x24be, {1, {0x24d8}}}, { 0x24bf, {1, {0x24d9}}}, { 0x24c0, {1, {0x24da}}}, { 0x24c1, {1, {0x24db}}}, { 0x24c2, {1, {0x24dc}}}, { 0x24c3, {1, {0x24dd}}}, { 0x24c4, {1, {0x24de}}}, { 0x24c5, {1, {0x24df}}}, { 0x24c6, {1, {0x24e0}}}, { 0x24c7, {1, {0x24e1}}}, { 0x24c8, {1, {0x24e2}}}, { 0x24c9, {1, {0x24e3}}}, { 0x24ca, {1, {0x24e4}}}, { 0x24cb, {1, {0x24e5}}}, { 0x24cc, {1, {0x24e6}}}, { 0x24cd, {1, {0x24e7}}}, { 0x24ce, {1, {0x24e8}}}, { 0x24cf, {1, {0x24e9}}}, { 0x2c00, {1, {0x2c30}}}, { 0x2c01, {1, {0x2c31}}}, { 0x2c02, {1, {0x2c32}}}, { 0x2c03, {1, {0x2c33}}}, { 0x2c04, {1, {0x2c34}}}, { 0x2c05, {1, {0x2c35}}}, { 0x2c06, {1, {0x2c36}}}, { 0x2c07, {1, {0x2c37}}}, { 0x2c08, {1, {0x2c38}}}, { 0x2c09, {1, {0x2c39}}}, { 0x2c0a, {1, {0x2c3a}}}, { 0x2c0b, {1, {0x2c3b}}}, { 0x2c0c, {1, {0x2c3c}}}, { 0x2c0d, {1, {0x2c3d}}}, { 0x2c0e, {1, {0x2c3e}}}, { 0x2c0f, {1, {0x2c3f}}}, { 0x2c10, {1, {0x2c40}}}, { 0x2c11, {1, {0x2c41}}}, { 0x2c12, {1, {0x2c42}}}, { 0x2c13, {1, {0x2c43}}}, { 0x2c14, {1, {0x2c44}}}, { 0x2c15, {1, {0x2c45}}}, { 0x2c16, {1, {0x2c46}}}, { 0x2c17, {1, {0x2c47}}}, { 0x2c18, {1, {0x2c48}}}, { 0x2c19, {1, {0x2c49}}}, { 0x2c1a, {1, {0x2c4a}}}, { 0x2c1b, {1, {0x2c4b}}}, { 0x2c1c, {1, {0x2c4c}}}, { 0x2c1d, {1, {0x2c4d}}}, { 0x2c1e, {1, {0x2c4e}}}, { 0x2c1f, {1, {0x2c4f}}}, { 0x2c20, {1, {0x2c50}}}, { 0x2c21, {1, {0x2c51}}}, { 0x2c22, {1, {0x2c52}}}, { 0x2c23, {1, {0x2c53}}}, { 0x2c24, {1, {0x2c54}}}, { 0x2c25, {1, {0x2c55}}}, { 0x2c26, {1, {0x2c56}}}, { 0x2c27, {1, {0x2c57}}}, { 0x2c28, {1, {0x2c58}}}, { 0x2c29, {1, {0x2c59}}}, { 0x2c2a, {1, {0x2c5a}}}, { 0x2c2b, {1, {0x2c5b}}}, { 0x2c2c, {1, {0x2c5c}}}, { 0x2c2d, {1, {0x2c5d}}}, { 0x2c2e, {1, {0x2c5e}}}, { 0x2c60, {1, {0x2c61}}}, { 0x2c62, {1, {0x026b}}}, { 0x2c63, {1, {0x1d7d}}}, { 0x2c64, {1, {0x027d}}}, { 0x2c67, {1, {0x2c68}}}, { 0x2c69, {1, {0x2c6a}}}, { 0x2c6b, {1, {0x2c6c}}}, { 0x2c6d, {1, {0x0251}}}, { 0x2c6e, {1, {0x0271}}}, { 0x2c6f, {1, {0x0250}}}, { 0x2c70, {1, {0x0252}}}, { 0x2c72, {1, {0x2c73}}}, { 0x2c75, {1, {0x2c76}}}, { 0x2c7e, {1, {0x023f}}}, { 0x2c7f, {1, {0x0240}}}, { 0x2c80, {1, {0x2c81}}}, { 0x2c82, {1, {0x2c83}}}, { 0x2c84, {1, {0x2c85}}}, { 0x2c86, {1, {0x2c87}}}, { 0x2c88, {1, {0x2c89}}}, { 0x2c8a, {1, {0x2c8b}}}, { 0x2c8c, {1, {0x2c8d}}}, { 0x2c8e, {1, {0x2c8f}}}, { 0x2c90, {1, {0x2c91}}}, { 0x2c92, {1, {0x2c93}}}, { 0x2c94, {1, {0x2c95}}}, { 0x2c96, {1, {0x2c97}}}, { 0x2c98, {1, {0x2c99}}}, { 0x2c9a, {1, {0x2c9b}}}, { 0x2c9c, {1, {0x2c9d}}}, { 0x2c9e, {1, {0x2c9f}}}, { 0x2ca0, {1, {0x2ca1}}}, { 0x2ca2, {1, {0x2ca3}}}, { 0x2ca4, {1, {0x2ca5}}}, { 0x2ca6, {1, {0x2ca7}}}, { 0x2ca8, {1, {0x2ca9}}}, { 0x2caa, {1, {0x2cab}}}, { 0x2cac, {1, {0x2cad}}}, { 0x2cae, {1, {0x2caf}}}, { 0x2cb0, {1, {0x2cb1}}}, { 0x2cb2, {1, {0x2cb3}}}, { 0x2cb4, {1, {0x2cb5}}}, { 0x2cb6, {1, {0x2cb7}}}, { 0x2cb8, {1, {0x2cb9}}}, { 0x2cba, {1, {0x2cbb}}}, { 0x2cbc, {1, {0x2cbd}}}, { 0x2cbe, {1, {0x2cbf}}}, { 0x2cc0, {1, {0x2cc1}}}, { 0x2cc2, {1, {0x2cc3}}}, { 0x2cc4, {1, {0x2cc5}}}, { 0x2cc6, {1, {0x2cc7}}}, { 0x2cc8, {1, {0x2cc9}}}, { 0x2cca, {1, {0x2ccb}}}, { 0x2ccc, {1, {0x2ccd}}}, { 0x2cce, {1, {0x2ccf}}}, { 0x2cd0, {1, {0x2cd1}}}, { 0x2cd2, {1, {0x2cd3}}}, { 0x2cd4, {1, {0x2cd5}}}, { 0x2cd6, {1, {0x2cd7}}}, { 0x2cd8, {1, {0x2cd9}}}, { 0x2cda, {1, {0x2cdb}}}, { 0x2cdc, {1, {0x2cdd}}}, { 0x2cde, {1, {0x2cdf}}}, { 0x2ce0, {1, {0x2ce1}}}, { 0x2ce2, {1, {0x2ce3}}}, { 0x2ceb, {1, {0x2cec}}}, { 0x2ced, {1, {0x2cee}}}, { 0x2cf2, {1, {0x2cf3}}}, { 0xa640, {1, {0xa641}}}, { 0xa642, {1, {0xa643}}}, { 0xa644, {1, {0xa645}}}, { 0xa646, {1, {0xa647}}}, { 0xa648, {1, {0xa649}}}, { 0xa64a, {1, {0xa64b}}}, { 0xa64c, {1, {0xa64d}}}, { 0xa64e, {1, {0xa64f}}}, { 0xa650, {1, {0xa651}}}, { 0xa652, {1, {0xa653}}}, { 0xa654, {1, {0xa655}}}, { 0xa656, {1, {0xa657}}}, { 0xa658, {1, {0xa659}}}, { 0xa65a, {1, {0xa65b}}}, { 0xa65c, {1, {0xa65d}}}, { 0xa65e, {1, {0xa65f}}}, { 0xa660, {1, {0xa661}}}, { 0xa662, {1, {0xa663}}}, { 0xa664, {1, {0xa665}}}, { 0xa666, {1, {0xa667}}}, { 0xa668, {1, {0xa669}}}, { 0xa66a, {1, {0xa66b}}}, { 0xa66c, {1, {0xa66d}}}, { 0xa680, {1, {0xa681}}}, { 0xa682, {1, {0xa683}}}, { 0xa684, {1, {0xa685}}}, { 0xa686, {1, {0xa687}}}, { 0xa688, {1, {0xa689}}}, { 0xa68a, {1, {0xa68b}}}, { 0xa68c, {1, {0xa68d}}}, { 0xa68e, {1, {0xa68f}}}, { 0xa690, {1, {0xa691}}}, { 0xa692, {1, {0xa693}}}, { 0xa694, {1, {0xa695}}}, { 0xa696, {1, {0xa697}}}, { 0xa722, {1, {0xa723}}}, { 0xa724, {1, {0xa725}}}, { 0xa726, {1, {0xa727}}}, { 0xa728, {1, {0xa729}}}, { 0xa72a, {1, {0xa72b}}}, { 0xa72c, {1, {0xa72d}}}, { 0xa72e, {1, {0xa72f}}}, { 0xa732, {1, {0xa733}}}, { 0xa734, {1, {0xa735}}}, { 0xa736, {1, {0xa737}}}, { 0xa738, {1, {0xa739}}}, { 0xa73a, {1, {0xa73b}}}, { 0xa73c, {1, {0xa73d}}}, { 0xa73e, {1, {0xa73f}}}, { 0xa740, {1, {0xa741}}}, { 0xa742, {1, {0xa743}}}, { 0xa744, {1, {0xa745}}}, { 0xa746, {1, {0xa747}}}, { 0xa748, {1, {0xa749}}}, { 0xa74a, {1, {0xa74b}}}, { 0xa74c, {1, {0xa74d}}}, { 0xa74e, {1, {0xa74f}}}, { 0xa750, {1, {0xa751}}}, { 0xa752, {1, {0xa753}}}, { 0xa754, {1, {0xa755}}}, { 0xa756, {1, {0xa757}}}, { 0xa758, {1, {0xa759}}}, { 0xa75a, {1, {0xa75b}}}, { 0xa75c, {1, {0xa75d}}}, { 0xa75e, {1, {0xa75f}}}, { 0xa760, {1, {0xa761}}}, { 0xa762, {1, {0xa763}}}, { 0xa764, {1, {0xa765}}}, { 0xa766, {1, {0xa767}}}, { 0xa768, {1, {0xa769}}}, { 0xa76a, {1, {0xa76b}}}, { 0xa76c, {1, {0xa76d}}}, { 0xa76e, {1, {0xa76f}}}, { 0xa779, {1, {0xa77a}}}, { 0xa77b, {1, {0xa77c}}}, { 0xa77d, {1, {0x1d79}}}, { 0xa77e, {1, {0xa77f}}}, { 0xa780, {1, {0xa781}}}, { 0xa782, {1, {0xa783}}}, { 0xa784, {1, {0xa785}}}, { 0xa786, {1, {0xa787}}}, { 0xa78b, {1, {0xa78c}}}, { 0xa78d, {1, {0x0265}}}, { 0xa790, {1, {0xa791}}}, { 0xa792, {1, {0xa793}}}, { 0xa7a0, {1, {0xa7a1}}}, { 0xa7a2, {1, {0xa7a3}}}, { 0xa7a4, {1, {0xa7a5}}}, { 0xa7a6, {1, {0xa7a7}}}, { 0xa7a8, {1, {0xa7a9}}}, { 0xa7aa, {1, {0x0266}}}, { 0xfb00, {2, {0x0066, 0x0066}}}, { 0xfb01, {2, {0x0066, 0x0069}}}, { 0xfb02, {2, {0x0066, 0x006c}}}, { 0xfb03, {3, {0x0066, 0x0066, 0x0069}}}, { 0xfb04, {3, {0x0066, 0x0066, 0x006c}}}, { 0xfb05, {2, {0x0073, 0x0074}}}, { 0xfb06, {2, {0x0073, 0x0074}}}, { 0xfb13, {2, {0x0574, 0x0576}}}, { 0xfb14, {2, {0x0574, 0x0565}}}, { 0xfb15, {2, {0x0574, 0x056b}}}, { 0xfb16, {2, {0x057e, 0x0576}}}, { 0xfb17, {2, {0x0574, 0x056d}}}, { 0xff21, {1, {0xff41}}}, { 0xff22, {1, {0xff42}}}, { 0xff23, {1, {0xff43}}}, { 0xff24, {1, {0xff44}}}, { 0xff25, {1, {0xff45}}}, { 0xff26, {1, {0xff46}}}, { 0xff27, {1, {0xff47}}}, { 0xff28, {1, {0xff48}}}, { 0xff29, {1, {0xff49}}}, { 0xff2a, {1, {0xff4a}}}, { 0xff2b, {1, {0xff4b}}}, { 0xff2c, {1, {0xff4c}}}, { 0xff2d, {1, {0xff4d}}}, { 0xff2e, {1, {0xff4e}}}, { 0xff2f, {1, {0xff4f}}}, { 0xff30, {1, {0xff50}}}, { 0xff31, {1, {0xff51}}}, { 0xff32, {1, {0xff52}}}, { 0xff33, {1, {0xff53}}}, { 0xff34, {1, {0xff54}}}, { 0xff35, {1, {0xff55}}}, { 0xff36, {1, {0xff56}}}, { 0xff37, {1, {0xff57}}}, { 0xff38, {1, {0xff58}}}, { 0xff39, {1, {0xff59}}}, { 0xff3a, {1, {0xff5a}}}, { 0x10400, {1, {0x10428}}}, { 0x10401, {1, {0x10429}}}, { 0x10402, {1, {0x1042a}}}, { 0x10403, {1, {0x1042b}}}, { 0x10404, {1, {0x1042c}}}, { 0x10405, {1, {0x1042d}}}, { 0x10406, {1, {0x1042e}}}, { 0x10407, {1, {0x1042f}}}, { 0x10408, {1, {0x10430}}}, { 0x10409, {1, {0x10431}}}, { 0x1040a, {1, {0x10432}}}, { 0x1040b, {1, {0x10433}}}, { 0x1040c, {1, {0x10434}}}, { 0x1040d, {1, {0x10435}}}, { 0x1040e, {1, {0x10436}}}, { 0x1040f, {1, {0x10437}}}, { 0x10410, {1, {0x10438}}}, { 0x10411, {1, {0x10439}}}, { 0x10412, {1, {0x1043a}}}, { 0x10413, {1, {0x1043b}}}, { 0x10414, {1, {0x1043c}}}, { 0x10415, {1, {0x1043d}}}, { 0x10416, {1, {0x1043e}}}, { 0x10417, {1, {0x1043f}}}, { 0x10418, {1, {0x10440}}}, { 0x10419, {1, {0x10441}}}, { 0x1041a, {1, {0x10442}}}, { 0x1041b, {1, {0x10443}}}, { 0x1041c, {1, {0x10444}}}, { 0x1041d, {1, {0x10445}}}, { 0x1041e, {1, {0x10446}}}, { 0x1041f, {1, {0x10447}}}, { 0x10420, {1, {0x10448}}}, { 0x10421, {1, {0x10449}}}, { 0x10422, {1, {0x1044a}}}, { 0x10423, {1, {0x1044b}}}, { 0x10424, {1, {0x1044c}}}, { 0x10425, {1, {0x1044d}}}, { 0x10426, {1, {0x1044e}}}, { 0x10427, {1, {0x1044f}}}, }; static const CaseFold_11_Type CaseFold_Locale[] = { { 0x0049, {1, {0x0069}}}, { 0x0130, {2, {0x0069, 0x0307}}}, }; static const CaseUnfold_11_Type CaseUnfold_11[] = { { 0x0061, {1, {0x0041 }}}, { 0x0062, {1, {0x0042 }}}, { 0x0063, {1, {0x0043 }}}, { 0x0064, {1, {0x0044 }}}, { 0x0065, {1, {0x0045 }}}, { 0x0066, {1, {0x0046 }}}, { 0x0067, {1, {0x0047 }}}, { 0x0068, {1, {0x0048 }}}, { 0x006a, {1, {0x004a }}}, { 0x006b, {2, {0x004b, 0x212a }}}, { 0x006c, {1, {0x004c }}}, { 0x006d, {1, {0x004d }}}, { 0x006e, {1, {0x004e }}}, { 0x006f, {1, {0x004f }}}, { 0x0070, {1, {0x0050 }}}, { 0x0071, {1, {0x0051 }}}, { 0x0072, {1, {0x0052 }}}, { 0x0073, {2, {0x0053, 0x017f }}}, { 0x0074, {1, {0x0054 }}}, { 0x0075, {1, {0x0055 }}}, { 0x0076, {1, {0x0056 }}}, { 0x0077, {1, {0x0057 }}}, { 0x0078, {1, {0x0058 }}}, { 0x0079, {1, {0x0059 }}}, { 0x007a, {1, {0x005a }}}, { 0x00e0, {1, {0x00c0 }}}, { 0x00e1, {1, {0x00c1 }}}, { 0x00e2, {1, {0x00c2 }}}, { 0x00e3, {1, {0x00c3 }}}, { 0x00e4, {1, {0x00c4 }}}, { 0x00e5, {2, {0x00c5, 0x212b }}}, { 0x00e6, {1, {0x00c6 }}}, { 0x00e7, {1, {0x00c7 }}}, { 0x00e8, {1, {0x00c8 }}}, { 0x00e9, {1, {0x00c9 }}}, { 0x00ea, {1, {0x00ca }}}, { 0x00eb, {1, {0x00cb }}}, { 0x00ec, {1, {0x00cc }}}, { 0x00ed, {1, {0x00cd }}}, { 0x00ee, {1, {0x00ce }}}, { 0x00ef, {1, {0x00cf }}}, { 0x00f0, {1, {0x00d0 }}}, { 0x00f1, {1, {0x00d1 }}}, { 0x00f2, {1, {0x00d2 }}}, { 0x00f3, {1, {0x00d3 }}}, { 0x00f4, {1, {0x00d4 }}}, { 0x00f5, {1, {0x00d5 }}}, { 0x00f6, {1, {0x00d6 }}}, { 0x00f8, {1, {0x00d8 }}}, { 0x00f9, {1, {0x00d9 }}}, { 0x00fa, {1, {0x00da }}}, { 0x00fb, {1, {0x00db }}}, { 0x00fc, {1, {0x00dc }}}, { 0x00fd, {1, {0x00dd }}}, { 0x00fe, {1, {0x00de }}}, { 0x00ff, {1, {0x0178 }}}, { 0x0101, {1, {0x0100 }}}, { 0x0103, {1, {0x0102 }}}, { 0x0105, {1, {0x0104 }}}, { 0x0107, {1, {0x0106 }}}, { 0x0109, {1, {0x0108 }}}, { 0x010b, {1, {0x010a }}}, { 0x010d, {1, {0x010c }}}, { 0x010f, {1, {0x010e }}}, { 0x0111, {1, {0x0110 }}}, { 0x0113, {1, {0x0112 }}}, { 0x0115, {1, {0x0114 }}}, { 0x0117, {1, {0x0116 }}}, { 0x0119, {1, {0x0118 }}}, { 0x011b, {1, {0x011a }}}, { 0x011d, {1, {0x011c }}}, { 0x011f, {1, {0x011e }}}, { 0x0121, {1, {0x0120 }}}, { 0x0123, {1, {0x0122 }}}, { 0x0125, {1, {0x0124 }}}, { 0x0127, {1, {0x0126 }}}, { 0x0129, {1, {0x0128 }}}, { 0x012b, {1, {0x012a }}}, { 0x012d, {1, {0x012c }}}, { 0x012f, {1, {0x012e }}}, { 0x0133, {1, {0x0132 }}}, { 0x0135, {1, {0x0134 }}}, { 0x0137, {1, {0x0136 }}}, { 0x013a, {1, {0x0139 }}}, { 0x013c, {1, {0x013b }}}, { 0x013e, {1, {0x013d }}}, { 0x0140, {1, {0x013f }}}, { 0x0142, {1, {0x0141 }}}, { 0x0144, {1, {0x0143 }}}, { 0x0146, {1, {0x0145 }}}, { 0x0148, {1, {0x0147 }}}, { 0x014b, {1, {0x014a }}}, { 0x014d, {1, {0x014c }}}, { 0x014f, {1, {0x014e }}}, { 0x0151, {1, {0x0150 }}}, { 0x0153, {1, {0x0152 }}}, { 0x0155, {1, {0x0154 }}}, { 0x0157, {1, {0x0156 }}}, { 0x0159, {1, {0x0158 }}}, { 0x015b, {1, {0x015a }}}, { 0x015d, {1, {0x015c }}}, { 0x015f, {1, {0x015e }}}, { 0x0161, {1, {0x0160 }}}, { 0x0163, {1, {0x0162 }}}, { 0x0165, {1, {0x0164 }}}, { 0x0167, {1, {0x0166 }}}, { 0x0169, {1, {0x0168 }}}, { 0x016b, {1, {0x016a }}}, { 0x016d, {1, {0x016c }}}, { 0x016f, {1, {0x016e }}}, { 0x0171, {1, {0x0170 }}}, { 0x0173, {1, {0x0172 }}}, { 0x0175, {1, {0x0174 }}}, { 0x0177, {1, {0x0176 }}}, { 0x017a, {1, {0x0179 }}}, { 0x017c, {1, {0x017b }}}, { 0x017e, {1, {0x017d }}}, { 0x0180, {1, {0x0243 }}}, { 0x0183, {1, {0x0182 }}}, { 0x0185, {1, {0x0184 }}}, { 0x0188, {1, {0x0187 }}}, { 0x018c, {1, {0x018b }}}, { 0x0192, {1, {0x0191 }}}, { 0x0195, {1, {0x01f6 }}}, { 0x0199, {1, {0x0198 }}}, { 0x019a, {1, {0x023d }}}, { 0x019e, {1, {0x0220 }}}, { 0x01a1, {1, {0x01a0 }}}, { 0x01a3, {1, {0x01a2 }}}, { 0x01a5, {1, {0x01a4 }}}, { 0x01a8, {1, {0x01a7 }}}, { 0x01ad, {1, {0x01ac }}}, { 0x01b0, {1, {0x01af }}}, { 0x01b4, {1, {0x01b3 }}}, { 0x01b6, {1, {0x01b5 }}}, { 0x01b9, {1, {0x01b8 }}}, { 0x01bd, {1, {0x01bc }}}, { 0x01bf, {1, {0x01f7 }}}, { 0x01c6, {2, {0x01c4, 0x01c5 }}}, { 0x01c9, {2, {0x01c7, 0x01c8 }}}, { 0x01cc, {2, {0x01ca, 0x01cb }}}, { 0x01ce, {1, {0x01cd }}}, { 0x01d0, {1, {0x01cf }}}, { 0x01d2, {1, {0x01d1 }}}, { 0x01d4, {1, {0x01d3 }}}, { 0x01d6, {1, {0x01d5 }}}, { 0x01d8, {1, {0x01d7 }}}, { 0x01da, {1, {0x01d9 }}}, { 0x01dc, {1, {0x01db }}}, { 0x01dd, {1, {0x018e }}}, { 0x01df, {1, {0x01de }}}, { 0x01e1, {1, {0x01e0 }}}, { 0x01e3, {1, {0x01e2 }}}, { 0x01e5, {1, {0x01e4 }}}, { 0x01e7, {1, {0x01e6 }}}, { 0x01e9, {1, {0x01e8 }}}, { 0x01eb, {1, {0x01ea }}}, { 0x01ed, {1, {0x01ec }}}, { 0x01ef, {1, {0x01ee }}}, { 0x01f3, {2, {0x01f1, 0x01f2 }}}, { 0x01f5, {1, {0x01f4 }}}, { 0x01f9, {1, {0x01f8 }}}, { 0x01fb, {1, {0x01fa }}}, { 0x01fd, {1, {0x01fc }}}, { 0x01ff, {1, {0x01fe }}}, { 0x0201, {1, {0x0200 }}}, { 0x0203, {1, {0x0202 }}}, { 0x0205, {1, {0x0204 }}}, { 0x0207, {1, {0x0206 }}}, { 0x0209, {1, {0x0208 }}}, { 0x020b, {1, {0x020a }}}, { 0x020d, {1, {0x020c }}}, { 0x020f, {1, {0x020e }}}, { 0x0211, {1, {0x0210 }}}, { 0x0213, {1, {0x0212 }}}, { 0x0215, {1, {0x0214 }}}, { 0x0217, {1, {0x0216 }}}, { 0x0219, {1, {0x0218 }}}, { 0x021b, {1, {0x021a }}}, { 0x021d, {1, {0x021c }}}, { 0x021f, {1, {0x021e }}}, { 0x0223, {1, {0x0222 }}}, { 0x0225, {1, {0x0224 }}}, { 0x0227, {1, {0x0226 }}}, { 0x0229, {1, {0x0228 }}}, { 0x022b, {1, {0x022a }}}, { 0x022d, {1, {0x022c }}}, { 0x022f, {1, {0x022e }}}, { 0x0231, {1, {0x0230 }}}, { 0x0233, {1, {0x0232 }}}, { 0x023c, {1, {0x023b }}}, { 0x023f, {1, {0x2c7e }}}, { 0x0240, {1, {0x2c7f }}}, { 0x0242, {1, {0x0241 }}}, { 0x0247, {1, {0x0246 }}}, { 0x0249, {1, {0x0248 }}}, { 0x024b, {1, {0x024a }}}, { 0x024d, {1, {0x024c }}}, { 0x024f, {1, {0x024e }}}, { 0x0250, {1, {0x2c6f }}}, { 0x0251, {1, {0x2c6d }}}, { 0x0252, {1, {0x2c70 }}}, { 0x0253, {1, {0x0181 }}}, { 0x0254, {1, {0x0186 }}}, { 0x0256, {1, {0x0189 }}}, { 0x0257, {1, {0x018a }}}, { 0x0259, {1, {0x018f }}}, { 0x025b, {1, {0x0190 }}}, { 0x0260, {1, {0x0193 }}}, { 0x0263, {1, {0x0194 }}}, { 0x0265, {1, {0xa78d }}}, { 0x0266, {1, {0xa7aa }}}, { 0x0268, {1, {0x0197 }}}, { 0x0269, {1, {0x0196 }}}, { 0x026b, {1, {0x2c62 }}}, { 0x026f, {1, {0x019c }}}, { 0x0271, {1, {0x2c6e }}}, { 0x0272, {1, {0x019d }}}, { 0x0275, {1, {0x019f }}}, { 0x027d, {1, {0x2c64 }}}, { 0x0280, {1, {0x01a6 }}}, { 0x0283, {1, {0x01a9 }}}, { 0x0288, {1, {0x01ae }}}, { 0x0289, {1, {0x0244 }}}, { 0x028a, {1, {0x01b1 }}}, { 0x028b, {1, {0x01b2 }}}, { 0x028c, {1, {0x0245 }}}, { 0x0292, {1, {0x01b7 }}}, { 0x0371, {1, {0x0370 }}}, { 0x0373, {1, {0x0372 }}}, { 0x0377, {1, {0x0376 }}}, { 0x037b, {1, {0x03fd }}}, { 0x037c, {1, {0x03fe }}}, { 0x037d, {1, {0x03ff }}}, { 0x03ac, {1, {0x0386 }}}, { 0x03ad, {1, {0x0388 }}}, { 0x03ae, {1, {0x0389 }}}, { 0x03af, {1, {0x038a }}}, { 0x03b1, {1, {0x0391 }}}, { 0x03b2, {2, {0x0392, 0x03d0 }}}, { 0x03b3, {1, {0x0393 }}}, { 0x03b4, {1, {0x0394 }}}, { 0x03b5, {2, {0x0395, 0x03f5 }}}, { 0x03b6, {1, {0x0396 }}}, { 0x03b7, {1, {0x0397 }}}, { 0x03b8, {3, {0x0398, 0x03d1, 0x03f4 }}}, { 0x03b9, {3, {0x0345, 0x0399, 0x1fbe }}}, { 0x03ba, {2, {0x039a, 0x03f0 }}}, { 0x03bb, {1, {0x039b }}}, { 0x03bc, {2, {0x00b5, 0x039c }}}, { 0x03bd, {1, {0x039d }}}, { 0x03be, {1, {0x039e }}}, { 0x03bf, {1, {0x039f }}}, { 0x03c0, {2, {0x03a0, 0x03d6 }}}, { 0x03c1, {2, {0x03a1, 0x03f1 }}}, { 0x03c3, {2, {0x03a3, 0x03c2 }}}, { 0x03c4, {1, {0x03a4 }}}, { 0x03c5, {1, {0x03a5 }}}, { 0x03c6, {2, {0x03a6, 0x03d5 }}}, { 0x03c7, {1, {0x03a7 }}}, { 0x03c8, {1, {0x03a8 }}}, { 0x03c9, {2, {0x03a9, 0x2126 }}}, { 0x03ca, {1, {0x03aa }}}, { 0x03cb, {1, {0x03ab }}}, { 0x03cc, {1, {0x038c }}}, { 0x03cd, {1, {0x038e }}}, { 0x03ce, {1, {0x038f }}}, { 0x03d7, {1, {0x03cf }}}, { 0x03d9, {1, {0x03d8 }}}, { 0x03db, {1, {0x03da }}}, { 0x03dd, {1, {0x03dc }}}, { 0x03df, {1, {0x03de }}}, { 0x03e1, {1, {0x03e0 }}}, { 0x03e3, {1, {0x03e2 }}}, { 0x03e5, {1, {0x03e4 }}}, { 0x03e7, {1, {0x03e6 }}}, { 0x03e9, {1, {0x03e8 }}}, { 0x03eb, {1, {0x03ea }}}, { 0x03ed, {1, {0x03ec }}}, { 0x03ef, {1, {0x03ee }}}, { 0x03f2, {1, {0x03f9 }}}, { 0x03f8, {1, {0x03f7 }}}, { 0x03fb, {1, {0x03fa }}}, { 0x0430, {1, {0x0410 }}}, { 0x0431, {1, {0x0411 }}}, { 0x0432, {1, {0x0412 }}}, { 0x0433, {1, {0x0413 }}}, { 0x0434, {1, {0x0414 }}}, { 0x0435, {1, {0x0415 }}}, { 0x0436, {1, {0x0416 }}}, { 0x0437, {1, {0x0417 }}}, { 0x0438, {1, {0x0418 }}}, { 0x0439, {1, {0x0419 }}}, { 0x043a, {1, {0x041a }}}, { 0x043b, {1, {0x041b }}}, { 0x043c, {1, {0x041c }}}, { 0x043d, {1, {0x041d }}}, { 0x043e, {1, {0x041e }}}, { 0x043f, {1, {0x041f }}}, { 0x0440, {1, {0x0420 }}}, { 0x0441, {1, {0x0421 }}}, { 0x0442, {1, {0x0422 }}}, { 0x0443, {1, {0x0423 }}}, { 0x0444, {1, {0x0424 }}}, { 0x0445, {1, {0x0425 }}}, { 0x0446, {1, {0x0426 }}}, { 0x0447, {1, {0x0427 }}}, { 0x0448, {1, {0x0428 }}}, { 0x0449, {1, {0x0429 }}}, { 0x044a, {1, {0x042a }}}, { 0x044b, {1, {0x042b }}}, { 0x044c, {1, {0x042c }}}, { 0x044d, {1, {0x042d }}}, { 0x044e, {1, {0x042e }}}, { 0x044f, {1, {0x042f }}}, { 0x0450, {1, {0x0400 }}}, { 0x0451, {1, {0x0401 }}}, { 0x0452, {1, {0x0402 }}}, { 0x0453, {1, {0x0403 }}}, { 0x0454, {1, {0x0404 }}}, { 0x0455, {1, {0x0405 }}}, { 0x0456, {1, {0x0406 }}}, { 0x0457, {1, {0x0407 }}}, { 0x0458, {1, {0x0408 }}}, { 0x0459, {1, {0x0409 }}}, { 0x045a, {1, {0x040a }}}, { 0x045b, {1, {0x040b }}}, { 0x045c, {1, {0x040c }}}, { 0x045d, {1, {0x040d }}}, { 0x045e, {1, {0x040e }}}, { 0x045f, {1, {0x040f }}}, { 0x0461, {1, {0x0460 }}}, { 0x0463, {1, {0x0462 }}}, { 0x0465, {1, {0x0464 }}}, { 0x0467, {1, {0x0466 }}}, { 0x0469, {1, {0x0468 }}}, { 0x046b, {1, {0x046a }}}, { 0x046d, {1, {0x046c }}}, { 0x046f, {1, {0x046e }}}, { 0x0471, {1, {0x0470 }}}, { 0x0473, {1, {0x0472 }}}, { 0x0475, {1, {0x0474 }}}, { 0x0477, {1, {0x0476 }}}, { 0x0479, {1, {0x0478 }}}, { 0x047b, {1, {0x047a }}}, { 0x047d, {1, {0x047c }}}, { 0x047f, {1, {0x047e }}}, { 0x0481, {1, {0x0480 }}}, { 0x048b, {1, {0x048a }}}, { 0x048d, {1, {0x048c }}}, { 0x048f, {1, {0x048e }}}, { 0x0491, {1, {0x0490 }}}, { 0x0493, {1, {0x0492 }}}, { 0x0495, {1, {0x0494 }}}, { 0x0497, {1, {0x0496 }}}, { 0x0499, {1, {0x0498 }}}, { 0x049b, {1, {0x049a }}}, { 0x049d, {1, {0x049c }}}, { 0x049f, {1, {0x049e }}}, { 0x04a1, {1, {0x04a0 }}}, { 0x04a3, {1, {0x04a2 }}}, { 0x04a5, {1, {0x04a4 }}}, { 0x04a7, {1, {0x04a6 }}}, { 0x04a9, {1, {0x04a8 }}}, { 0x04ab, {1, {0x04aa }}}, { 0x04ad, {1, {0x04ac }}}, { 0x04af, {1, {0x04ae }}}, { 0x04b1, {1, {0x04b0 }}}, { 0x04b3, {1, {0x04b2 }}}, { 0x04b5, {1, {0x04b4 }}}, { 0x04b7, {1, {0x04b6 }}}, { 0x04b9, {1, {0x04b8 }}}, { 0x04bb, {1, {0x04ba }}}, { 0x04bd, {1, {0x04bc }}}, { 0x04bf, {1, {0x04be }}}, { 0x04c2, {1, {0x04c1 }}}, { 0x04c4, {1, {0x04c3 }}}, { 0x04c6, {1, {0x04c5 }}}, { 0x04c8, {1, {0x04c7 }}}, { 0x04ca, {1, {0x04c9 }}}, { 0x04cc, {1, {0x04cb }}}, { 0x04ce, {1, {0x04cd }}}, { 0x04cf, {1, {0x04c0 }}}, { 0x04d1, {1, {0x04d0 }}}, { 0x04d3, {1, {0x04d2 }}}, { 0x04d5, {1, {0x04d4 }}}, { 0x04d7, {1, {0x04d6 }}}, { 0x04d9, {1, {0x04d8 }}}, { 0x04db, {1, {0x04da }}}, { 0x04dd, {1, {0x04dc }}}, { 0x04df, {1, {0x04de }}}, { 0x04e1, {1, {0x04e0 }}}, { 0x04e3, {1, {0x04e2 }}}, { 0x04e5, {1, {0x04e4 }}}, { 0x04e7, {1, {0x04e6 }}}, { 0x04e9, {1, {0x04e8 }}}, { 0x04eb, {1, {0x04ea }}}, { 0x04ed, {1, {0x04ec }}}, { 0x04ef, {1, {0x04ee }}}, { 0x04f1, {1, {0x04f0 }}}, { 0x04f3, {1, {0x04f2 }}}, { 0x04f5, {1, {0x04f4 }}}, { 0x04f7, {1, {0x04f6 }}}, { 0x04f9, {1, {0x04f8 }}}, { 0x04fb, {1, {0x04fa }}}, { 0x04fd, {1, {0x04fc }}}, { 0x04ff, {1, {0x04fe }}}, { 0x0501, {1, {0x0500 }}}, { 0x0503, {1, {0x0502 }}}, { 0x0505, {1, {0x0504 }}}, { 0x0507, {1, {0x0506 }}}, { 0x0509, {1, {0x0508 }}}, { 0x050b, {1, {0x050a }}}, { 0x050d, {1, {0x050c }}}, { 0x050f, {1, {0x050e }}}, { 0x0511, {1, {0x0510 }}}, { 0x0513, {1, {0x0512 }}}, { 0x0515, {1, {0x0514 }}}, { 0x0517, {1, {0x0516 }}}, { 0x0519, {1, {0x0518 }}}, { 0x051b, {1, {0x051a }}}, { 0x051d, {1, {0x051c }}}, { 0x051f, {1, {0x051e }}}, { 0x0521, {1, {0x0520 }}}, { 0x0523, {1, {0x0522 }}}, { 0x0525, {1, {0x0524 }}}, { 0x0527, {1, {0x0526 }}}, { 0x0561, {1, {0x0531 }}}, { 0x0562, {1, {0x0532 }}}, { 0x0563, {1, {0x0533 }}}, { 0x0564, {1, {0x0534 }}}, { 0x0565, {1, {0x0535 }}}, { 0x0566, {1, {0x0536 }}}, { 0x0567, {1, {0x0537 }}}, { 0x0568, {1, {0x0538 }}}, { 0x0569, {1, {0x0539 }}}, { 0x056a, {1, {0x053a }}}, { 0x056b, {1, {0x053b }}}, { 0x056c, {1, {0x053c }}}, { 0x056d, {1, {0x053d }}}, { 0x056e, {1, {0x053e }}}, { 0x056f, {1, {0x053f }}}, { 0x0570, {1, {0x0540 }}}, { 0x0571, {1, {0x0541 }}}, { 0x0572, {1, {0x0542 }}}, { 0x0573, {1, {0x0543 }}}, { 0x0574, {1, {0x0544 }}}, { 0x0575, {1, {0x0545 }}}, { 0x0576, {1, {0x0546 }}}, { 0x0577, {1, {0x0547 }}}, { 0x0578, {1, {0x0548 }}}, { 0x0579, {1, {0x0549 }}}, { 0x057a, {1, {0x054a }}}, { 0x057b, {1, {0x054b }}}, { 0x057c, {1, {0x054c }}}, { 0x057d, {1, {0x054d }}}, { 0x057e, {1, {0x054e }}}, { 0x057f, {1, {0x054f }}}, { 0x0580, {1, {0x0550 }}}, { 0x0581, {1, {0x0551 }}}, { 0x0582, {1, {0x0552 }}}, { 0x0583, {1, {0x0553 }}}, { 0x0584, {1, {0x0554 }}}, { 0x0585, {1, {0x0555 }}}, { 0x0586, {1, {0x0556 }}}, { 0x1d79, {1, {0xa77d }}}, { 0x1d7d, {1, {0x2c63 }}}, { 0x1e01, {1, {0x1e00 }}}, { 0x1e03, {1, {0x1e02 }}}, { 0x1e05, {1, {0x1e04 }}}, { 0x1e07, {1, {0x1e06 }}}, { 0x1e09, {1, {0x1e08 }}}, { 0x1e0b, {1, {0x1e0a }}}, { 0x1e0d, {1, {0x1e0c }}}, { 0x1e0f, {1, {0x1e0e }}}, { 0x1e11, {1, {0x1e10 }}}, { 0x1e13, {1, {0x1e12 }}}, { 0x1e15, {1, {0x1e14 }}}, { 0x1e17, {1, {0x1e16 }}}, { 0x1e19, {1, {0x1e18 }}}, { 0x1e1b, {1, {0x1e1a }}}, { 0x1e1d, {1, {0x1e1c }}}, { 0x1e1f, {1, {0x1e1e }}}, { 0x1e21, {1, {0x1e20 }}}, { 0x1e23, {1, {0x1e22 }}}, { 0x1e25, {1, {0x1e24 }}}, { 0x1e27, {1, {0x1e26 }}}, { 0x1e29, {1, {0x1e28 }}}, { 0x1e2b, {1, {0x1e2a }}}, { 0x1e2d, {1, {0x1e2c }}}, { 0x1e2f, {1, {0x1e2e }}}, { 0x1e31, {1, {0x1e30 }}}, { 0x1e33, {1, {0x1e32 }}}, { 0x1e35, {1, {0x1e34 }}}, { 0x1e37, {1, {0x1e36 }}}, { 0x1e39, {1, {0x1e38 }}}, { 0x1e3b, {1, {0x1e3a }}}, { 0x1e3d, {1, {0x1e3c }}}, { 0x1e3f, {1, {0x1e3e }}}, { 0x1e41, {1, {0x1e40 }}}, { 0x1e43, {1, {0x1e42 }}}, { 0x1e45, {1, {0x1e44 }}}, { 0x1e47, {1, {0x1e46 }}}, { 0x1e49, {1, {0x1e48 }}}, { 0x1e4b, {1, {0x1e4a }}}, { 0x1e4d, {1, {0x1e4c }}}, { 0x1e4f, {1, {0x1e4e }}}, { 0x1e51, {1, {0x1e50 }}}, { 0x1e53, {1, {0x1e52 }}}, { 0x1e55, {1, {0x1e54 }}}, { 0x1e57, {1, {0x1e56 }}}, { 0x1e59, {1, {0x1e58 }}}, { 0x1e5b, {1, {0x1e5a }}}, { 0x1e5d, {1, {0x1e5c }}}, { 0x1e5f, {1, {0x1e5e }}}, { 0x1e61, {2, {0x1e60, 0x1e9b }}}, { 0x1e63, {1, {0x1e62 }}}, { 0x1e65, {1, {0x1e64 }}}, { 0x1e67, {1, {0x1e66 }}}, { 0x1e69, {1, {0x1e68 }}}, { 0x1e6b, {1, {0x1e6a }}}, { 0x1e6d, {1, {0x1e6c }}}, { 0x1e6f, {1, {0x1e6e }}}, { 0x1e71, {1, {0x1e70 }}}, { 0x1e73, {1, {0x1e72 }}}, { 0x1e75, {1, {0x1e74 }}}, { 0x1e77, {1, {0x1e76 }}}, { 0x1e79, {1, {0x1e78 }}}, { 0x1e7b, {1, {0x1e7a }}}, { 0x1e7d, {1, {0x1e7c }}}, { 0x1e7f, {1, {0x1e7e }}}, { 0x1e81, {1, {0x1e80 }}}, { 0x1e83, {1, {0x1e82 }}}, { 0x1e85, {1, {0x1e84 }}}, { 0x1e87, {1, {0x1e86 }}}, { 0x1e89, {1, {0x1e88 }}}, { 0x1e8b, {1, {0x1e8a }}}, { 0x1e8d, {1, {0x1e8c }}}, { 0x1e8f, {1, {0x1e8e }}}, { 0x1e91, {1, {0x1e90 }}}, { 0x1e93, {1, {0x1e92 }}}, { 0x1e95, {1, {0x1e94 }}}, { 0x1ea1, {1, {0x1ea0 }}}, { 0x1ea3, {1, {0x1ea2 }}}, { 0x1ea5, {1, {0x1ea4 }}}, { 0x1ea7, {1, {0x1ea6 }}}, { 0x1ea9, {1, {0x1ea8 }}}, { 0x1eab, {1, {0x1eaa }}}, { 0x1ead, {1, {0x1eac }}}, { 0x1eaf, {1, {0x1eae }}}, { 0x1eb1, {1, {0x1eb0 }}}, { 0x1eb3, {1, {0x1eb2 }}}, { 0x1eb5, {1, {0x1eb4 }}}, { 0x1eb7, {1, {0x1eb6 }}}, { 0x1eb9, {1, {0x1eb8 }}}, { 0x1ebb, {1, {0x1eba }}}, { 0x1ebd, {1, {0x1ebc }}}, { 0x1ebf, {1, {0x1ebe }}}, { 0x1ec1, {1, {0x1ec0 }}}, { 0x1ec3, {1, {0x1ec2 }}}, { 0x1ec5, {1, {0x1ec4 }}}, { 0x1ec7, {1, {0x1ec6 }}}, { 0x1ec9, {1, {0x1ec8 }}}, { 0x1ecb, {1, {0x1eca }}}, { 0x1ecd, {1, {0x1ecc }}}, { 0x1ecf, {1, {0x1ece }}}, { 0x1ed1, {1, {0x1ed0 }}}, { 0x1ed3, {1, {0x1ed2 }}}, { 0x1ed5, {1, {0x1ed4 }}}, { 0x1ed7, {1, {0x1ed6 }}}, { 0x1ed9, {1, {0x1ed8 }}}, { 0x1edb, {1, {0x1eda }}}, { 0x1edd, {1, {0x1edc }}}, { 0x1edf, {1, {0x1ede }}}, { 0x1ee1, {1, {0x1ee0 }}}, { 0x1ee3, {1, {0x1ee2 }}}, { 0x1ee5, {1, {0x1ee4 }}}, { 0x1ee7, {1, {0x1ee6 }}}, { 0x1ee9, {1, {0x1ee8 }}}, { 0x1eeb, {1, {0x1eea }}}, { 0x1eed, {1, {0x1eec }}}, { 0x1eef, {1, {0x1eee }}}, { 0x1ef1, {1, {0x1ef0 }}}, { 0x1ef3, {1, {0x1ef2 }}}, { 0x1ef5, {1, {0x1ef4 }}}, { 0x1ef7, {1, {0x1ef6 }}}, { 0x1ef9, {1, {0x1ef8 }}}, { 0x1efb, {1, {0x1efa }}}, { 0x1efd, {1, {0x1efc }}}, { 0x1eff, {1, {0x1efe }}}, { 0x1f00, {1, {0x1f08 }}}, { 0x1f01, {1, {0x1f09 }}}, { 0x1f02, {1, {0x1f0a }}}, { 0x1f03, {1, {0x1f0b }}}, { 0x1f04, {1, {0x1f0c }}}, { 0x1f05, {1, {0x1f0d }}}, { 0x1f06, {1, {0x1f0e }}}, { 0x1f07, {1, {0x1f0f }}}, { 0x1f10, {1, {0x1f18 }}}, { 0x1f11, {1, {0x1f19 }}}, { 0x1f12, {1, {0x1f1a }}}, { 0x1f13, {1, {0x1f1b }}}, { 0x1f14, {1, {0x1f1c }}}, { 0x1f15, {1, {0x1f1d }}}, { 0x1f20, {1, {0x1f28 }}}, { 0x1f21, {1, {0x1f29 }}}, { 0x1f22, {1, {0x1f2a }}}, { 0x1f23, {1, {0x1f2b }}}, { 0x1f24, {1, {0x1f2c }}}, { 0x1f25, {1, {0x1f2d }}}, { 0x1f26, {1, {0x1f2e }}}, { 0x1f27, {1, {0x1f2f }}}, { 0x1f30, {1, {0x1f38 }}}, { 0x1f31, {1, {0x1f39 }}}, { 0x1f32, {1, {0x1f3a }}}, { 0x1f33, {1, {0x1f3b }}}, { 0x1f34, {1, {0x1f3c }}}, { 0x1f35, {1, {0x1f3d }}}, { 0x1f36, {1, {0x1f3e }}}, { 0x1f37, {1, {0x1f3f }}}, { 0x1f40, {1, {0x1f48 }}}, { 0x1f41, {1, {0x1f49 }}}, { 0x1f42, {1, {0x1f4a }}}, { 0x1f43, {1, {0x1f4b }}}, { 0x1f44, {1, {0x1f4c }}}, { 0x1f45, {1, {0x1f4d }}}, { 0x1f51, {1, {0x1f59 }}}, { 0x1f53, {1, {0x1f5b }}}, { 0x1f55, {1, {0x1f5d }}}, { 0x1f57, {1, {0x1f5f }}}, { 0x1f60, {1, {0x1f68 }}}, { 0x1f61, {1, {0x1f69 }}}, { 0x1f62, {1, {0x1f6a }}}, { 0x1f63, {1, {0x1f6b }}}, { 0x1f64, {1, {0x1f6c }}}, { 0x1f65, {1, {0x1f6d }}}, { 0x1f66, {1, {0x1f6e }}}, { 0x1f67, {1, {0x1f6f }}}, { 0x1f70, {1, {0x1fba }}}, { 0x1f71, {1, {0x1fbb }}}, { 0x1f72, {1, {0x1fc8 }}}, { 0x1f73, {1, {0x1fc9 }}}, { 0x1f74, {1, {0x1fca }}}, { 0x1f75, {1, {0x1fcb }}}, { 0x1f76, {1, {0x1fda }}}, { 0x1f77, {1, {0x1fdb }}}, { 0x1f78, {1, {0x1ff8 }}}, { 0x1f79, {1, {0x1ff9 }}}, { 0x1f7a, {1, {0x1fea }}}, { 0x1f7b, {1, {0x1feb }}}, { 0x1f7c, {1, {0x1ffa }}}, { 0x1f7d, {1, {0x1ffb }}}, { 0x1fb0, {1, {0x1fb8 }}}, { 0x1fb1, {1, {0x1fb9 }}}, { 0x1fd0, {1, {0x1fd8 }}}, { 0x1fd1, {1, {0x1fd9 }}}, { 0x1fe0, {1, {0x1fe8 }}}, { 0x1fe1, {1, {0x1fe9 }}}, { 0x1fe5, {1, {0x1fec }}}, { 0x214e, {1, {0x2132 }}}, { 0x2170, {1, {0x2160 }}}, { 0x2171, {1, {0x2161 }}}, { 0x2172, {1, {0x2162 }}}, { 0x2173, {1, {0x2163 }}}, { 0x2174, {1, {0x2164 }}}, { 0x2175, {1, {0x2165 }}}, { 0x2176, {1, {0x2166 }}}, { 0x2177, {1, {0x2167 }}}, { 0x2178, {1, {0x2168 }}}, { 0x2179, {1, {0x2169 }}}, { 0x217a, {1, {0x216a }}}, { 0x217b, {1, {0x216b }}}, { 0x217c, {1, {0x216c }}}, { 0x217d, {1, {0x216d }}}, { 0x217e, {1, {0x216e }}}, { 0x217f, {1, {0x216f }}}, { 0x2184, {1, {0x2183 }}}, { 0x24d0, {1, {0x24b6 }}}, { 0x24d1, {1, {0x24b7 }}}, { 0x24d2, {1, {0x24b8 }}}, { 0x24d3, {1, {0x24b9 }}}, { 0x24d4, {1, {0x24ba }}}, { 0x24d5, {1, {0x24bb }}}, { 0x24d6, {1, {0x24bc }}}, { 0x24d7, {1, {0x24bd }}}, { 0x24d8, {1, {0x24be }}}, { 0x24d9, {1, {0x24bf }}}, { 0x24da, {1, {0x24c0 }}}, { 0x24db, {1, {0x24c1 }}}, { 0x24dc, {1, {0x24c2 }}}, { 0x24dd, {1, {0x24c3 }}}, { 0x24de, {1, {0x24c4 }}}, { 0x24df, {1, {0x24c5 }}}, { 0x24e0, {1, {0x24c6 }}}, { 0x24e1, {1, {0x24c7 }}}, { 0x24e2, {1, {0x24c8 }}}, { 0x24e3, {1, {0x24c9 }}}, { 0x24e4, {1, {0x24ca }}}, { 0x24e5, {1, {0x24cb }}}, { 0x24e6, {1, {0x24cc }}}, { 0x24e7, {1, {0x24cd }}}, { 0x24e8, {1, {0x24ce }}}, { 0x24e9, {1, {0x24cf }}}, { 0x2c30, {1, {0x2c00 }}}, { 0x2c31, {1, {0x2c01 }}}, { 0x2c32, {1, {0x2c02 }}}, { 0x2c33, {1, {0x2c03 }}}, { 0x2c34, {1, {0x2c04 }}}, { 0x2c35, {1, {0x2c05 }}}, { 0x2c36, {1, {0x2c06 }}}, { 0x2c37, {1, {0x2c07 }}}, { 0x2c38, {1, {0x2c08 }}}, { 0x2c39, {1, {0x2c09 }}}, { 0x2c3a, {1, {0x2c0a }}}, { 0x2c3b, {1, {0x2c0b }}}, { 0x2c3c, {1, {0x2c0c }}}, { 0x2c3d, {1, {0x2c0d }}}, { 0x2c3e, {1, {0x2c0e }}}, { 0x2c3f, {1, {0x2c0f }}}, { 0x2c40, {1, {0x2c10 }}}, { 0x2c41, {1, {0x2c11 }}}, { 0x2c42, {1, {0x2c12 }}}, { 0x2c43, {1, {0x2c13 }}}, { 0x2c44, {1, {0x2c14 }}}, { 0x2c45, {1, {0x2c15 }}}, { 0x2c46, {1, {0x2c16 }}}, { 0x2c47, {1, {0x2c17 }}}, { 0x2c48, {1, {0x2c18 }}}, { 0x2c49, {1, {0x2c19 }}}, { 0x2c4a, {1, {0x2c1a }}}, { 0x2c4b, {1, {0x2c1b }}}, { 0x2c4c, {1, {0x2c1c }}}, { 0x2c4d, {1, {0x2c1d }}}, { 0x2c4e, {1, {0x2c1e }}}, { 0x2c4f, {1, {0x2c1f }}}, { 0x2c50, {1, {0x2c20 }}}, { 0x2c51, {1, {0x2c21 }}}, { 0x2c52, {1, {0x2c22 }}}, { 0x2c53, {1, {0x2c23 }}}, { 0x2c54, {1, {0x2c24 }}}, { 0x2c55, {1, {0x2c25 }}}, { 0x2c56, {1, {0x2c26 }}}, { 0x2c57, {1, {0x2c27 }}}, { 0x2c58, {1, {0x2c28 }}}, { 0x2c59, {1, {0x2c29 }}}, { 0x2c5a, {1, {0x2c2a }}}, { 0x2c5b, {1, {0x2c2b }}}, { 0x2c5c, {1, {0x2c2c }}}, { 0x2c5d, {1, {0x2c2d }}}, { 0x2c5e, {1, {0x2c2e }}}, { 0x2c61, {1, {0x2c60 }}}, { 0x2c65, {1, {0x023a }}}, { 0x2c66, {1, {0x023e }}}, { 0x2c68, {1, {0x2c67 }}}, { 0x2c6a, {1, {0x2c69 }}}, { 0x2c6c, {1, {0x2c6b }}}, { 0x2c73, {1, {0x2c72 }}}, { 0x2c76, {1, {0x2c75 }}}, { 0x2c81, {1, {0x2c80 }}}, { 0x2c83, {1, {0x2c82 }}}, { 0x2c85, {1, {0x2c84 }}}, { 0x2c87, {1, {0x2c86 }}}, { 0x2c89, {1, {0x2c88 }}}, { 0x2c8b, {1, {0x2c8a }}}, { 0x2c8d, {1, {0x2c8c }}}, { 0x2c8f, {1, {0x2c8e }}}, { 0x2c91, {1, {0x2c90 }}}, { 0x2c93, {1, {0x2c92 }}}, { 0x2c95, {1, {0x2c94 }}}, { 0x2c97, {1, {0x2c96 }}}, { 0x2c99, {1, {0x2c98 }}}, { 0x2c9b, {1, {0x2c9a }}}, { 0x2c9d, {1, {0x2c9c }}}, { 0x2c9f, {1, {0x2c9e }}}, { 0x2ca1, {1, {0x2ca0 }}}, { 0x2ca3, {1, {0x2ca2 }}}, { 0x2ca5, {1, {0x2ca4 }}}, { 0x2ca7, {1, {0x2ca6 }}}, { 0x2ca9, {1, {0x2ca8 }}}, { 0x2cab, {1, {0x2caa }}}, { 0x2cad, {1, {0x2cac }}}, { 0x2caf, {1, {0x2cae }}}, { 0x2cb1, {1, {0x2cb0 }}}, { 0x2cb3, {1, {0x2cb2 }}}, { 0x2cb5, {1, {0x2cb4 }}}, { 0x2cb7, {1, {0x2cb6 }}}, { 0x2cb9, {1, {0x2cb8 }}}, { 0x2cbb, {1, {0x2cba }}}, { 0x2cbd, {1, {0x2cbc }}}, { 0x2cbf, {1, {0x2cbe }}}, { 0x2cc1, {1, {0x2cc0 }}}, { 0x2cc3, {1, {0x2cc2 }}}, { 0x2cc5, {1, {0x2cc4 }}}, { 0x2cc7, {1, {0x2cc6 }}}, { 0x2cc9, {1, {0x2cc8 }}}, { 0x2ccb, {1, {0x2cca }}}, { 0x2ccd, {1, {0x2ccc }}}, { 0x2ccf, {1, {0x2cce }}}, { 0x2cd1, {1, {0x2cd0 }}}, { 0x2cd3, {1, {0x2cd2 }}}, { 0x2cd5, {1, {0x2cd4 }}}, { 0x2cd7, {1, {0x2cd6 }}}, { 0x2cd9, {1, {0x2cd8 }}}, { 0x2cdb, {1, {0x2cda }}}, { 0x2cdd, {1, {0x2cdc }}}, { 0x2cdf, {1, {0x2cde }}}, { 0x2ce1, {1, {0x2ce0 }}}, { 0x2ce3, {1, {0x2ce2 }}}, { 0x2cec, {1, {0x2ceb }}}, { 0x2cee, {1, {0x2ced }}}, { 0x2cf3, {1, {0x2cf2 }}}, { 0x2d00, {1, {0x10a0 }}}, { 0x2d01, {1, {0x10a1 }}}, { 0x2d02, {1, {0x10a2 }}}, { 0x2d03, {1, {0x10a3 }}}, { 0x2d04, {1, {0x10a4 }}}, { 0x2d05, {1, {0x10a5 }}}, { 0x2d06, {1, {0x10a6 }}}, { 0x2d07, {1, {0x10a7 }}}, { 0x2d08, {1, {0x10a8 }}}, { 0x2d09, {1, {0x10a9 }}}, { 0x2d0a, {1, {0x10aa }}}, { 0x2d0b, {1, {0x10ab }}}, { 0x2d0c, {1, {0x10ac }}}, { 0x2d0d, {1, {0x10ad }}}, { 0x2d0e, {1, {0x10ae }}}, { 0x2d0f, {1, {0x10af }}}, { 0x2d10, {1, {0x10b0 }}}, { 0x2d11, {1, {0x10b1 }}}, { 0x2d12, {1, {0x10b2 }}}, { 0x2d13, {1, {0x10b3 }}}, { 0x2d14, {1, {0x10b4 }}}, { 0x2d15, {1, {0x10b5 }}}, { 0x2d16, {1, {0x10b6 }}}, { 0x2d17, {1, {0x10b7 }}}, { 0x2d18, {1, {0x10b8 }}}, { 0x2d19, {1, {0x10b9 }}}, { 0x2d1a, {1, {0x10ba }}}, { 0x2d1b, {1, {0x10bb }}}, { 0x2d1c, {1, {0x10bc }}}, { 0x2d1d, {1, {0x10bd }}}, { 0x2d1e, {1, {0x10be }}}, { 0x2d1f, {1, {0x10bf }}}, { 0x2d20, {1, {0x10c0 }}}, { 0x2d21, {1, {0x10c1 }}}, { 0x2d22, {1, {0x10c2 }}}, { 0x2d23, {1, {0x10c3 }}}, { 0x2d24, {1, {0x10c4 }}}, { 0x2d25, {1, {0x10c5 }}}, { 0x2d27, {1, {0x10c7 }}}, { 0x2d2d, {1, {0x10cd }}}, { 0xa641, {1, {0xa640 }}}, { 0xa643, {1, {0xa642 }}}, { 0xa645, {1, {0xa644 }}}, { 0xa647, {1, {0xa646 }}}, { 0xa649, {1, {0xa648 }}}, { 0xa64b, {1, {0xa64a }}}, { 0xa64d, {1, {0xa64c }}}, { 0xa64f, {1, {0xa64e }}}, { 0xa651, {1, {0xa650 }}}, { 0xa653, {1, {0xa652 }}}, { 0xa655, {1, {0xa654 }}}, { 0xa657, {1, {0xa656 }}}, { 0xa659, {1, {0xa658 }}}, { 0xa65b, {1, {0xa65a }}}, { 0xa65d, {1, {0xa65c }}}, { 0xa65f, {1, {0xa65e }}}, { 0xa661, {1, {0xa660 }}}, { 0xa663, {1, {0xa662 }}}, { 0xa665, {1, {0xa664 }}}, { 0xa667, {1, {0xa666 }}}, { 0xa669, {1, {0xa668 }}}, { 0xa66b, {1, {0xa66a }}}, { 0xa66d, {1, {0xa66c }}}, { 0xa681, {1, {0xa680 }}}, { 0xa683, {1, {0xa682 }}}, { 0xa685, {1, {0xa684 }}}, { 0xa687, {1, {0xa686 }}}, { 0xa689, {1, {0xa688 }}}, { 0xa68b, {1, {0xa68a }}}, { 0xa68d, {1, {0xa68c }}}, { 0xa68f, {1, {0xa68e }}}, { 0xa691, {1, {0xa690 }}}, { 0xa693, {1, {0xa692 }}}, { 0xa695, {1, {0xa694 }}}, { 0xa697, {1, {0xa696 }}}, { 0xa723, {1, {0xa722 }}}, { 0xa725, {1, {0xa724 }}}, { 0xa727, {1, {0xa726 }}}, { 0xa729, {1, {0xa728 }}}, { 0xa72b, {1, {0xa72a }}}, { 0xa72d, {1, {0xa72c }}}, { 0xa72f, {1, {0xa72e }}}, { 0xa733, {1, {0xa732 }}}, { 0xa735, {1, {0xa734 }}}, { 0xa737, {1, {0xa736 }}}, { 0xa739, {1, {0xa738 }}}, { 0xa73b, {1, {0xa73a }}}, { 0xa73d, {1, {0xa73c }}}, { 0xa73f, {1, {0xa73e }}}, { 0xa741, {1, {0xa740 }}}, { 0xa743, {1, {0xa742 }}}, { 0xa745, {1, {0xa744 }}}, { 0xa747, {1, {0xa746 }}}, { 0xa749, {1, {0xa748 }}}, { 0xa74b, {1, {0xa74a }}}, { 0xa74d, {1, {0xa74c }}}, { 0xa74f, {1, {0xa74e }}}, { 0xa751, {1, {0xa750 }}}, { 0xa753, {1, {0xa752 }}}, { 0xa755, {1, {0xa754 }}}, { 0xa757, {1, {0xa756 }}}, { 0xa759, {1, {0xa758 }}}, { 0xa75b, {1, {0xa75a }}}, { 0xa75d, {1, {0xa75c }}}, { 0xa75f, {1, {0xa75e }}}, { 0xa761, {1, {0xa760 }}}, { 0xa763, {1, {0xa762 }}}, { 0xa765, {1, {0xa764 }}}, { 0xa767, {1, {0xa766 }}}, { 0xa769, {1, {0xa768 }}}, { 0xa76b, {1, {0xa76a }}}, { 0xa76d, {1, {0xa76c }}}, { 0xa76f, {1, {0xa76e }}}, { 0xa77a, {1, {0xa779 }}}, { 0xa77c, {1, {0xa77b }}}, { 0xa77f, {1, {0xa77e }}}, { 0xa781, {1, {0xa780 }}}, { 0xa783, {1, {0xa782 }}}, { 0xa785, {1, {0xa784 }}}, { 0xa787, {1, {0xa786 }}}, { 0xa78c, {1, {0xa78b }}}, { 0xa791, {1, {0xa790 }}}, { 0xa793, {1, {0xa792 }}}, { 0xa7a1, {1, {0xa7a0 }}}, { 0xa7a3, {1, {0xa7a2 }}}, { 0xa7a5, {1, {0xa7a4 }}}, { 0xa7a7, {1, {0xa7a6 }}}, { 0xa7a9, {1, {0xa7a8 }}}, { 0xff41, {1, {0xff21 }}}, { 0xff42, {1, {0xff22 }}}, { 0xff43, {1, {0xff23 }}}, { 0xff44, {1, {0xff24 }}}, { 0xff45, {1, {0xff25 }}}, { 0xff46, {1, {0xff26 }}}, { 0xff47, {1, {0xff27 }}}, { 0xff48, {1, {0xff28 }}}, { 0xff49, {1, {0xff29 }}}, { 0xff4a, {1, {0xff2a }}}, { 0xff4b, {1, {0xff2b }}}, { 0xff4c, {1, {0xff2c }}}, { 0xff4d, {1, {0xff2d }}}, { 0xff4e, {1, {0xff2e }}}, { 0xff4f, {1, {0xff2f }}}, { 0xff50, {1, {0xff30 }}}, { 0xff51, {1, {0xff31 }}}, { 0xff52, {1, {0xff32 }}}, { 0xff53, {1, {0xff33 }}}, { 0xff54, {1, {0xff34 }}}, { 0xff55, {1, {0xff35 }}}, { 0xff56, {1, {0xff36 }}}, { 0xff57, {1, {0xff37 }}}, { 0xff58, {1, {0xff38 }}}, { 0xff59, {1, {0xff39 }}}, { 0xff5a, {1, {0xff3a }}}, { 0x10428, {1, {0x10400 }}}, { 0x10429, {1, {0x10401 }}}, { 0x1042a, {1, {0x10402 }}}, { 0x1042b, {1, {0x10403 }}}, { 0x1042c, {1, {0x10404 }}}, { 0x1042d, {1, {0x10405 }}}, { 0x1042e, {1, {0x10406 }}}, { 0x1042f, {1, {0x10407 }}}, { 0x10430, {1, {0x10408 }}}, { 0x10431, {1, {0x10409 }}}, { 0x10432, {1, {0x1040a }}}, { 0x10433, {1, {0x1040b }}}, { 0x10434, {1, {0x1040c }}}, { 0x10435, {1, {0x1040d }}}, { 0x10436, {1, {0x1040e }}}, { 0x10437, {1, {0x1040f }}}, { 0x10438, {1, {0x10410 }}}, { 0x10439, {1, {0x10411 }}}, { 0x1043a, {1, {0x10412 }}}, { 0x1043b, {1, {0x10413 }}}, { 0x1043c, {1, {0x10414 }}}, { 0x1043d, {1, {0x10415 }}}, { 0x1043e, {1, {0x10416 }}}, { 0x1043f, {1, {0x10417 }}}, { 0x10440, {1, {0x10418 }}}, { 0x10441, {1, {0x10419 }}}, { 0x10442, {1, {0x1041a }}}, { 0x10443, {1, {0x1041b }}}, { 0x10444, {1, {0x1041c }}}, { 0x10445, {1, {0x1041d }}}, { 0x10446, {1, {0x1041e }}}, { 0x10447, {1, {0x1041f }}}, { 0x10448, {1, {0x10420 }}}, { 0x10449, {1, {0x10421 }}}, { 0x1044a, {1, {0x10422 }}}, { 0x1044b, {1, {0x10423 }}}, { 0x1044c, {1, {0x10424 }}}, { 0x1044d, {1, {0x10425 }}}, { 0x1044e, {1, {0x10426 }}}, { 0x1044f, {1, {0x10427 }}}, }; static const CaseUnfold_11_Type CaseUnfold_11_Locale[] = { { 0x0069, {1, {0x0049 }}}, }; static const CaseUnfold_12_Type CaseUnfold_12[] = { { {0x0061, 0x02be}, {1, {0x1e9a }}}, { {0x0066, 0x0066}, {1, {0xfb00 }}}, { {0x0066, 0x0069}, {1, {0xfb01 }}}, { {0x0066, 0x006c}, {1, {0xfb02 }}}, { {0x0068, 0x0331}, {1, {0x1e96 }}}, { {0x006a, 0x030c}, {1, {0x01f0 }}}, { {0x0073, 0x0073}, {2, {0x00df, 0x1e9e }}}, { {0x0073, 0x0074}, {2, {0xfb05, 0xfb06 }}}, { {0x0074, 0x0308}, {1, {0x1e97 }}}, { {0x0077, 0x030a}, {1, {0x1e98 }}}, { {0x0079, 0x030a}, {1, {0x1e99 }}}, { {0x02bc, 0x006e}, {1, {0x0149 }}}, { {0x03ac, 0x03b9}, {1, {0x1fb4 }}}, { {0x03ae, 0x03b9}, {1, {0x1fc4 }}}, { {0x03b1, 0x0342}, {1, {0x1fb6 }}}, { {0x03b1, 0x03b9}, {2, {0x1fb3, 0x1fbc }}}, { {0x03b7, 0x0342}, {1, {0x1fc6 }}}, { {0x03b7, 0x03b9}, {2, {0x1fc3, 0x1fcc }}}, { {0x03b9, 0x0342}, {1, {0x1fd6 }}}, { {0x03c1, 0x0313}, {1, {0x1fe4 }}}, { {0x03c5, 0x0313}, {1, {0x1f50 }}}, { {0x03c5, 0x0342}, {1, {0x1fe6 }}}, { {0x03c9, 0x0342}, {1, {0x1ff6 }}}, { {0x03c9, 0x03b9}, {2, {0x1ff3, 0x1ffc }}}, { {0x03ce, 0x03b9}, {1, {0x1ff4 }}}, { {0x0565, 0x0582}, {1, {0x0587 }}}, { {0x0574, 0x0565}, {1, {0xfb14 }}}, { {0x0574, 0x056b}, {1, {0xfb15 }}}, { {0x0574, 0x056d}, {1, {0xfb17 }}}, { {0x0574, 0x0576}, {1, {0xfb13 }}}, { {0x057e, 0x0576}, {1, {0xfb16 }}}, { {0x1f00, 0x03b9}, {2, {0x1f80, 0x1f88 }}}, { {0x1f01, 0x03b9}, {2, {0x1f81, 0x1f89 }}}, { {0x1f02, 0x03b9}, {2, {0x1f82, 0x1f8a }}}, { {0x1f03, 0x03b9}, {2, {0x1f83, 0x1f8b }}}, { {0x1f04, 0x03b9}, {2, {0x1f84, 0x1f8c }}}, { {0x1f05, 0x03b9}, {2, {0x1f85, 0x1f8d }}}, { {0x1f06, 0x03b9}, {2, {0x1f86, 0x1f8e }}}, { {0x1f07, 0x03b9}, {2, {0x1f87, 0x1f8f }}}, { {0x1f20, 0x03b9}, {2, {0x1f90, 0x1f98 }}}, { {0x1f21, 0x03b9}, {2, {0x1f91, 0x1f99 }}}, { {0x1f22, 0x03b9}, {2, {0x1f92, 0x1f9a }}}, { {0x1f23, 0x03b9}, {2, {0x1f93, 0x1f9b }}}, { {0x1f24, 0x03b9}, {2, {0x1f94, 0x1f9c }}}, { {0x1f25, 0x03b9}, {2, {0x1f95, 0x1f9d }}}, { {0x1f26, 0x03b9}, {2, {0x1f96, 0x1f9e }}}, { {0x1f27, 0x03b9}, {2, {0x1f97, 0x1f9f }}}, { {0x1f60, 0x03b9}, {2, {0x1fa0, 0x1fa8 }}}, { {0x1f61, 0x03b9}, {2, {0x1fa1, 0x1fa9 }}}, { {0x1f62, 0x03b9}, {2, {0x1fa2, 0x1faa }}}, { {0x1f63, 0x03b9}, {2, {0x1fa3, 0x1fab }}}, { {0x1f64, 0x03b9}, {2, {0x1fa4, 0x1fac }}}, { {0x1f65, 0x03b9}, {2, {0x1fa5, 0x1fad }}}, { {0x1f66, 0x03b9}, {2, {0x1fa6, 0x1fae }}}, { {0x1f67, 0x03b9}, {2, {0x1fa7, 0x1faf }}}, { {0x1f70, 0x03b9}, {1, {0x1fb2 }}}, { {0x1f74, 0x03b9}, {1, {0x1fc2 }}}, { {0x1f7c, 0x03b9}, {1, {0x1ff2 }}}, }; static const CaseUnfold_12_Type CaseUnfold_12_Locale[] = { { {0x0069, 0x0307}, {1, {0x0130 }}}, }; static const CaseUnfold_13_Type CaseUnfold_13[] = { { {0x0066, 0x0066, 0x0069}, {1, {0xfb03 }}}, { {0x0066, 0x0066, 0x006c}, {1, {0xfb04 }}}, { {0x03b1, 0x0342, 0x03b9}, {1, {0x1fb7 }}}, { {0x03b7, 0x0342, 0x03b9}, {1, {0x1fc7 }}}, { {0x03b9, 0x0308, 0x0300}, {1, {0x1fd2 }}}, { {0x03b9, 0x0308, 0x0301}, {2, {0x0390, 0x1fd3 }}}, { {0x03b9, 0x0308, 0x0342}, {1, {0x1fd7 }}}, { {0x03c5, 0x0308, 0x0300}, {1, {0x1fe2 }}}, { {0x03c5, 0x0308, 0x0301}, {2, {0x03b0, 0x1fe3 }}}, { {0x03c5, 0x0308, 0x0342}, {1, {0x1fe7 }}}, { {0x03c5, 0x0313, 0x0300}, {1, {0x1f52 }}}, { {0x03c5, 0x0313, 0x0301}, {1, {0x1f54 }}}, { {0x03c5, 0x0313, 0x0342}, {1, {0x1f56 }}}, { {0x03c9, 0x0342, 0x03b9}, {1, {0x1ff7 }}}, }; #define FOLD_TABLE_SIZE 1357 #define UNFOLD1_TABLE_SIZE 1207 #define UNFOLD2_TABLE_SIZE 88 #define UNFOLD3_TABLE_SIZE 23 ================================================ FILE: src/Onigmo/enc/unicode/name2ctype.h ================================================ /* C code produced by gperf version 3.0.3 */ /* Command-line: gperf -7 -c -j1 -i1 -t -C -P -T -H uniname2ctype_hash -Q uniname2ctype_pool -N uniname2ctype_p */ #ifndef USE_UNICODE_PROPERTIES /* Computed positions: -k'1,3' */ #else /* USE_UNICODE_PROPERTIES */ /* Computed positions: -k'1-3,5-6,12,16,$' */ #endif /* USE_UNICODE_PROPERTIES */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #define long size_t /* 'NEWLINE': [[:NEWLINE:]] */ static const OnigCodePoint CR_NEWLINE[] = { 1, 0x000a, 0x000a, }; /* CR_NEWLINE */ /* 'Alpha': [[:Alpha:]] */ static const OnigCodePoint CR_Alpha[] = { 540, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0345, 0x0345, 0x0370, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x05b0, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0610, 0x061a, 0x0620, 0x0657, 0x0659, 0x065f, 0x066e, 0x06d3, 0x06d5, 0x06dc, 0x06e1, 0x06e8, 0x06ed, 0x06ef, 0x06fa, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x073f, 0x074d, 0x07b1, 0x07ca, 0x07ea, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x0817, 0x081a, 0x082c, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08e9, 0x08f0, 0x08fe, 0x0900, 0x093b, 0x093d, 0x094c, 0x094e, 0x0950, 0x0955, 0x0963, 0x0971, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09ce, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09f0, 0x09f1, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4c, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a70, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acc, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b71, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4c, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccc, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d4e, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d7a, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e01, 0x0e3a, 0x0e40, 0x0e46, 0x0e4d, 0x0e4d, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ecd, 0x0ecd, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f81, 0x0f88, 0x0f97, 0x0f99, 0x0fbc, 0x1000, 0x1036, 0x1038, 0x1038, 0x103b, 0x103f, 0x1050, 0x1062, 0x1065, 0x1068, 0x106e, 0x1086, 0x108e, 0x108e, 0x109c, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x135f, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1713, 0x1720, 0x1733, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17b3, 0x17b6, 0x17c8, 0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x1938, 0x1950, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a61, 0x1a74, 0x1aa7, 0x1aa7, 0x1b00, 0x1b33, 0x1b35, 0x1b43, 0x1b45, 0x1b4b, 0x1b80, 0x1ba9, 0x1bac, 0x1baf, 0x1bba, 0x1be5, 0x1be7, 0x1bf1, 0x1c00, 0x1c35, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, 0x1ce9, 0x1cec, 0x1cee, 0x1cf3, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x24b6, 0x24e9, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff, 0x2e2f, 0x2e2f, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa640, 0xa66e, 0xa674, 0xa67b, 0xa67f, 0xa697, 0xa69f, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c3, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa90a, 0xa92a, 0xa930, 0xa952, 0xa960, 0xa97c, 0xa980, 0xa9b2, 0xa9b4, 0xa9bf, 0xa9cf, 0xa9cf, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaabe, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf5, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabea, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11000, 0x11045, 0x11082, 0x110b8, 0x110d0, 0x110e8, 0x11100, 0x11132, 0x11180, 0x111bf, 0x111c1, 0x111c4, 0x11680, 0x116b5, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Alpha */ /* 'Blank': [[:Blank:]] */ static const OnigCodePoint CR_Blank[] = { 9, 0x0009, 0x0009, 0x0020, 0x0020, 0x00a0, 0x00a0, 0x1680, 0x1680, 0x180e, 0x180e, 0x2000, 0x200a, 0x202f, 0x202f, 0x205f, 0x205f, 0x3000, 0x3000, }; /* CR_Blank */ /* 'Cntrl': [[:Cntrl:]] */ static const OnigCodePoint CR_Cntrl[] = { 2, 0x0000, 0x001f, 0x007f, 0x009f, }; /* CR_Cntrl */ /* 'Digit': [[:Digit:]] */ static const OnigCodePoint CR_Digit[] = { 42, 0x0030, 0x0039, 0x0660, 0x0669, 0x06f0, 0x06f9, 0x07c0, 0x07c9, 0x0966, 0x096f, 0x09e6, 0x09ef, 0x0a66, 0x0a6f, 0x0ae6, 0x0aef, 0x0b66, 0x0b6f, 0x0be6, 0x0bef, 0x0c66, 0x0c6f, 0x0ce6, 0x0cef, 0x0d66, 0x0d6f, 0x0e50, 0x0e59, 0x0ed0, 0x0ed9, 0x0f20, 0x0f29, 0x1040, 0x1049, 0x1090, 0x1099, 0x17e0, 0x17e9, 0x1810, 0x1819, 0x1946, 0x194f, 0x19d0, 0x19d9, 0x1a80, 0x1a89, 0x1a90, 0x1a99, 0x1b50, 0x1b59, 0x1bb0, 0x1bb9, 0x1c40, 0x1c49, 0x1c50, 0x1c59, 0xa620, 0xa629, 0xa8d0, 0xa8d9, 0xa900, 0xa909, 0xa9d0, 0xa9d9, 0xaa50, 0xaa59, 0xabf0, 0xabf9, 0xff10, 0xff19, 0x104a0, 0x104a9, 0x11066, 0x1106f, 0x110f0, 0x110f9, 0x11136, 0x1113f, 0x111d0, 0x111d9, 0x116c0, 0x116c9, 0x1d7ce, 0x1d7ff, }; /* CR_Digit */ /* 'Graph': [[:Graph:]] */ static const OnigCodePoint CR_Graph[] = { 544, 0x0021, 0x007e, 0x00a1, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0604, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x167f, 0x1681, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180d, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x200b, 0x2027, 0x202a, 0x202e, 0x2030, 0x205e, 0x2060, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3001, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa697, 0xa69f, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xe000, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xfffd, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, 0x11180, 0x111c8, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xf0000, 0xffffd, 0x100000, 0x10fffd, }; /* CR_Graph */ /* 'Lower': [[:Lower:]] */ static const OnigCodePoint CR_Lower[] = { 618, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00df, 0x00f6, 0x00f8, 0x00ff, 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, 0x0131, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x0180, 0x0183, 0x0183, 0x0185, 0x0185, 0x0188, 0x0188, 0x018c, 0x018d, 0x0192, 0x0192, 0x0195, 0x0195, 0x0199, 0x019b, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x01a8, 0x01a8, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x01b0, 0x01b0, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x01b9, 0x01ba, 0x01bd, 0x01bf, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dd, 0x01df, 0x01df, 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01f0, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff, 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, 0x0221, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, 0x0231, 0x0231, 0x0233, 0x0239, 0x023c, 0x023c, 0x023f, 0x0240, 0x0242, 0x0242, 0x0247, 0x0247, 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x0293, 0x0295, 0x02b8, 0x02c0, 0x02c1, 0x02e0, 0x02e4, 0x0345, 0x0345, 0x0371, 0x0371, 0x0373, 0x0373, 0x0377, 0x0377, 0x037a, 0x037d, 0x0390, 0x0390, 0x03ac, 0x03ce, 0x03d0, 0x03d1, 0x03d5, 0x03d7, 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03f3, 0x03f5, 0x03f5, 0x03f8, 0x03f8, 0x03fb, 0x03fc, 0x0430, 0x045f, 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, 0x0481, 0x0481, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04cf, 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff, 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, 0x0561, 0x0587, 0x1d00, 0x1dbf, 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e9d, 0x1e9f, 0x1e9f, 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45, 0x1f50, 0x1f57, 0x1f60, 0x1f67, 0x1f70, 0x1f7d, 0x1f80, 0x1f87, 0x1f90, 0x1f97, 0x1fa0, 0x1fa7, 0x1fb0, 0x1fb4, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fc7, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fd7, 0x1fe0, 0x1fe7, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ff7, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x210a, 0x210a, 0x210e, 0x210f, 0x2113, 0x2113, 0x212f, 0x212f, 0x2134, 0x2134, 0x2139, 0x2139, 0x213c, 0x213d, 0x2146, 0x2149, 0x214e, 0x214e, 0x2170, 0x217f, 0x2184, 0x2184, 0x24d0, 0x24e9, 0x2c30, 0x2c5e, 0x2c61, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x2c71, 0x2c71, 0x2c73, 0x2c74, 0x2c76, 0x2c7d, 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce4, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cf3, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa731, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa778, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0xa77f, 0xa77f, 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, 0xa78c, 0xa78c, 0xa78e, 0xa78e, 0xa791, 0xa791, 0xa793, 0xa793, 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, 0xa7a9, 0xa7a9, 0xa7f8, 0xa7fa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff41, 0xff5a, 0x10428, 0x1044f, 0x1d41a, 0x1d433, 0x1d44e, 0x1d454, 0x1d456, 0x1d467, 0x1d482, 0x1d49b, 0x1d4b6, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d4cf, 0x1d4ea, 0x1d503, 0x1d51e, 0x1d537, 0x1d552, 0x1d56b, 0x1d586, 0x1d59f, 0x1d5ba, 0x1d5d3, 0x1d5ee, 0x1d607, 0x1d622, 0x1d63b, 0x1d656, 0x1d66f, 0x1d68a, 0x1d6a5, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6e1, 0x1d6fc, 0x1d714, 0x1d716, 0x1d71b, 0x1d736, 0x1d74e, 0x1d750, 0x1d755, 0x1d770, 0x1d788, 0x1d78a, 0x1d78f, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7c9, 0x1d7cb, 0x1d7cb, }; /* CR_Lower */ /* 'Print': [[:Print:]] */ static const OnigCodePoint CR_Print[] = { 541, 0x0020, 0x007e, 0x00a0, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0604, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2027, 0x202a, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa697, 0xa69f, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xe000, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xfffd, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, 0x11180, 0x111c8, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xf0000, 0xffffd, 0x100000, 0x10fffd, }; /* CR_Print */ /* 'Punct': [[:Punct:]] */ static const OnigCodePoint CR_Punct[] = { 140, 0x0021, 0x0023, 0x0025, 0x002a, 0x002c, 0x002f, 0x003a, 0x003b, 0x003f, 0x0040, 0x005b, 0x005d, 0x005f, 0x005f, 0x007b, 0x007b, 0x007d, 0x007d, 0x00a1, 0x00a1, 0x00a7, 0x00a7, 0x00ab, 0x00ab, 0x00b6, 0x00b7, 0x00bb, 0x00bb, 0x00bf, 0x00bf, 0x037e, 0x037e, 0x0387, 0x0387, 0x055a, 0x055f, 0x0589, 0x058a, 0x05be, 0x05be, 0x05c0, 0x05c0, 0x05c3, 0x05c3, 0x05c6, 0x05c6, 0x05f3, 0x05f4, 0x0609, 0x060a, 0x060c, 0x060d, 0x061b, 0x061b, 0x061e, 0x061f, 0x066a, 0x066d, 0x06d4, 0x06d4, 0x0700, 0x070d, 0x07f7, 0x07f9, 0x0830, 0x083e, 0x085e, 0x085e, 0x0964, 0x0965, 0x0970, 0x0970, 0x0af0, 0x0af0, 0x0df4, 0x0df4, 0x0e4f, 0x0e4f, 0x0e5a, 0x0e5b, 0x0f04, 0x0f12, 0x0f14, 0x0f14, 0x0f3a, 0x0f3d, 0x0f85, 0x0f85, 0x0fd0, 0x0fd4, 0x0fd9, 0x0fda, 0x104a, 0x104f, 0x10fb, 0x10fb, 0x1360, 0x1368, 0x1400, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x16eb, 0x16ed, 0x1735, 0x1736, 0x17d4, 0x17d6, 0x17d8, 0x17da, 0x1800, 0x180a, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa6, 0x1aa8, 0x1aad, 0x1b5a, 0x1b60, 0x1bfc, 0x1bff, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd3, 0x1cd3, 0x2010, 0x2027, 0x2030, 0x2043, 0x2045, 0x2051, 0x2053, 0x205e, 0x207d, 0x207e, 0x208d, 0x208e, 0x2329, 0x232a, 0x2768, 0x2775, 0x27c5, 0x27c6, 0x27e6, 0x27ef, 0x2983, 0x2998, 0x29d8, 0x29db, 0x29fc, 0x29fd, 0x2cf9, 0x2cfc, 0x2cfe, 0x2cff, 0x2d70, 0x2d70, 0x2e00, 0x2e2e, 0x2e30, 0x2e3b, 0x3001, 0x3003, 0x3008, 0x3011, 0x3014, 0x301f, 0x3030, 0x3030, 0x303d, 0x303d, 0x30a0, 0x30a0, 0x30fb, 0x30fb, 0xa4fe, 0xa4ff, 0xa60d, 0xa60f, 0xa673, 0xa673, 0xa67e, 0xa67e, 0xa6f2, 0xa6f7, 0xa874, 0xa877, 0xa8ce, 0xa8cf, 0xa8f8, 0xa8fa, 0xa92e, 0xa92f, 0xa95f, 0xa95f, 0xa9c1, 0xa9cd, 0xa9de, 0xa9df, 0xaa5c, 0xaa5f, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, 0xfd3e, 0xfd3f, 0xfe10, 0xfe19, 0xfe30, 0xfe52, 0xfe54, 0xfe61, 0xfe63, 0xfe63, 0xfe68, 0xfe68, 0xfe6a, 0xfe6b, 0xff01, 0xff03, 0xff05, 0xff0a, 0xff0c, 0xff0f, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3b, 0xff3d, 0xff3f, 0xff3f, 0xff5b, 0xff5b, 0xff5d, 0xff5d, 0xff5f, 0xff65, 0x10100, 0x10102, 0x1039f, 0x1039f, 0x103d0, 0x103d0, 0x10857, 0x10857, 0x1091f, 0x1091f, 0x1093f, 0x1093f, 0x10a50, 0x10a58, 0x10a7f, 0x10a7f, 0x10b39, 0x10b3f, 0x11047, 0x1104d, 0x110bb, 0x110bc, 0x110be, 0x110c1, 0x11140, 0x11143, 0x111c5, 0x111c8, 0x12470, 0x12473, }; /* CR_Punct */ /* 'Space': [[:Space:]] */ static const OnigCodePoint CR_Space[] = { 11, 0x0009, 0x000d, 0x0020, 0x0020, 0x0085, 0x0085, 0x00a0, 0x00a0, 0x1680, 0x1680, 0x180e, 0x180e, 0x2000, 0x200a, 0x2028, 0x2029, 0x202f, 0x202f, 0x205f, 0x205f, 0x3000, 0x3000, }; /* CR_Space */ /* 'Upper': [[:Upper:]] */ static const OnigCodePoint CR_Upper[] = { 610, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, 0x0130, 0x0130, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, 0x0147, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, 0x0178, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x0181, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0189, 0x018b, 0x018e, 0x0191, 0x0193, 0x0194, 0x0196, 0x0198, 0x019c, 0x019d, 0x019f, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, 0x01a9, 0x01a9, 0x01ac, 0x01ac, 0x01ae, 0x01af, 0x01b1, 0x01b3, 0x01b5, 0x01b5, 0x01b7, 0x01b8, 0x01bc, 0x01bc, 0x01c4, 0x01c4, 0x01c7, 0x01c7, 0x01ca, 0x01ca, 0x01cd, 0x01cd, 0x01cf, 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x01de, 0x01de, 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, 0x01f1, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, 0x0220, 0x0220, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, 0x0230, 0x0230, 0x0232, 0x0232, 0x023a, 0x023b, 0x023d, 0x023e, 0x0241, 0x0241, 0x0243, 0x0246, 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, 0x0370, 0x0370, 0x0372, 0x0372, 0x0376, 0x0376, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x038f, 0x0391, 0x03a1, 0x03a3, 0x03ab, 0x03cf, 0x03cf, 0x03d2, 0x03d4, 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, 0x03f4, 0x03f4, 0x03f7, 0x03f7, 0x03f9, 0x03fa, 0x03fd, 0x042f, 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, 0x0480, 0x0480, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, 0x04c0, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0514, 0x0516, 0x0516, 0x0518, 0x0518, 0x051a, 0x051a, 0x051c, 0x051c, 0x051e, 0x051e, 0x0520, 0x0520, 0x0522, 0x0522, 0x0524, 0x0524, 0x0526, 0x0526, 0x0531, 0x0556, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1e00, 0x1e00, 0x1e02, 0x1e02, 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, 0x1e94, 0x1e94, 0x1e9e, 0x1e9e, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efa, 0x1efc, 0x1efc, 0x1efe, 0x1efe, 0x1f08, 0x1f0f, 0x1f18, 0x1f1d, 0x1f28, 0x1f2f, 0x1f38, 0x1f3f, 0x1f48, 0x1f4d, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f5f, 0x1f68, 0x1f6f, 0x1fb8, 0x1fbb, 0x1fc8, 0x1fcb, 0x1fd8, 0x1fdb, 0x1fe8, 0x1fec, 0x1ff8, 0x1ffb, 0x2102, 0x2102, 0x2107, 0x2107, 0x210b, 0x210d, 0x2110, 0x2112, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x2130, 0x2133, 0x213e, 0x213f, 0x2145, 0x2145, 0x2160, 0x216f, 0x2183, 0x2183, 0x24b6, 0x24cf, 0x2c00, 0x2c2e, 0x2c60, 0x2c60, 0x2c62, 0x2c64, 0x2c67, 0x2c67, 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c70, 0x2c72, 0x2c72, 0x2c75, 0x2c75, 0x2c7e, 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, 0x2ce0, 0x2ce2, 0x2ce2, 0x2ceb, 0x2ceb, 0x2ced, 0x2ced, 0x2cf2, 0x2cf2, 0xa640, 0xa640, 0xa642, 0xa642, 0xa644, 0xa644, 0xa646, 0xa646, 0xa648, 0xa648, 0xa64a, 0xa64a, 0xa64c, 0xa64c, 0xa64e, 0xa64e, 0xa650, 0xa650, 0xa652, 0xa652, 0xa654, 0xa654, 0xa656, 0xa656, 0xa658, 0xa658, 0xa65a, 0xa65a, 0xa65c, 0xa65c, 0xa65e, 0xa65e, 0xa660, 0xa660, 0xa662, 0xa662, 0xa664, 0xa664, 0xa666, 0xa666, 0xa668, 0xa668, 0xa66a, 0xa66a, 0xa66c, 0xa66c, 0xa680, 0xa680, 0xa682, 0xa682, 0xa684, 0xa684, 0xa686, 0xa686, 0xa688, 0xa688, 0xa68a, 0xa68a, 0xa68c, 0xa68c, 0xa68e, 0xa68e, 0xa690, 0xa690, 0xa692, 0xa692, 0xa694, 0xa694, 0xa696, 0xa696, 0xa722, 0xa722, 0xa724, 0xa724, 0xa726, 0xa726, 0xa728, 0xa728, 0xa72a, 0xa72a, 0xa72c, 0xa72c, 0xa72e, 0xa72e, 0xa732, 0xa732, 0xa734, 0xa734, 0xa736, 0xa736, 0xa738, 0xa738, 0xa73a, 0xa73a, 0xa73c, 0xa73c, 0xa73e, 0xa73e, 0xa740, 0xa740, 0xa742, 0xa742, 0xa744, 0xa744, 0xa746, 0xa746, 0xa748, 0xa748, 0xa74a, 0xa74a, 0xa74c, 0xa74c, 0xa74e, 0xa74e, 0xa750, 0xa750, 0xa752, 0xa752, 0xa754, 0xa754, 0xa756, 0xa756, 0xa758, 0xa758, 0xa75a, 0xa75a, 0xa75c, 0xa75c, 0xa75e, 0xa75e, 0xa760, 0xa760, 0xa762, 0xa762, 0xa764, 0xa764, 0xa766, 0xa766, 0xa768, 0xa768, 0xa76a, 0xa76a, 0xa76c, 0xa76c, 0xa76e, 0xa76e, 0xa779, 0xa779, 0xa77b, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa780, 0xa782, 0xa782, 0xa784, 0xa784, 0xa786, 0xa786, 0xa78b, 0xa78b, 0xa78d, 0xa78d, 0xa790, 0xa790, 0xa792, 0xa792, 0xa7a0, 0xa7a0, 0xa7a2, 0xa7a2, 0xa7a4, 0xa7a4, 0xa7a6, 0xa7a6, 0xa7a8, 0xa7a8, 0xa7aa, 0xa7aa, 0xff21, 0xff3a, 0x10400, 0x10427, 0x1d400, 0x1d419, 0x1d434, 0x1d44d, 0x1d468, 0x1d481, 0x1d49c, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b5, 0x1d4d0, 0x1d4e9, 0x1d504, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d538, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d56c, 0x1d585, 0x1d5a0, 0x1d5b9, 0x1d5d4, 0x1d5ed, 0x1d608, 0x1d621, 0x1d63c, 0x1d655, 0x1d670, 0x1d689, 0x1d6a8, 0x1d6c0, 0x1d6e2, 0x1d6fa, 0x1d71c, 0x1d734, 0x1d756, 0x1d76e, 0x1d790, 0x1d7a8, 0x1d7ca, 0x1d7ca, }; /* CR_Upper */ /* 'XDigit': [[:XDigit:]] */ static const OnigCodePoint CR_XDigit[] = { 3, 0x0030, 0x0039, 0x0041, 0x0046, 0x0061, 0x0066, }; /* CR_XDigit */ /* 'Word': [[:Word:]] */ static const OnigCodePoint CR_Word[] = { 564, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0300, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x0483, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0610, 0x061a, 0x0620, 0x0669, 0x066e, 0x06d3, 0x06d5, 0x06dc, 0x06df, 0x06e8, 0x06ea, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x082d, 0x0840, 0x085b, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0963, 0x0966, 0x096f, 0x0971, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09f1, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, 0x0b71, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bef, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e01, 0x0e3a, 0x0e40, 0x0e4e, 0x0e50, 0x0e59, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f18, 0x0f19, 0x0f20, 0x0f29, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f3e, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f84, 0x0f86, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x1000, 0x1049, 0x1050, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x135f, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1734, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17d3, 0x17d7, 0x17d7, 0x17dc, 0x17dd, 0x17e0, 0x17e9, 0x180b, 0x180d, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1946, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19d9, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, 0x1b80, 0x1bf3, 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, 0x1cd0, 0x1cd2, 0x1cd4, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x20d0, 0x20f0, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x24b6, 0x24e9, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff, 0x2e2f, 0x2e2f, 0x3005, 0x3007, 0x3021, 0x302f, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x3099, 0x309a, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa62b, 0xa640, 0xa672, 0xa674, 0xa67d, 0xa67f, 0xa697, 0xa69f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c4, 0xa8d0, 0xa8d9, 0xa8e0, 0xa8f7, 0xa8fb, 0xa8fb, 0xa900, 0xa92d, 0xa930, 0xa953, 0xa960, 0xa97c, 0xa980, 0xa9c0, 0xa9cf, 0xa9d9, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa60, 0xaa76, 0xaa7a, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0xfe33, 0xfe34, 0xfe4d, 0xfe4f, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff10, 0xff19, 0xff21, 0xff3a, 0xff3f, 0xff3f, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x101fd, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11000, 0x11046, 0x11066, 0x1106f, 0x11080, 0x110ba, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, 0x11180, 0x111c4, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0100, 0xe01ef, }; /* CR_Word */ /* 'Alnum': [[:Alnum:]] */ static const OnigCodePoint CR_Alnum[] = { 566, 0x0030, 0x0039, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0345, 0x0345, 0x0370, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x05b0, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0610, 0x061a, 0x0620, 0x0657, 0x0659, 0x0669, 0x066e, 0x06d3, 0x06d5, 0x06dc, 0x06e1, 0x06e8, 0x06ed, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x073f, 0x074d, 0x07b1, 0x07c0, 0x07ea, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x0817, 0x081a, 0x082c, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08e9, 0x08f0, 0x08fe, 0x0900, 0x093b, 0x093d, 0x094c, 0x094e, 0x0950, 0x0955, 0x0963, 0x0966, 0x096f, 0x0971, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09ce, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09f1, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4c, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acc, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, 0x0b71, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bef, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4c, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccc, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d4e, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e01, 0x0e3a, 0x0e40, 0x0e46, 0x0e4d, 0x0e4d, 0x0e50, 0x0e59, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ecd, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f20, 0x0f29, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f81, 0x0f88, 0x0f97, 0x0f99, 0x0fbc, 0x1000, 0x1036, 0x1038, 0x1038, 0x103b, 0x1049, 0x1050, 0x1062, 0x1065, 0x1068, 0x106e, 0x1086, 0x108e, 0x108e, 0x1090, 0x1099, 0x109c, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x135f, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1713, 0x1720, 0x1733, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17b3, 0x17b6, 0x17c8, 0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x17e0, 0x17e9, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x1938, 0x1946, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19d9, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a61, 0x1a74, 0x1a80, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1b00, 0x1b33, 0x1b35, 0x1b43, 0x1b45, 0x1b4b, 0x1b50, 0x1b59, 0x1b80, 0x1ba9, 0x1bac, 0x1be5, 0x1be7, 0x1bf1, 0x1c00, 0x1c35, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, 0x1ce9, 0x1cec, 0x1cee, 0x1cf3, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x24b6, 0x24e9, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff, 0x2e2f, 0x2e2f, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa62b, 0xa640, 0xa66e, 0xa674, 0xa67b, 0xa67f, 0xa697, 0xa69f, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c3, 0xa8d0, 0xa8d9, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa900, 0xa92a, 0xa930, 0xa952, 0xa960, 0xa97c, 0xa980, 0xa9b2, 0xa9b4, 0xa9bf, 0xa9cf, 0xa9d9, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaabe, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf5, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabea, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff10, 0xff19, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11000, 0x11045, 0x11066, 0x1106f, 0x11082, 0x110b8, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11132, 0x11136, 0x1113f, 0x11180, 0x111bf, 0x111c1, 0x111c4, 0x111d0, 0x111d9, 0x11680, 0x116b5, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Alnum */ /* 'ASCII': [[:ASCII:]] */ static const OnigCodePoint CR_ASCII[] = { 1, 0x0000, 0x007f, }; /* CR_ASCII */ #ifdef USE_UNICODE_PROPERTIES /* 'Any': - */ static const OnigCodePoint CR_Any[] = { 1, 0x0000, 0x10ffff, }; /* CR_Any */ /* 'Assigned': - */ static const OnigCodePoint CR_Assigned[] = { 539, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0604, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa697, 0xa69f, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xd800, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xfffd, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, 0x11180, 0x111c8, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xf0000, 0xffffd, 0x100000, 0x10fffd, }; /* CR_Assigned */ /* 'C': Major Category */ static const OnigCodePoint CR_C[] = { 541, 0x0000, 0x001f, 0x007f, 0x009f, 0x00ad, 0x00ad, 0x0378, 0x0379, 0x037f, 0x0383, 0x038b, 0x038b, 0x038d, 0x038d, 0x03a2, 0x03a2, 0x0528, 0x0530, 0x0557, 0x0558, 0x0560, 0x0560, 0x0588, 0x0588, 0x058b, 0x058e, 0x0590, 0x0590, 0x05c8, 0x05cf, 0x05eb, 0x05ef, 0x05f5, 0x0605, 0x061c, 0x061d, 0x06dd, 0x06dd, 0x070e, 0x070f, 0x074b, 0x074c, 0x07b2, 0x07bf, 0x07fb, 0x07ff, 0x082e, 0x082f, 0x083f, 0x083f, 0x085c, 0x085d, 0x085f, 0x089f, 0x08a1, 0x08a1, 0x08ad, 0x08e3, 0x08ff, 0x08ff, 0x0978, 0x0978, 0x0980, 0x0980, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, 0x09a9, 0x09a9, 0x09b1, 0x09b1, 0x09b3, 0x09b5, 0x09ba, 0x09bb, 0x09c5, 0x09c6, 0x09c9, 0x09ca, 0x09cf, 0x09d6, 0x09d8, 0x09db, 0x09de, 0x09de, 0x09e4, 0x09e5, 0x09fc, 0x0a00, 0x0a04, 0x0a04, 0x0a0b, 0x0a0e, 0x0a11, 0x0a12, 0x0a29, 0x0a29, 0x0a31, 0x0a31, 0x0a34, 0x0a34, 0x0a37, 0x0a37, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3d, 0x0a43, 0x0a46, 0x0a49, 0x0a4a, 0x0a4e, 0x0a50, 0x0a52, 0x0a58, 0x0a5d, 0x0a5d, 0x0a5f, 0x0a65, 0x0a76, 0x0a80, 0x0a84, 0x0a84, 0x0a8e, 0x0a8e, 0x0a92, 0x0a92, 0x0aa9, 0x0aa9, 0x0ab1, 0x0ab1, 0x0ab4, 0x0ab4, 0x0aba, 0x0abb, 0x0ac6, 0x0ac6, 0x0aca, 0x0aca, 0x0ace, 0x0acf, 0x0ad1, 0x0adf, 0x0ae4, 0x0ae5, 0x0af2, 0x0b00, 0x0b04, 0x0b04, 0x0b0d, 0x0b0e, 0x0b11, 0x0b12, 0x0b29, 0x0b29, 0x0b31, 0x0b31, 0x0b34, 0x0b34, 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, 0x0b4e, 0x0b55, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, 0x0b78, 0x0b81, 0x0b84, 0x0b84, 0x0b8b, 0x0b8d, 0x0b91, 0x0b91, 0x0b96, 0x0b98, 0x0b9b, 0x0b9b, 0x0b9d, 0x0b9d, 0x0ba0, 0x0ba2, 0x0ba5, 0x0ba7, 0x0bab, 0x0bad, 0x0bba, 0x0bbd, 0x0bc3, 0x0bc5, 0x0bc9, 0x0bc9, 0x0bce, 0x0bcf, 0x0bd1, 0x0bd6, 0x0bd8, 0x0be5, 0x0bfb, 0x0c00, 0x0c04, 0x0c04, 0x0c0d, 0x0c0d, 0x0c11, 0x0c11, 0x0c29, 0x0c29, 0x0c34, 0x0c34, 0x0c3a, 0x0c3c, 0x0c45, 0x0c45, 0x0c49, 0x0c49, 0x0c4e, 0x0c54, 0x0c57, 0x0c57, 0x0c5a, 0x0c5f, 0x0c64, 0x0c65, 0x0c70, 0x0c77, 0x0c80, 0x0c81, 0x0c84, 0x0c84, 0x0c8d, 0x0c8d, 0x0c91, 0x0c91, 0x0ca9, 0x0ca9, 0x0cb4, 0x0cb4, 0x0cba, 0x0cbb, 0x0cc5, 0x0cc5, 0x0cc9, 0x0cc9, 0x0cce, 0x0cd4, 0x0cd7, 0x0cdd, 0x0cdf, 0x0cdf, 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0d01, 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d3b, 0x0d3c, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d4f, 0x0d56, 0x0d58, 0x0d5f, 0x0d64, 0x0d65, 0x0d76, 0x0d78, 0x0d80, 0x0d81, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, 0x0dbc, 0x0dbc, 0x0dbe, 0x0dbf, 0x0dc7, 0x0dc9, 0x0dcb, 0x0dce, 0x0dd5, 0x0dd5, 0x0dd7, 0x0dd7, 0x0de0, 0x0df1, 0x0df5, 0x0e00, 0x0e3b, 0x0e3e, 0x0e5c, 0x0e80, 0x0e83, 0x0e83, 0x0e85, 0x0e86, 0x0e89, 0x0e89, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e93, 0x0e98, 0x0e98, 0x0ea0, 0x0ea0, 0x0ea4, 0x0ea4, 0x0ea6, 0x0ea6, 0x0ea8, 0x0ea9, 0x0eac, 0x0eac, 0x0eba, 0x0eba, 0x0ebe, 0x0ebf, 0x0ec5, 0x0ec5, 0x0ec7, 0x0ec7, 0x0ece, 0x0ecf, 0x0eda, 0x0edb, 0x0ee0, 0x0eff, 0x0f48, 0x0f48, 0x0f6d, 0x0f70, 0x0f98, 0x0f98, 0x0fbd, 0x0fbd, 0x0fcd, 0x0fcd, 0x0fdb, 0x0fff, 0x10c6, 0x10c6, 0x10c8, 0x10cc, 0x10ce, 0x10cf, 0x1249, 0x1249, 0x124e, 0x124f, 0x1257, 0x1257, 0x1259, 0x1259, 0x125e, 0x125f, 0x1289, 0x1289, 0x128e, 0x128f, 0x12b1, 0x12b1, 0x12b6, 0x12b7, 0x12bf, 0x12bf, 0x12c1, 0x12c1, 0x12c6, 0x12c7, 0x12d7, 0x12d7, 0x1311, 0x1311, 0x1316, 0x1317, 0x135b, 0x135c, 0x137d, 0x137f, 0x139a, 0x139f, 0x13f5, 0x13ff, 0x169d, 0x169f, 0x16f1, 0x16ff, 0x170d, 0x170d, 0x1715, 0x171f, 0x1737, 0x173f, 0x1754, 0x175f, 0x176d, 0x176d, 0x1771, 0x1771, 0x1774, 0x177f, 0x17de, 0x17df, 0x17ea, 0x17ef, 0x17fa, 0x17ff, 0x180f, 0x180f, 0x181a, 0x181f, 0x1878, 0x187f, 0x18ab, 0x18af, 0x18f6, 0x18ff, 0x191d, 0x191f, 0x192c, 0x192f, 0x193c, 0x193f, 0x1941, 0x1943, 0x196e, 0x196f, 0x1975, 0x197f, 0x19ac, 0x19af, 0x19ca, 0x19cf, 0x19db, 0x19dd, 0x1a1c, 0x1a1d, 0x1a5f, 0x1a5f, 0x1a7d, 0x1a7e, 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, 0x1c80, 0x1cbf, 0x1cc8, 0x1ccf, 0x1cf7, 0x1cff, 0x1de7, 0x1dfb, 0x1f16, 0x1f17, 0x1f1e, 0x1f1f, 0x1f46, 0x1f47, 0x1f4e, 0x1f4f, 0x1f58, 0x1f58, 0x1f5a, 0x1f5a, 0x1f5c, 0x1f5c, 0x1f5e, 0x1f5e, 0x1f7e, 0x1f7f, 0x1fb5, 0x1fb5, 0x1fc5, 0x1fc5, 0x1fd4, 0x1fd5, 0x1fdc, 0x1fdc, 0x1ff0, 0x1ff1, 0x1ff5, 0x1ff5, 0x1fff, 0x1fff, 0x200b, 0x200f, 0x202a, 0x202e, 0x2060, 0x206f, 0x2072, 0x2073, 0x208f, 0x208f, 0x209d, 0x209f, 0x20ba, 0x20cf, 0x20f1, 0x20ff, 0x218a, 0x218f, 0x23f4, 0x23ff, 0x2427, 0x243f, 0x244b, 0x245f, 0x2700, 0x2700, 0x2b4d, 0x2b4f, 0x2b5a, 0x2bff, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, 0x2d26, 0x2d26, 0x2d28, 0x2d2c, 0x2d2e, 0x2d2f, 0x2d68, 0x2d6e, 0x2d71, 0x2d7e, 0x2d97, 0x2d9f, 0x2da7, 0x2da7, 0x2daf, 0x2daf, 0x2db7, 0x2db7, 0x2dbf, 0x2dbf, 0x2dc7, 0x2dc7, 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, 0x2e3c, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x312e, 0x3130, 0x318f, 0x318f, 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, 0x32ff, 0x32ff, 0x4db6, 0x4dbf, 0x9fcd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa698, 0xa69e, 0xa6f8, 0xa6ff, 0xa78f, 0xa78f, 0xa794, 0xa79f, 0xa7ab, 0xa7f7, 0xa82c, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c5, 0xa8cd, 0xa8da, 0xa8df, 0xa8fc, 0xa8ff, 0xa954, 0xa95e, 0xa97d, 0xa97f, 0xa9ce, 0xa9ce, 0xa9da, 0xa9dd, 0xa9e0, 0xa9ff, 0xaa37, 0xaa3f, 0xaa4e, 0xaa4f, 0xaa5a, 0xaa5b, 0xaa7c, 0xaa7f, 0xaac3, 0xaada, 0xaaf7, 0xab00, 0xab07, 0xab08, 0xab0f, 0xab10, 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xabbf, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, 0xd7c7, 0xd7ca, 0xd7fc, 0xf8ff, 0xfa6e, 0xfa6f, 0xfada, 0xfaff, 0xfb07, 0xfb12, 0xfb18, 0xfb1c, 0xfb37, 0xfb37, 0xfb3d, 0xfb3d, 0xfb3f, 0xfb3f, 0xfb42, 0xfb42, 0xfb45, 0xfb45, 0xfbc2, 0xfbd2, 0xfd40, 0xfd4f, 0xfd90, 0xfd91, 0xfdc8, 0xfdef, 0xfdfe, 0xfdff, 0xfe1a, 0xfe1f, 0xfe27, 0xfe2f, 0xfe53, 0xfe53, 0xfe67, 0xfe67, 0xfe6c, 0xfe6f, 0xfe75, 0xfe75, 0xfefd, 0xff00, 0xffbf, 0xffc1, 0xffc8, 0xffc9, 0xffd0, 0xffd1, 0xffd8, 0xffd9, 0xffdd, 0xffdf, 0xffe7, 0xffe7, 0xffef, 0xfffb, 0xfffe, 0xffff, 0x1000c, 0x1000c, 0x10027, 0x10027, 0x1003b, 0x1003b, 0x1003e, 0x1003e, 0x1004e, 0x1004f, 0x1005e, 0x1007f, 0x100fb, 0x100ff, 0x10103, 0x10106, 0x10134, 0x10136, 0x1018b, 0x1018f, 0x1019c, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, 0x102d1, 0x102ff, 0x1031f, 0x1031f, 0x10324, 0x1032f, 0x1034b, 0x1037f, 0x1039e, 0x1039e, 0x103c4, 0x103c7, 0x103d6, 0x103ff, 0x1049e, 0x1049f, 0x104aa, 0x107ff, 0x10806, 0x10807, 0x10809, 0x10809, 0x10836, 0x10836, 0x10839, 0x1083b, 0x1083d, 0x1083e, 0x10856, 0x10856, 0x10860, 0x108ff, 0x1091c, 0x1091e, 0x1093a, 0x1093e, 0x10940, 0x1097f, 0x109b8, 0x109bd, 0x109c0, 0x109ff, 0x10a04, 0x10a04, 0x10a07, 0x10a0b, 0x10a14, 0x10a14, 0x10a18, 0x10a18, 0x10a34, 0x10a37, 0x10a3b, 0x10a3e, 0x10a48, 0x10a4f, 0x10a59, 0x10a5f, 0x10a80, 0x10aff, 0x10b36, 0x10b38, 0x10b56, 0x10b57, 0x10b73, 0x10b77, 0x10b80, 0x10bff, 0x10c49, 0x10e5f, 0x10e7f, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107f, 0x110bd, 0x110bd, 0x110c2, 0x110cf, 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, 0x11144, 0x1117f, 0x111c9, 0x111cf, 0x111da, 0x1167f, 0x116b8, 0x116bf, 0x116ca, 0x11fff, 0x1236f, 0x123ff, 0x12463, 0x1246f, 0x12474, 0x12fff, 0x1342f, 0x167ff, 0x16a39, 0x16eff, 0x16f45, 0x16f4f, 0x16f7f, 0x16f8e, 0x16fa0, 0x1afff, 0x1b002, 0x1cfff, 0x1d0f6, 0x1d0ff, 0x1d127, 0x1d128, 0x1d173, 0x1d17a, 0x1d1de, 0x1d1ff, 0x1d246, 0x1d2ff, 0x1d357, 0x1d35f, 0x1d372, 0x1d3ff, 0x1d455, 0x1d455, 0x1d49d, 0x1d49d, 0x1d4a0, 0x1d4a1, 0x1d4a3, 0x1d4a4, 0x1d4a7, 0x1d4a8, 0x1d4ad, 0x1d4ad, 0x1d4ba, 0x1d4ba, 0x1d4bc, 0x1d4bc, 0x1d4c4, 0x1d4c4, 0x1d506, 0x1d506, 0x1d50b, 0x1d50c, 0x1d515, 0x1d515, 0x1d51d, 0x1d51d, 0x1d53a, 0x1d53a, 0x1d53f, 0x1d53f, 0x1d545, 0x1d545, 0x1d547, 0x1d549, 0x1d551, 0x1d551, 0x1d6a6, 0x1d6a7, 0x1d7cc, 0x1d7cd, 0x1d800, 0x1edff, 0x1ee04, 0x1ee04, 0x1ee20, 0x1ee20, 0x1ee23, 0x1ee23, 0x1ee25, 0x1ee26, 0x1ee28, 0x1ee28, 0x1ee33, 0x1ee33, 0x1ee38, 0x1ee38, 0x1ee3a, 0x1ee3a, 0x1ee3c, 0x1ee41, 0x1ee43, 0x1ee46, 0x1ee48, 0x1ee48, 0x1ee4a, 0x1ee4a, 0x1ee4c, 0x1ee4c, 0x1ee50, 0x1ee50, 0x1ee53, 0x1ee53, 0x1ee55, 0x1ee56, 0x1ee58, 0x1ee58, 0x1ee5a, 0x1ee5a, 0x1ee5c, 0x1ee5c, 0x1ee5e, 0x1ee5e, 0x1ee60, 0x1ee60, 0x1ee63, 0x1ee63, 0x1ee65, 0x1ee66, 0x1ee6b, 0x1ee6b, 0x1ee73, 0x1ee73, 0x1ee78, 0x1ee78, 0x1ee7d, 0x1ee7d, 0x1ee7f, 0x1ee7f, 0x1ee8a, 0x1ee8a, 0x1ee9c, 0x1eea0, 0x1eea4, 0x1eea4, 0x1eeaa, 0x1eeaa, 0x1eebc, 0x1eeef, 0x1eef2, 0x1efff, 0x1f02c, 0x1f02f, 0x1f094, 0x1f09f, 0x1f0af, 0x1f0b0, 0x1f0bf, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0e0, 0x1f0ff, 0x1f10b, 0x1f10f, 0x1f12f, 0x1f12f, 0x1f16c, 0x1f16f, 0x1f19b, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23b, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f2ff, 0x1f321, 0x1f32f, 0x1f336, 0x1f336, 0x1f37d, 0x1f37f, 0x1f394, 0x1f39f, 0x1f3c5, 0x1f3c5, 0x1f3cb, 0x1f3df, 0x1f3f1, 0x1f3ff, 0x1f43f, 0x1f43f, 0x1f441, 0x1f441, 0x1f4f8, 0x1f4f8, 0x1f4fd, 0x1f4ff, 0x1f53e, 0x1f53f, 0x1f544, 0x1f54f, 0x1f568, 0x1f5fa, 0x1f641, 0x1f644, 0x1f650, 0x1f67f, 0x1f6c6, 0x1f6ff, 0x1f774, 0x1ffff, 0x2a6d7, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2f7ff, 0x2fa1e, 0xe00ff, 0xe01f0, 0x10ffff, }; /* CR_C */ /* 'Cc': General Category */ #define CR_Cc CR_Cntrl /* 'Cf': General Category */ static const OnigCodePoint CR_Cf[] = { 14, 0x00ad, 0x00ad, 0x0600, 0x0604, 0x06dd, 0x06dd, 0x070f, 0x070f, 0x200b, 0x200f, 0x202a, 0x202e, 0x2060, 0x2064, 0x206a, 0x206f, 0xfeff, 0xfeff, 0xfff9, 0xfffb, 0x110bd, 0x110bd, 0x1d173, 0x1d17a, 0xe0001, 0xe0001, 0xe0020, 0xe007f, }; /* CR_Cf */ /* 'Cn': General Category */ static const OnigCodePoint CR_Cn[] = { 539, 0x0378, 0x0379, 0x037f, 0x0383, 0x038b, 0x038b, 0x038d, 0x038d, 0x03a2, 0x03a2, 0x0528, 0x0530, 0x0557, 0x0558, 0x0560, 0x0560, 0x0588, 0x0588, 0x058b, 0x058e, 0x0590, 0x0590, 0x05c8, 0x05cf, 0x05eb, 0x05ef, 0x05f5, 0x05ff, 0x0605, 0x0605, 0x061c, 0x061d, 0x070e, 0x070e, 0x074b, 0x074c, 0x07b2, 0x07bf, 0x07fb, 0x07ff, 0x082e, 0x082f, 0x083f, 0x083f, 0x085c, 0x085d, 0x085f, 0x089f, 0x08a1, 0x08a1, 0x08ad, 0x08e3, 0x08ff, 0x08ff, 0x0978, 0x0978, 0x0980, 0x0980, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, 0x09a9, 0x09a9, 0x09b1, 0x09b1, 0x09b3, 0x09b5, 0x09ba, 0x09bb, 0x09c5, 0x09c6, 0x09c9, 0x09ca, 0x09cf, 0x09d6, 0x09d8, 0x09db, 0x09de, 0x09de, 0x09e4, 0x09e5, 0x09fc, 0x0a00, 0x0a04, 0x0a04, 0x0a0b, 0x0a0e, 0x0a11, 0x0a12, 0x0a29, 0x0a29, 0x0a31, 0x0a31, 0x0a34, 0x0a34, 0x0a37, 0x0a37, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3d, 0x0a43, 0x0a46, 0x0a49, 0x0a4a, 0x0a4e, 0x0a50, 0x0a52, 0x0a58, 0x0a5d, 0x0a5d, 0x0a5f, 0x0a65, 0x0a76, 0x0a80, 0x0a84, 0x0a84, 0x0a8e, 0x0a8e, 0x0a92, 0x0a92, 0x0aa9, 0x0aa9, 0x0ab1, 0x0ab1, 0x0ab4, 0x0ab4, 0x0aba, 0x0abb, 0x0ac6, 0x0ac6, 0x0aca, 0x0aca, 0x0ace, 0x0acf, 0x0ad1, 0x0adf, 0x0ae4, 0x0ae5, 0x0af2, 0x0b00, 0x0b04, 0x0b04, 0x0b0d, 0x0b0e, 0x0b11, 0x0b12, 0x0b29, 0x0b29, 0x0b31, 0x0b31, 0x0b34, 0x0b34, 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, 0x0b4e, 0x0b55, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, 0x0b78, 0x0b81, 0x0b84, 0x0b84, 0x0b8b, 0x0b8d, 0x0b91, 0x0b91, 0x0b96, 0x0b98, 0x0b9b, 0x0b9b, 0x0b9d, 0x0b9d, 0x0ba0, 0x0ba2, 0x0ba5, 0x0ba7, 0x0bab, 0x0bad, 0x0bba, 0x0bbd, 0x0bc3, 0x0bc5, 0x0bc9, 0x0bc9, 0x0bce, 0x0bcf, 0x0bd1, 0x0bd6, 0x0bd8, 0x0be5, 0x0bfb, 0x0c00, 0x0c04, 0x0c04, 0x0c0d, 0x0c0d, 0x0c11, 0x0c11, 0x0c29, 0x0c29, 0x0c34, 0x0c34, 0x0c3a, 0x0c3c, 0x0c45, 0x0c45, 0x0c49, 0x0c49, 0x0c4e, 0x0c54, 0x0c57, 0x0c57, 0x0c5a, 0x0c5f, 0x0c64, 0x0c65, 0x0c70, 0x0c77, 0x0c80, 0x0c81, 0x0c84, 0x0c84, 0x0c8d, 0x0c8d, 0x0c91, 0x0c91, 0x0ca9, 0x0ca9, 0x0cb4, 0x0cb4, 0x0cba, 0x0cbb, 0x0cc5, 0x0cc5, 0x0cc9, 0x0cc9, 0x0cce, 0x0cd4, 0x0cd7, 0x0cdd, 0x0cdf, 0x0cdf, 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0d01, 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d3b, 0x0d3c, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d4f, 0x0d56, 0x0d58, 0x0d5f, 0x0d64, 0x0d65, 0x0d76, 0x0d78, 0x0d80, 0x0d81, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, 0x0dbc, 0x0dbc, 0x0dbe, 0x0dbf, 0x0dc7, 0x0dc9, 0x0dcb, 0x0dce, 0x0dd5, 0x0dd5, 0x0dd7, 0x0dd7, 0x0de0, 0x0df1, 0x0df5, 0x0e00, 0x0e3b, 0x0e3e, 0x0e5c, 0x0e80, 0x0e83, 0x0e83, 0x0e85, 0x0e86, 0x0e89, 0x0e89, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e93, 0x0e98, 0x0e98, 0x0ea0, 0x0ea0, 0x0ea4, 0x0ea4, 0x0ea6, 0x0ea6, 0x0ea8, 0x0ea9, 0x0eac, 0x0eac, 0x0eba, 0x0eba, 0x0ebe, 0x0ebf, 0x0ec5, 0x0ec5, 0x0ec7, 0x0ec7, 0x0ece, 0x0ecf, 0x0eda, 0x0edb, 0x0ee0, 0x0eff, 0x0f48, 0x0f48, 0x0f6d, 0x0f70, 0x0f98, 0x0f98, 0x0fbd, 0x0fbd, 0x0fcd, 0x0fcd, 0x0fdb, 0x0fff, 0x10c6, 0x10c6, 0x10c8, 0x10cc, 0x10ce, 0x10cf, 0x1249, 0x1249, 0x124e, 0x124f, 0x1257, 0x1257, 0x1259, 0x1259, 0x125e, 0x125f, 0x1289, 0x1289, 0x128e, 0x128f, 0x12b1, 0x12b1, 0x12b6, 0x12b7, 0x12bf, 0x12bf, 0x12c1, 0x12c1, 0x12c6, 0x12c7, 0x12d7, 0x12d7, 0x1311, 0x1311, 0x1316, 0x1317, 0x135b, 0x135c, 0x137d, 0x137f, 0x139a, 0x139f, 0x13f5, 0x13ff, 0x169d, 0x169f, 0x16f1, 0x16ff, 0x170d, 0x170d, 0x1715, 0x171f, 0x1737, 0x173f, 0x1754, 0x175f, 0x176d, 0x176d, 0x1771, 0x1771, 0x1774, 0x177f, 0x17de, 0x17df, 0x17ea, 0x17ef, 0x17fa, 0x17ff, 0x180f, 0x180f, 0x181a, 0x181f, 0x1878, 0x187f, 0x18ab, 0x18af, 0x18f6, 0x18ff, 0x191d, 0x191f, 0x192c, 0x192f, 0x193c, 0x193f, 0x1941, 0x1943, 0x196e, 0x196f, 0x1975, 0x197f, 0x19ac, 0x19af, 0x19ca, 0x19cf, 0x19db, 0x19dd, 0x1a1c, 0x1a1d, 0x1a5f, 0x1a5f, 0x1a7d, 0x1a7e, 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, 0x1c80, 0x1cbf, 0x1cc8, 0x1ccf, 0x1cf7, 0x1cff, 0x1de7, 0x1dfb, 0x1f16, 0x1f17, 0x1f1e, 0x1f1f, 0x1f46, 0x1f47, 0x1f4e, 0x1f4f, 0x1f58, 0x1f58, 0x1f5a, 0x1f5a, 0x1f5c, 0x1f5c, 0x1f5e, 0x1f5e, 0x1f7e, 0x1f7f, 0x1fb5, 0x1fb5, 0x1fc5, 0x1fc5, 0x1fd4, 0x1fd5, 0x1fdc, 0x1fdc, 0x1ff0, 0x1ff1, 0x1ff5, 0x1ff5, 0x1fff, 0x1fff, 0x2065, 0x2069, 0x2072, 0x2073, 0x208f, 0x208f, 0x209d, 0x209f, 0x20ba, 0x20cf, 0x20f1, 0x20ff, 0x218a, 0x218f, 0x23f4, 0x23ff, 0x2427, 0x243f, 0x244b, 0x245f, 0x2700, 0x2700, 0x2b4d, 0x2b4f, 0x2b5a, 0x2bff, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, 0x2d26, 0x2d26, 0x2d28, 0x2d2c, 0x2d2e, 0x2d2f, 0x2d68, 0x2d6e, 0x2d71, 0x2d7e, 0x2d97, 0x2d9f, 0x2da7, 0x2da7, 0x2daf, 0x2daf, 0x2db7, 0x2db7, 0x2dbf, 0x2dbf, 0x2dc7, 0x2dc7, 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, 0x2e3c, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x312e, 0x3130, 0x318f, 0x318f, 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, 0x32ff, 0x32ff, 0x4db6, 0x4dbf, 0x9fcd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa698, 0xa69e, 0xa6f8, 0xa6ff, 0xa78f, 0xa78f, 0xa794, 0xa79f, 0xa7ab, 0xa7f7, 0xa82c, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c5, 0xa8cd, 0xa8da, 0xa8df, 0xa8fc, 0xa8ff, 0xa954, 0xa95e, 0xa97d, 0xa97f, 0xa9ce, 0xa9ce, 0xa9da, 0xa9dd, 0xa9e0, 0xa9ff, 0xaa37, 0xaa3f, 0xaa4e, 0xaa4f, 0xaa5a, 0xaa5b, 0xaa7c, 0xaa7f, 0xaac3, 0xaada, 0xaaf7, 0xab00, 0xab07, 0xab08, 0xab0f, 0xab10, 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xabbf, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, 0xd7c7, 0xd7ca, 0xd7fc, 0xd7ff, 0xfa6e, 0xfa6f, 0xfada, 0xfaff, 0xfb07, 0xfb12, 0xfb18, 0xfb1c, 0xfb37, 0xfb37, 0xfb3d, 0xfb3d, 0xfb3f, 0xfb3f, 0xfb42, 0xfb42, 0xfb45, 0xfb45, 0xfbc2, 0xfbd2, 0xfd40, 0xfd4f, 0xfd90, 0xfd91, 0xfdc8, 0xfdef, 0xfdfe, 0xfdff, 0xfe1a, 0xfe1f, 0xfe27, 0xfe2f, 0xfe53, 0xfe53, 0xfe67, 0xfe67, 0xfe6c, 0xfe6f, 0xfe75, 0xfe75, 0xfefd, 0xfefe, 0xff00, 0xff00, 0xffbf, 0xffc1, 0xffc8, 0xffc9, 0xffd0, 0xffd1, 0xffd8, 0xffd9, 0xffdd, 0xffdf, 0xffe7, 0xffe7, 0xffef, 0xfff8, 0xfffe, 0xffff, 0x1000c, 0x1000c, 0x10027, 0x10027, 0x1003b, 0x1003b, 0x1003e, 0x1003e, 0x1004e, 0x1004f, 0x1005e, 0x1007f, 0x100fb, 0x100ff, 0x10103, 0x10106, 0x10134, 0x10136, 0x1018b, 0x1018f, 0x1019c, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, 0x102d1, 0x102ff, 0x1031f, 0x1031f, 0x10324, 0x1032f, 0x1034b, 0x1037f, 0x1039e, 0x1039e, 0x103c4, 0x103c7, 0x103d6, 0x103ff, 0x1049e, 0x1049f, 0x104aa, 0x107ff, 0x10806, 0x10807, 0x10809, 0x10809, 0x10836, 0x10836, 0x10839, 0x1083b, 0x1083d, 0x1083e, 0x10856, 0x10856, 0x10860, 0x108ff, 0x1091c, 0x1091e, 0x1093a, 0x1093e, 0x10940, 0x1097f, 0x109b8, 0x109bd, 0x109c0, 0x109ff, 0x10a04, 0x10a04, 0x10a07, 0x10a0b, 0x10a14, 0x10a14, 0x10a18, 0x10a18, 0x10a34, 0x10a37, 0x10a3b, 0x10a3e, 0x10a48, 0x10a4f, 0x10a59, 0x10a5f, 0x10a80, 0x10aff, 0x10b36, 0x10b38, 0x10b56, 0x10b57, 0x10b73, 0x10b77, 0x10b80, 0x10bff, 0x10c49, 0x10e5f, 0x10e7f, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107f, 0x110c2, 0x110cf, 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, 0x11144, 0x1117f, 0x111c9, 0x111cf, 0x111da, 0x1167f, 0x116b8, 0x116bf, 0x116ca, 0x11fff, 0x1236f, 0x123ff, 0x12463, 0x1246f, 0x12474, 0x12fff, 0x1342f, 0x167ff, 0x16a39, 0x16eff, 0x16f45, 0x16f4f, 0x16f7f, 0x16f8e, 0x16fa0, 0x1afff, 0x1b002, 0x1cfff, 0x1d0f6, 0x1d0ff, 0x1d127, 0x1d128, 0x1d1de, 0x1d1ff, 0x1d246, 0x1d2ff, 0x1d357, 0x1d35f, 0x1d372, 0x1d3ff, 0x1d455, 0x1d455, 0x1d49d, 0x1d49d, 0x1d4a0, 0x1d4a1, 0x1d4a3, 0x1d4a4, 0x1d4a7, 0x1d4a8, 0x1d4ad, 0x1d4ad, 0x1d4ba, 0x1d4ba, 0x1d4bc, 0x1d4bc, 0x1d4c4, 0x1d4c4, 0x1d506, 0x1d506, 0x1d50b, 0x1d50c, 0x1d515, 0x1d515, 0x1d51d, 0x1d51d, 0x1d53a, 0x1d53a, 0x1d53f, 0x1d53f, 0x1d545, 0x1d545, 0x1d547, 0x1d549, 0x1d551, 0x1d551, 0x1d6a6, 0x1d6a7, 0x1d7cc, 0x1d7cd, 0x1d800, 0x1edff, 0x1ee04, 0x1ee04, 0x1ee20, 0x1ee20, 0x1ee23, 0x1ee23, 0x1ee25, 0x1ee26, 0x1ee28, 0x1ee28, 0x1ee33, 0x1ee33, 0x1ee38, 0x1ee38, 0x1ee3a, 0x1ee3a, 0x1ee3c, 0x1ee41, 0x1ee43, 0x1ee46, 0x1ee48, 0x1ee48, 0x1ee4a, 0x1ee4a, 0x1ee4c, 0x1ee4c, 0x1ee50, 0x1ee50, 0x1ee53, 0x1ee53, 0x1ee55, 0x1ee56, 0x1ee58, 0x1ee58, 0x1ee5a, 0x1ee5a, 0x1ee5c, 0x1ee5c, 0x1ee5e, 0x1ee5e, 0x1ee60, 0x1ee60, 0x1ee63, 0x1ee63, 0x1ee65, 0x1ee66, 0x1ee6b, 0x1ee6b, 0x1ee73, 0x1ee73, 0x1ee78, 0x1ee78, 0x1ee7d, 0x1ee7d, 0x1ee7f, 0x1ee7f, 0x1ee8a, 0x1ee8a, 0x1ee9c, 0x1eea0, 0x1eea4, 0x1eea4, 0x1eeaa, 0x1eeaa, 0x1eebc, 0x1eeef, 0x1eef2, 0x1efff, 0x1f02c, 0x1f02f, 0x1f094, 0x1f09f, 0x1f0af, 0x1f0b0, 0x1f0bf, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0e0, 0x1f0ff, 0x1f10b, 0x1f10f, 0x1f12f, 0x1f12f, 0x1f16c, 0x1f16f, 0x1f19b, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23b, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f2ff, 0x1f321, 0x1f32f, 0x1f336, 0x1f336, 0x1f37d, 0x1f37f, 0x1f394, 0x1f39f, 0x1f3c5, 0x1f3c5, 0x1f3cb, 0x1f3df, 0x1f3f1, 0x1f3ff, 0x1f43f, 0x1f43f, 0x1f441, 0x1f441, 0x1f4f8, 0x1f4f8, 0x1f4fd, 0x1f4ff, 0x1f53e, 0x1f53f, 0x1f544, 0x1f54f, 0x1f568, 0x1f5fa, 0x1f641, 0x1f644, 0x1f650, 0x1f67f, 0x1f6c6, 0x1f6ff, 0x1f774, 0x1ffff, 0x2a6d7, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2f7ff, 0x2fa1e, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xe00ff, 0xe01f0, 0xeffff, 0xffffe, 0xfffff, 0x10fffe, 0x10ffff, }; /* CR_Cn */ /* 'Co': General Category */ static const OnigCodePoint CR_Co[] = { 3, 0xe000, 0xf8ff, 0xf0000, 0xffffd, 0x100000, 0x10fffd, }; /* CR_Co */ /* 'Cs': General Category */ static const OnigCodePoint CR_Cs[] = { 1, 0xd800, 0xdfff, }; /* CR_Cs */ /* 'L': Major Category */ static const OnigCodePoint CR_L[] = { 486, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0370, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0620, 0x064a, 0x066e, 0x066f, 0x0671, 0x06d3, 0x06d5, 0x06d5, 0x06e5, 0x06e6, 0x06ee, 0x06ef, 0x06fa, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x0710, 0x0712, 0x072f, 0x074d, 0x07a5, 0x07b1, 0x07b1, 0x07ca, 0x07ea, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x0815, 0x081a, 0x081a, 0x0824, 0x0824, 0x0828, 0x0828, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, 0x0958, 0x0961, 0x0971, 0x0977, 0x0979, 0x097f, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09bd, 0x09ce, 0x09ce, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09f0, 0x09f1, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a72, 0x0a74, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0abd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae1, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b3d, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b71, 0x0b71, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bd0, 0x0bd0, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c3d, 0x0c58, 0x0c59, 0x0c60, 0x0c61, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbd, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, 0x0d4e, 0x0d4e, 0x0d60, 0x0d61, 0x0d7a, 0x0d7f, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0e01, 0x0e30, 0x0e32, 0x0e33, 0x0e40, 0x0e46, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb3, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f88, 0x0f8c, 0x1000, 0x102a, 0x103f, 0x103f, 0x1050, 0x1055, 0x105a, 0x105d, 0x1061, 0x1061, 0x1065, 0x1066, 0x106e, 0x1070, 0x1075, 0x1081, 0x108e, 0x108e, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3, 0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x1820, 0x1877, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1950, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19c1, 0x19c7, 0x1a00, 0x1a16, 0x1a20, 0x1a54, 0x1aa7, 0x1aa7, 0x1b05, 0x1b33, 0x1b45, 0x1b4b, 0x1b83, 0x1ba0, 0x1bae, 0x1baf, 0x1bba, 0x1be5, 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, 0x1ce9, 0x1cec, 0x1cee, 0x1cf1, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2183, 0x2184, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2e2f, 0x2e2f, 0x3005, 0x3006, 0x3031, 0x3035, 0x303b, 0x303c, 0x3041, 0x3096, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa640, 0xa66e, 0xa67f, 0xa697, 0xa6a0, 0xa6e5, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, 0xa840, 0xa873, 0xa882, 0xa8b3, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa90a, 0xa925, 0xa930, 0xa946, 0xa960, 0xa97c, 0xa984, 0xa9b2, 0xa9cf, 0xa9cf, 0xaa00, 0xaa28, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaea, 0xaaf2, 0xaaf4, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x10340, 0x10342, 0x10349, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x10400, 0x1049d, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11183, 0x111b2, 0x111c1, 0x111c4, 0x11680, 0x116aa, 0x12000, 0x1236e, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f50, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_L */ /* 'LC': General Category */ static const OnigCodePoint CR_LC[] = { 113, 0x0041, 0x005a, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x01ba, 0x01bc, 0x01bf, 0x01c4, 0x0293, 0x0295, 0x02af, 0x0370, 0x0373, 0x0376, 0x0377, 0x037b, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0561, 0x0587, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1d00, 0x1d2b, 0x1d6b, 0x1d77, 0x1d79, 0x1d9a, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2134, 0x2139, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2183, 0x2184, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2c7b, 0x2c7e, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa640, 0xa66d, 0xa680, 0xa697, 0xa722, 0xa76f, 0xa771, 0xa787, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7fa, 0xa7fa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff21, 0xff3a, 0xff41, 0xff5a, 0x10400, 0x1044f, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, }; /* CR_LC */ /* 'Ll': General Category */ static const OnigCodePoint CR_Ll[] = { 611, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, 0x00f8, 0x00ff, 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, 0x0131, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0138, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x0180, 0x0183, 0x0183, 0x0185, 0x0185, 0x0188, 0x0188, 0x018c, 0x018d, 0x0192, 0x0192, 0x0195, 0x0195, 0x0199, 0x019b, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x01a8, 0x01a8, 0x01aa, 0x01ab, 0x01ad, 0x01ad, 0x01b0, 0x01b0, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x01b9, 0x01ba, 0x01bd, 0x01bf, 0x01c6, 0x01c6, 0x01c9, 0x01c9, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dd, 0x01df, 0x01df, 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01f0, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff, 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, 0x0221, 0x0221, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, 0x0231, 0x0231, 0x0233, 0x0239, 0x023c, 0x023c, 0x023f, 0x0240, 0x0242, 0x0242, 0x0247, 0x0247, 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x0293, 0x0295, 0x02af, 0x0371, 0x0371, 0x0373, 0x0373, 0x0377, 0x0377, 0x037b, 0x037d, 0x0390, 0x0390, 0x03ac, 0x03ce, 0x03d0, 0x03d1, 0x03d5, 0x03d7, 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03f3, 0x03f5, 0x03f5, 0x03f8, 0x03f8, 0x03fb, 0x03fc, 0x0430, 0x045f, 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, 0x0481, 0x0481, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04cf, 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff, 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, 0x0561, 0x0587, 0x1d00, 0x1d2b, 0x1d6b, 0x1d77, 0x1d79, 0x1d9a, 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e9d, 0x1e9f, 0x1e9f, 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45, 0x1f50, 0x1f57, 0x1f60, 0x1f67, 0x1f70, 0x1f7d, 0x1f80, 0x1f87, 0x1f90, 0x1f97, 0x1fa0, 0x1fa7, 0x1fb0, 0x1fb4, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fc7, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fd7, 0x1fe0, 0x1fe7, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ff7, 0x210a, 0x210a, 0x210e, 0x210f, 0x2113, 0x2113, 0x212f, 0x212f, 0x2134, 0x2134, 0x2139, 0x2139, 0x213c, 0x213d, 0x2146, 0x2149, 0x214e, 0x214e, 0x2184, 0x2184, 0x2c30, 0x2c5e, 0x2c61, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x2c71, 0x2c71, 0x2c73, 0x2c74, 0x2c76, 0x2c7b, 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce4, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cf3, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa731, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa76f, 0xa771, 0xa778, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0xa77f, 0xa77f, 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, 0xa78c, 0xa78c, 0xa78e, 0xa78e, 0xa791, 0xa791, 0xa793, 0xa793, 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, 0xa7a9, 0xa7a9, 0xa7fa, 0xa7fa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff41, 0xff5a, 0x10428, 0x1044f, 0x1d41a, 0x1d433, 0x1d44e, 0x1d454, 0x1d456, 0x1d467, 0x1d482, 0x1d49b, 0x1d4b6, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d4cf, 0x1d4ea, 0x1d503, 0x1d51e, 0x1d537, 0x1d552, 0x1d56b, 0x1d586, 0x1d59f, 0x1d5ba, 0x1d5d3, 0x1d5ee, 0x1d607, 0x1d622, 0x1d63b, 0x1d656, 0x1d66f, 0x1d68a, 0x1d6a5, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6e1, 0x1d6fc, 0x1d714, 0x1d716, 0x1d71b, 0x1d736, 0x1d74e, 0x1d750, 0x1d755, 0x1d770, 0x1d788, 0x1d78a, 0x1d78f, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7c9, 0x1d7cb, 0x1d7cb, }; /* CR_Ll */ /* 'Lm': General Category */ static const OnigCodePoint CR_Lm[] = { 52, 0x02b0, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0374, 0x0374, 0x037a, 0x037a, 0x0559, 0x0559, 0x0640, 0x0640, 0x06e5, 0x06e6, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x081a, 0x081a, 0x0824, 0x0824, 0x0828, 0x0828, 0x0971, 0x0971, 0x0e46, 0x0e46, 0x0ec6, 0x0ec6, 0x10fc, 0x10fc, 0x17d7, 0x17d7, 0x1843, 0x1843, 0x1aa7, 0x1aa7, 0x1c78, 0x1c7d, 0x1d2c, 0x1d6a, 0x1d78, 0x1d78, 0x1d9b, 0x1dbf, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2c7c, 0x2c7d, 0x2d6f, 0x2d6f, 0x2e2f, 0x2e2f, 0x3005, 0x3005, 0x3031, 0x3035, 0x303b, 0x303b, 0x309d, 0x309e, 0x30fc, 0x30fe, 0xa015, 0xa015, 0xa4f8, 0xa4fd, 0xa60c, 0xa60c, 0xa67f, 0xa67f, 0xa717, 0xa71f, 0xa770, 0xa770, 0xa788, 0xa788, 0xa7f8, 0xa7f9, 0xa9cf, 0xa9cf, 0xaa70, 0xaa70, 0xaadd, 0xaadd, 0xaaf3, 0xaaf4, 0xff70, 0xff70, 0xff9e, 0xff9f, 0x16f93, 0x16f9f, }; /* CR_Lm */ /* 'Lo': General Category */ static const OnigCodePoint CR_Lo[] = { 371, 0x00aa, 0x00aa, 0x00ba, 0x00ba, 0x01bb, 0x01bb, 0x01c0, 0x01c3, 0x0294, 0x0294, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0620, 0x063f, 0x0641, 0x064a, 0x066e, 0x066f, 0x0671, 0x06d3, 0x06d5, 0x06d5, 0x06ee, 0x06ef, 0x06fa, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x0710, 0x0712, 0x072f, 0x074d, 0x07a5, 0x07b1, 0x07b1, 0x07ca, 0x07ea, 0x0800, 0x0815, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, 0x0958, 0x0961, 0x0972, 0x0977, 0x0979, 0x097f, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09bd, 0x09ce, 0x09ce, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09f0, 0x09f1, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a72, 0x0a74, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0abd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae1, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b3d, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b71, 0x0b71, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bd0, 0x0bd0, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c3d, 0x0c58, 0x0c59, 0x0c60, 0x0c61, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbd, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, 0x0d4e, 0x0d4e, 0x0d60, 0x0d61, 0x0d7a, 0x0d7f, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0e01, 0x0e30, 0x0e32, 0x0e33, 0x0e40, 0x0e45, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb3, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f88, 0x0f8c, 0x1000, 0x102a, 0x103f, 0x103f, 0x1050, 0x1055, 0x105a, 0x105d, 0x1061, 0x1061, 0x1065, 0x1066, 0x106e, 0x1070, 0x1075, 0x1081, 0x108e, 0x108e, 0x10d0, 0x10fa, 0x10fd, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3, 0x17dc, 0x17dc, 0x1820, 0x1842, 0x1844, 0x1877, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1950, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19c1, 0x19c7, 0x1a00, 0x1a16, 0x1a20, 0x1a54, 0x1b05, 0x1b33, 0x1b45, 0x1b4b, 0x1b83, 0x1ba0, 0x1bae, 0x1baf, 0x1bba, 0x1be5, 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c77, 0x1ce9, 0x1cec, 0x1cee, 0x1cf1, 0x1cf5, 0x1cf6, 0x2135, 0x2138, 0x2d30, 0x2d67, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x3006, 0x3006, 0x303c, 0x303c, 0x3041, 0x3096, 0x309f, 0x309f, 0x30a1, 0x30fa, 0x30ff, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa014, 0xa016, 0xa48c, 0xa4d0, 0xa4f7, 0xa500, 0xa60b, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa66e, 0xa66e, 0xa6a0, 0xa6e5, 0xa7fb, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, 0xa840, 0xa873, 0xa882, 0xa8b3, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa90a, 0xa925, 0xa930, 0xa946, 0xa960, 0xa97c, 0xa984, 0xa9b2, 0xaa00, 0xaa28, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa60, 0xaa6f, 0xaa71, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadc, 0xaae0, 0xaaea, 0xaaf2, 0xaaf2, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff66, 0xff6f, 0xff71, 0xff9d, 0xffa0, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x10340, 0x10342, 0x10349, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x10450, 0x1049d, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11183, 0x111b2, 0x111c1, 0x111c4, 0x11680, 0x116aa, 0x12000, 0x1236e, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f50, 0x1b000, 0x1b001, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Lo */ /* 'Lt': General Category */ static const OnigCodePoint CR_Lt[] = { 10, 0x01c5, 0x01c5, 0x01c8, 0x01c8, 0x01cb, 0x01cb, 0x01f2, 0x01f2, 0x1f88, 0x1f8f, 0x1f98, 0x1f9f, 0x1fa8, 0x1faf, 0x1fbc, 0x1fbc, 0x1fcc, 0x1fcc, 0x1ffc, 0x1ffc, }; /* CR_Lt */ /* 'Lu': General Category */ static const OnigCodePoint CR_Lu[] = { 608, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, 0x0130, 0x0130, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, 0x0147, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, 0x0178, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x0181, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0189, 0x018b, 0x018e, 0x0191, 0x0193, 0x0194, 0x0196, 0x0198, 0x019c, 0x019d, 0x019f, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, 0x01a9, 0x01a9, 0x01ac, 0x01ac, 0x01ae, 0x01af, 0x01b1, 0x01b3, 0x01b5, 0x01b5, 0x01b7, 0x01b8, 0x01bc, 0x01bc, 0x01c4, 0x01c4, 0x01c7, 0x01c7, 0x01ca, 0x01ca, 0x01cd, 0x01cd, 0x01cf, 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x01de, 0x01de, 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, 0x01f1, 0x01f1, 0x01f4, 0x01f4, 0x01f6, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, 0x0220, 0x0220, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, 0x0230, 0x0230, 0x0232, 0x0232, 0x023a, 0x023b, 0x023d, 0x023e, 0x0241, 0x0241, 0x0243, 0x0246, 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, 0x0370, 0x0370, 0x0372, 0x0372, 0x0376, 0x0376, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x038f, 0x0391, 0x03a1, 0x03a3, 0x03ab, 0x03cf, 0x03cf, 0x03d2, 0x03d4, 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, 0x03f4, 0x03f4, 0x03f7, 0x03f7, 0x03f9, 0x03fa, 0x03fd, 0x042f, 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, 0x0480, 0x0480, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, 0x04c0, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0514, 0x0516, 0x0516, 0x0518, 0x0518, 0x051a, 0x051a, 0x051c, 0x051c, 0x051e, 0x051e, 0x0520, 0x0520, 0x0522, 0x0522, 0x0524, 0x0524, 0x0526, 0x0526, 0x0531, 0x0556, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1e00, 0x1e00, 0x1e02, 0x1e02, 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, 0x1e94, 0x1e94, 0x1e9e, 0x1e9e, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efa, 0x1efc, 0x1efc, 0x1efe, 0x1efe, 0x1f08, 0x1f0f, 0x1f18, 0x1f1d, 0x1f28, 0x1f2f, 0x1f38, 0x1f3f, 0x1f48, 0x1f4d, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f5f, 0x1f68, 0x1f6f, 0x1fb8, 0x1fbb, 0x1fc8, 0x1fcb, 0x1fd8, 0x1fdb, 0x1fe8, 0x1fec, 0x1ff8, 0x1ffb, 0x2102, 0x2102, 0x2107, 0x2107, 0x210b, 0x210d, 0x2110, 0x2112, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x2130, 0x2133, 0x213e, 0x213f, 0x2145, 0x2145, 0x2183, 0x2183, 0x2c00, 0x2c2e, 0x2c60, 0x2c60, 0x2c62, 0x2c64, 0x2c67, 0x2c67, 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c70, 0x2c72, 0x2c72, 0x2c75, 0x2c75, 0x2c7e, 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, 0x2ce0, 0x2ce2, 0x2ce2, 0x2ceb, 0x2ceb, 0x2ced, 0x2ced, 0x2cf2, 0x2cf2, 0xa640, 0xa640, 0xa642, 0xa642, 0xa644, 0xa644, 0xa646, 0xa646, 0xa648, 0xa648, 0xa64a, 0xa64a, 0xa64c, 0xa64c, 0xa64e, 0xa64e, 0xa650, 0xa650, 0xa652, 0xa652, 0xa654, 0xa654, 0xa656, 0xa656, 0xa658, 0xa658, 0xa65a, 0xa65a, 0xa65c, 0xa65c, 0xa65e, 0xa65e, 0xa660, 0xa660, 0xa662, 0xa662, 0xa664, 0xa664, 0xa666, 0xa666, 0xa668, 0xa668, 0xa66a, 0xa66a, 0xa66c, 0xa66c, 0xa680, 0xa680, 0xa682, 0xa682, 0xa684, 0xa684, 0xa686, 0xa686, 0xa688, 0xa688, 0xa68a, 0xa68a, 0xa68c, 0xa68c, 0xa68e, 0xa68e, 0xa690, 0xa690, 0xa692, 0xa692, 0xa694, 0xa694, 0xa696, 0xa696, 0xa722, 0xa722, 0xa724, 0xa724, 0xa726, 0xa726, 0xa728, 0xa728, 0xa72a, 0xa72a, 0xa72c, 0xa72c, 0xa72e, 0xa72e, 0xa732, 0xa732, 0xa734, 0xa734, 0xa736, 0xa736, 0xa738, 0xa738, 0xa73a, 0xa73a, 0xa73c, 0xa73c, 0xa73e, 0xa73e, 0xa740, 0xa740, 0xa742, 0xa742, 0xa744, 0xa744, 0xa746, 0xa746, 0xa748, 0xa748, 0xa74a, 0xa74a, 0xa74c, 0xa74c, 0xa74e, 0xa74e, 0xa750, 0xa750, 0xa752, 0xa752, 0xa754, 0xa754, 0xa756, 0xa756, 0xa758, 0xa758, 0xa75a, 0xa75a, 0xa75c, 0xa75c, 0xa75e, 0xa75e, 0xa760, 0xa760, 0xa762, 0xa762, 0xa764, 0xa764, 0xa766, 0xa766, 0xa768, 0xa768, 0xa76a, 0xa76a, 0xa76c, 0xa76c, 0xa76e, 0xa76e, 0xa779, 0xa779, 0xa77b, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa780, 0xa782, 0xa782, 0xa784, 0xa784, 0xa786, 0xa786, 0xa78b, 0xa78b, 0xa78d, 0xa78d, 0xa790, 0xa790, 0xa792, 0xa792, 0xa7a0, 0xa7a0, 0xa7a2, 0xa7a2, 0xa7a4, 0xa7a4, 0xa7a6, 0xa7a6, 0xa7a8, 0xa7a8, 0xa7aa, 0xa7aa, 0xff21, 0xff3a, 0x10400, 0x10427, 0x1d400, 0x1d419, 0x1d434, 0x1d44d, 0x1d468, 0x1d481, 0x1d49c, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b5, 0x1d4d0, 0x1d4e9, 0x1d504, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d538, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d56c, 0x1d585, 0x1d5a0, 0x1d5b9, 0x1d5d4, 0x1d5ed, 0x1d608, 0x1d621, 0x1d63c, 0x1d655, 0x1d670, 0x1d689, 0x1d6a8, 0x1d6c0, 0x1d6e2, 0x1d6fa, 0x1d71c, 0x1d734, 0x1d756, 0x1d76e, 0x1d790, 0x1d7a8, 0x1d7ca, 0x1d7ca, }; /* CR_Lu */ /* 'M': Major Category */ static const OnigCodePoint CR_M[] = { 204, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x0610, 0x061a, 0x064b, 0x065f, 0x0670, 0x0670, 0x06d6, 0x06dc, 0x06df, 0x06e4, 0x06e7, 0x06e8, 0x06ea, 0x06ed, 0x0711, 0x0711, 0x0730, 0x074a, 0x07a6, 0x07b0, 0x07eb, 0x07f3, 0x0816, 0x0819, 0x081b, 0x0823, 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, 0x08e4, 0x08fe, 0x0900, 0x0903, 0x093a, 0x093c, 0x093e, 0x094f, 0x0951, 0x0957, 0x0962, 0x0963, 0x0981, 0x0983, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09e2, 0x09e3, 0x0a01, 0x0a03, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a70, 0x0a71, 0x0a75, 0x0a75, 0x0a81, 0x0a83, 0x0abc, 0x0abc, 0x0abe, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ae2, 0x0ae3, 0x0b01, 0x0b03, 0x0b3c, 0x0b3c, 0x0b3e, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0c01, 0x0c03, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c62, 0x0c63, 0x0c82, 0x0c83, 0x0cbc, 0x0cbc, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0ce2, 0x0ce3, 0x0d02, 0x0d03, 0x0d3e, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d62, 0x0d63, 0x0d82, 0x0d83, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e31, 0x0e31, 0x0e34, 0x0e3a, 0x0e47, 0x0e4e, 0x0eb1, 0x0eb1, 0x0eb4, 0x0eb9, 0x0ebb, 0x0ebc, 0x0ec8, 0x0ecd, 0x0f18, 0x0f19, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f3e, 0x0f3f, 0x0f71, 0x0f84, 0x0f86, 0x0f87, 0x0f8d, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x102b, 0x103e, 0x1056, 0x1059, 0x105e, 0x1060, 0x1062, 0x1064, 0x1067, 0x106d, 0x1071, 0x1074, 0x1082, 0x108d, 0x108f, 0x108f, 0x109a, 0x109d, 0x135d, 0x135f, 0x1712, 0x1714, 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17d3, 0x17dd, 0x17dd, 0x180b, 0x180d, 0x18a9, 0x18a9, 0x1920, 0x192b, 0x1930, 0x193b, 0x19b0, 0x19c0, 0x19c8, 0x19c9, 0x1a17, 0x1a1b, 0x1a55, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a7f, 0x1b00, 0x1b04, 0x1b34, 0x1b44, 0x1b6b, 0x1b73, 0x1b80, 0x1b82, 0x1ba1, 0x1bad, 0x1be6, 0x1bf3, 0x1c24, 0x1c37, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce8, 0x1ced, 0x1ced, 0x1cf2, 0x1cf4, 0x1dc0, 0x1de6, 0x1dfc, 0x1dff, 0x20d0, 0x20f0, 0x2cef, 0x2cf1, 0x2d7f, 0x2d7f, 0x2de0, 0x2dff, 0x302a, 0x302f, 0x3099, 0x309a, 0xa66f, 0xa672, 0xa674, 0xa67d, 0xa69f, 0xa69f, 0xa6f0, 0xa6f1, 0xa802, 0xa802, 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa823, 0xa827, 0xa880, 0xa881, 0xa8b4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa926, 0xa92d, 0xa947, 0xa953, 0xa980, 0xa983, 0xa9b3, 0xa9c0, 0xaa29, 0xaa36, 0xaa43, 0xaa43, 0xaa4c, 0xaa4d, 0xaa7b, 0xaa7b, 0xaab0, 0xaab0, 0xaab2, 0xaab4, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xaac1, 0xaaeb, 0xaaef, 0xaaf5, 0xaaf6, 0xabe3, 0xabea, 0xabec, 0xabed, 0xfb1e, 0xfb1e, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0x101fd, 0x101fd, 0x10a01, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x11000, 0x11002, 0x11038, 0x11046, 0x11080, 0x11082, 0x110b0, 0x110ba, 0x11100, 0x11102, 0x11127, 0x11134, 0x11180, 0x11182, 0x111b3, 0x111c0, 0x116ab, 0x116b7, 0x16f51, 0x16f7e, 0x16f8f, 0x16f92, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0xe0100, 0xe01ef, }; /* CR_M */ /* 'Mc': General Category */ static const OnigCodePoint CR_Mc[] = { 126, 0x0903, 0x0903, 0x093b, 0x093b, 0x093e, 0x0940, 0x0949, 0x094c, 0x094e, 0x094f, 0x0982, 0x0983, 0x09be, 0x09c0, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09d7, 0x09d7, 0x0a03, 0x0a03, 0x0a3e, 0x0a40, 0x0a83, 0x0a83, 0x0abe, 0x0ac0, 0x0ac9, 0x0ac9, 0x0acb, 0x0acc, 0x0b02, 0x0b03, 0x0b3e, 0x0b3e, 0x0b40, 0x0b40, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b57, 0x0b57, 0x0bbe, 0x0bbf, 0x0bc1, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd7, 0x0bd7, 0x0c01, 0x0c03, 0x0c41, 0x0c44, 0x0c82, 0x0c83, 0x0cbe, 0x0cbe, 0x0cc0, 0x0cc4, 0x0cc7, 0x0cc8, 0x0cca, 0x0ccb, 0x0cd5, 0x0cd6, 0x0d02, 0x0d03, 0x0d3e, 0x0d40, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d57, 0x0d57, 0x0d82, 0x0d83, 0x0dcf, 0x0dd1, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0f3e, 0x0f3f, 0x0f7f, 0x0f7f, 0x102b, 0x102c, 0x1031, 0x1031, 0x1038, 0x1038, 0x103b, 0x103c, 0x1056, 0x1057, 0x1062, 0x1064, 0x1067, 0x106d, 0x1083, 0x1084, 0x1087, 0x108c, 0x108f, 0x108f, 0x109a, 0x109c, 0x17b6, 0x17b6, 0x17be, 0x17c5, 0x17c7, 0x17c8, 0x1923, 0x1926, 0x1929, 0x192b, 0x1930, 0x1931, 0x1933, 0x1938, 0x19b0, 0x19c0, 0x19c8, 0x19c9, 0x1a19, 0x1a1b, 0x1a55, 0x1a55, 0x1a57, 0x1a57, 0x1a61, 0x1a61, 0x1a63, 0x1a64, 0x1a6d, 0x1a72, 0x1b04, 0x1b04, 0x1b35, 0x1b35, 0x1b3b, 0x1b3b, 0x1b3d, 0x1b41, 0x1b43, 0x1b44, 0x1b82, 0x1b82, 0x1ba1, 0x1ba1, 0x1ba6, 0x1ba7, 0x1baa, 0x1baa, 0x1bac, 0x1bad, 0x1be7, 0x1be7, 0x1bea, 0x1bec, 0x1bee, 0x1bee, 0x1bf2, 0x1bf3, 0x1c24, 0x1c2b, 0x1c34, 0x1c35, 0x1ce1, 0x1ce1, 0x1cf2, 0x1cf3, 0x302e, 0x302f, 0xa823, 0xa824, 0xa827, 0xa827, 0xa880, 0xa881, 0xa8b4, 0xa8c3, 0xa952, 0xa953, 0xa983, 0xa983, 0xa9b4, 0xa9b5, 0xa9ba, 0xa9bb, 0xa9bd, 0xa9c0, 0xaa2f, 0xaa30, 0xaa33, 0xaa34, 0xaa4d, 0xaa4d, 0xaa7b, 0xaa7b, 0xaaeb, 0xaaeb, 0xaaee, 0xaaef, 0xaaf5, 0xaaf5, 0xabe3, 0xabe4, 0xabe6, 0xabe7, 0xabe9, 0xabea, 0xabec, 0xabec, 0x11000, 0x11000, 0x11002, 0x11002, 0x11082, 0x11082, 0x110b0, 0x110b2, 0x110b7, 0x110b8, 0x1112c, 0x1112c, 0x11182, 0x11182, 0x111b3, 0x111b5, 0x111bf, 0x111c0, 0x116ac, 0x116ac, 0x116ae, 0x116af, 0x116b6, 0x116b6, 0x16f51, 0x16f7e, 0x1d165, 0x1d166, 0x1d16d, 0x1d172, }; /* CR_Mc */ /* 'Me': General Category */ static const OnigCodePoint CR_Me[] = { 4, 0x0488, 0x0489, 0x20dd, 0x20e0, 0x20e2, 0x20e4, 0xa670, 0xa672, }; /* CR_Me */ /* 'Mn': General Category */ static const OnigCodePoint CR_Mn[] = { 220, 0x0300, 0x036f, 0x0483, 0x0487, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x0610, 0x061a, 0x064b, 0x065f, 0x0670, 0x0670, 0x06d6, 0x06dc, 0x06df, 0x06e4, 0x06e7, 0x06e8, 0x06ea, 0x06ed, 0x0711, 0x0711, 0x0730, 0x074a, 0x07a6, 0x07b0, 0x07eb, 0x07f3, 0x0816, 0x0819, 0x081b, 0x0823, 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, 0x08e4, 0x08fe, 0x0900, 0x0902, 0x093a, 0x093a, 0x093c, 0x093c, 0x0941, 0x0948, 0x094d, 0x094d, 0x0951, 0x0957, 0x0962, 0x0963, 0x0981, 0x0981, 0x09bc, 0x09bc, 0x09c1, 0x09c4, 0x09cd, 0x09cd, 0x09e2, 0x09e3, 0x0a01, 0x0a02, 0x0a3c, 0x0a3c, 0x0a41, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a70, 0x0a71, 0x0a75, 0x0a75, 0x0a81, 0x0a82, 0x0abc, 0x0abc, 0x0ac1, 0x0ac5, 0x0ac7, 0x0ac8, 0x0acd, 0x0acd, 0x0ae2, 0x0ae3, 0x0b01, 0x0b01, 0x0b3c, 0x0b3c, 0x0b3f, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, 0x0b56, 0x0b56, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bc0, 0x0bc0, 0x0bcd, 0x0bcd, 0x0c3e, 0x0c40, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c62, 0x0c63, 0x0cbc, 0x0cbc, 0x0cbf, 0x0cbf, 0x0cc6, 0x0cc6, 0x0ccc, 0x0ccd, 0x0ce2, 0x0ce3, 0x0d41, 0x0d44, 0x0d4d, 0x0d4d, 0x0d62, 0x0d63, 0x0dca, 0x0dca, 0x0dd2, 0x0dd4, 0x0dd6, 0x0dd6, 0x0e31, 0x0e31, 0x0e34, 0x0e3a, 0x0e47, 0x0e4e, 0x0eb1, 0x0eb1, 0x0eb4, 0x0eb9, 0x0ebb, 0x0ebc, 0x0ec8, 0x0ecd, 0x0f18, 0x0f19, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f71, 0x0f7e, 0x0f80, 0x0f84, 0x0f86, 0x0f87, 0x0f8d, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x102d, 0x1030, 0x1032, 0x1037, 0x1039, 0x103a, 0x103d, 0x103e, 0x1058, 0x1059, 0x105e, 0x1060, 0x1071, 0x1074, 0x1082, 0x1082, 0x1085, 0x1086, 0x108d, 0x108d, 0x109d, 0x109d, 0x135d, 0x135f, 0x1712, 0x1714, 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17b5, 0x17b7, 0x17bd, 0x17c6, 0x17c6, 0x17c9, 0x17d3, 0x17dd, 0x17dd, 0x180b, 0x180d, 0x18a9, 0x18a9, 0x1920, 0x1922, 0x1927, 0x1928, 0x1932, 0x1932, 0x1939, 0x193b, 0x1a17, 0x1a18, 0x1a56, 0x1a56, 0x1a58, 0x1a5e, 0x1a60, 0x1a60, 0x1a62, 0x1a62, 0x1a65, 0x1a6c, 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, 0x1b00, 0x1b03, 0x1b34, 0x1b34, 0x1b36, 0x1b3a, 0x1b3c, 0x1b3c, 0x1b42, 0x1b42, 0x1b6b, 0x1b73, 0x1b80, 0x1b81, 0x1ba2, 0x1ba5, 0x1ba8, 0x1ba9, 0x1bab, 0x1bab, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, 0x1bef, 0x1bf1, 0x1c2c, 0x1c33, 0x1c36, 0x1c37, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce0, 0x1ce2, 0x1ce8, 0x1ced, 0x1ced, 0x1cf4, 0x1cf4, 0x1dc0, 0x1de6, 0x1dfc, 0x1dff, 0x20d0, 0x20dc, 0x20e1, 0x20e1, 0x20e5, 0x20f0, 0x2cef, 0x2cf1, 0x2d7f, 0x2d7f, 0x2de0, 0x2dff, 0x302a, 0x302d, 0x3099, 0x309a, 0xa66f, 0xa66f, 0xa674, 0xa67d, 0xa69f, 0xa69f, 0xa6f0, 0xa6f1, 0xa802, 0xa802, 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, 0xa8c4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa926, 0xa92d, 0xa947, 0xa951, 0xa980, 0xa982, 0xa9b3, 0xa9b3, 0xa9b6, 0xa9b9, 0xa9bc, 0xa9bc, 0xaa29, 0xaa2e, 0xaa31, 0xaa32, 0xaa35, 0xaa36, 0xaa43, 0xaa43, 0xaa4c, 0xaa4c, 0xaab0, 0xaab0, 0xaab2, 0xaab4, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xaac1, 0xaaec, 0xaaed, 0xaaf6, 0xaaf6, 0xabe5, 0xabe5, 0xabe8, 0xabe8, 0xabed, 0xabed, 0xfb1e, 0xfb1e, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0x101fd, 0x101fd, 0x10a01, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x11001, 0x11001, 0x11038, 0x11046, 0x11080, 0x11081, 0x110b3, 0x110b6, 0x110b9, 0x110ba, 0x11100, 0x11102, 0x11127, 0x1112b, 0x1112d, 0x11134, 0x11180, 0x11181, 0x111b6, 0x111be, 0x116ab, 0x116ab, 0x116ad, 0x116ad, 0x116b0, 0x116b5, 0x116b7, 0x116b7, 0x16f8f, 0x16f92, 0x1d167, 0x1d169, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0xe0100, 0xe01ef, }; /* CR_Mn */ /* 'N': Major Category */ static const OnigCodePoint CR_N[] = { 88, 0x0030, 0x0039, 0x00b2, 0x00b3, 0x00b9, 0x00b9, 0x00bc, 0x00be, 0x0660, 0x0669, 0x06f0, 0x06f9, 0x07c0, 0x07c9, 0x0966, 0x096f, 0x09e6, 0x09ef, 0x09f4, 0x09f9, 0x0a66, 0x0a6f, 0x0ae6, 0x0aef, 0x0b66, 0x0b6f, 0x0b72, 0x0b77, 0x0be6, 0x0bf2, 0x0c66, 0x0c6f, 0x0c78, 0x0c7e, 0x0ce6, 0x0cef, 0x0d66, 0x0d75, 0x0e50, 0x0e59, 0x0ed0, 0x0ed9, 0x0f20, 0x0f33, 0x1040, 0x1049, 0x1090, 0x1099, 0x1369, 0x137c, 0x16ee, 0x16f0, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1810, 0x1819, 0x1946, 0x194f, 0x19d0, 0x19da, 0x1a80, 0x1a89, 0x1a90, 0x1a99, 0x1b50, 0x1b59, 0x1bb0, 0x1bb9, 0x1c40, 0x1c49, 0x1c50, 0x1c59, 0x2070, 0x2070, 0x2074, 0x2079, 0x2080, 0x2089, 0x2150, 0x2182, 0x2185, 0x2189, 0x2460, 0x249b, 0x24ea, 0x24ff, 0x2776, 0x2793, 0x2cfd, 0x2cfd, 0x3007, 0x3007, 0x3021, 0x3029, 0x3038, 0x303a, 0x3192, 0x3195, 0x3220, 0x3229, 0x3248, 0x324f, 0x3251, 0x325f, 0x3280, 0x3289, 0x32b1, 0x32bf, 0xa620, 0xa629, 0xa6e6, 0xa6ef, 0xa830, 0xa835, 0xa8d0, 0xa8d9, 0xa900, 0xa909, 0xa9d0, 0xa9d9, 0xaa50, 0xaa59, 0xabf0, 0xabf9, 0xff10, 0xff19, 0x10107, 0x10133, 0x10140, 0x10178, 0x1018a, 0x1018a, 0x10320, 0x10323, 0x10341, 0x10341, 0x1034a, 0x1034a, 0x103d1, 0x103d5, 0x104a0, 0x104a9, 0x10858, 0x1085f, 0x10916, 0x1091b, 0x10a40, 0x10a47, 0x10a7d, 0x10a7e, 0x10b58, 0x10b5f, 0x10b78, 0x10b7f, 0x10e60, 0x10e7e, 0x11052, 0x1106f, 0x110f0, 0x110f9, 0x11136, 0x1113f, 0x111d0, 0x111d9, 0x116c0, 0x116c9, 0x12400, 0x12462, 0x1d360, 0x1d371, 0x1d7ce, 0x1d7ff, 0x1f100, 0x1f10a, }; /* CR_N */ /* 'Nd': General Category */ #define CR_Nd CR_Digit /* 'Nl': General Category */ static const OnigCodePoint CR_Nl[] = { 12, 0x16ee, 0x16f0, 0x2160, 0x2182, 0x2185, 0x2188, 0x3007, 0x3007, 0x3021, 0x3029, 0x3038, 0x303a, 0xa6e6, 0xa6ef, 0x10140, 0x10174, 0x10341, 0x10341, 0x1034a, 0x1034a, 0x103d1, 0x103d5, 0x12400, 0x12462, }; /* CR_Nl */ /* 'No': General Category */ static const OnigCodePoint CR_No[] = { 42, 0x00b2, 0x00b3, 0x00b9, 0x00b9, 0x00bc, 0x00be, 0x09f4, 0x09f9, 0x0b72, 0x0b77, 0x0bf0, 0x0bf2, 0x0c78, 0x0c7e, 0x0d70, 0x0d75, 0x0f2a, 0x0f33, 0x1369, 0x137c, 0x17f0, 0x17f9, 0x19da, 0x19da, 0x2070, 0x2070, 0x2074, 0x2079, 0x2080, 0x2089, 0x2150, 0x215f, 0x2189, 0x2189, 0x2460, 0x249b, 0x24ea, 0x24ff, 0x2776, 0x2793, 0x2cfd, 0x2cfd, 0x3192, 0x3195, 0x3220, 0x3229, 0x3248, 0x324f, 0x3251, 0x325f, 0x3280, 0x3289, 0x32b1, 0x32bf, 0xa830, 0xa835, 0x10107, 0x10133, 0x10175, 0x10178, 0x1018a, 0x1018a, 0x10320, 0x10323, 0x10858, 0x1085f, 0x10916, 0x1091b, 0x10a40, 0x10a47, 0x10a7d, 0x10a7e, 0x10b58, 0x10b5f, 0x10b78, 0x10b7f, 0x10e60, 0x10e7e, 0x11052, 0x11065, 0x1d360, 0x1d371, 0x1f100, 0x1f10a, }; /* CR_No */ /* 'P': Major Category */ #define CR_P CR_Punct /* 'Pc': General Category */ static const OnigCodePoint CR_Pc[] = { 6, 0x005f, 0x005f, 0x203f, 0x2040, 0x2054, 0x2054, 0xfe33, 0xfe34, 0xfe4d, 0xfe4f, 0xff3f, 0xff3f, }; /* CR_Pc */ /* 'Pd': General Category */ static const OnigCodePoint CR_Pd[] = { 16, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, 0x1400, 0x1400, 0x1806, 0x1806, 0x2010, 0x2015, 0x2e17, 0x2e17, 0x2e1a, 0x2e1a, 0x2e3a, 0x2e3b, 0x301c, 0x301c, 0x3030, 0x3030, 0x30a0, 0x30a0, 0xfe31, 0xfe32, 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, }; /* CR_Pd */ /* 'Pe': General Category */ static const OnigCodePoint CR_Pe[] = { 70, 0x0029, 0x0029, 0x005d, 0x005d, 0x007d, 0x007d, 0x0f3b, 0x0f3b, 0x0f3d, 0x0f3d, 0x169c, 0x169c, 0x2046, 0x2046, 0x207e, 0x207e, 0x208e, 0x208e, 0x232a, 0x232a, 0x2769, 0x2769, 0x276b, 0x276b, 0x276d, 0x276d, 0x276f, 0x276f, 0x2771, 0x2771, 0x2773, 0x2773, 0x2775, 0x2775, 0x27c6, 0x27c6, 0x27e7, 0x27e7, 0x27e9, 0x27e9, 0x27eb, 0x27eb, 0x27ed, 0x27ed, 0x27ef, 0x27ef, 0x2984, 0x2984, 0x2986, 0x2986, 0x2988, 0x2988, 0x298a, 0x298a, 0x298c, 0x298c, 0x298e, 0x298e, 0x2990, 0x2990, 0x2992, 0x2992, 0x2994, 0x2994, 0x2996, 0x2996, 0x2998, 0x2998, 0x29d9, 0x29d9, 0x29db, 0x29db, 0x29fd, 0x29fd, 0x2e23, 0x2e23, 0x2e25, 0x2e25, 0x2e27, 0x2e27, 0x2e29, 0x2e29, 0x3009, 0x3009, 0x300b, 0x300b, 0x300d, 0x300d, 0x300f, 0x300f, 0x3011, 0x3011, 0x3015, 0x3015, 0x3017, 0x3017, 0x3019, 0x3019, 0x301b, 0x301b, 0x301e, 0x301f, 0xfd3f, 0xfd3f, 0xfe18, 0xfe18, 0xfe36, 0xfe36, 0xfe38, 0xfe38, 0xfe3a, 0xfe3a, 0xfe3c, 0xfe3c, 0xfe3e, 0xfe3e, 0xfe40, 0xfe40, 0xfe42, 0xfe42, 0xfe44, 0xfe44, 0xfe48, 0xfe48, 0xfe5a, 0xfe5a, 0xfe5c, 0xfe5c, 0xfe5e, 0xfe5e, 0xff09, 0xff09, 0xff3d, 0xff3d, 0xff5d, 0xff5d, 0xff60, 0xff60, 0xff63, 0xff63, }; /* CR_Pe */ /* 'Pf': General Category */ static const OnigCodePoint CR_Pf[] = { 10, 0x00bb, 0x00bb, 0x2019, 0x2019, 0x201d, 0x201d, 0x203a, 0x203a, 0x2e03, 0x2e03, 0x2e05, 0x2e05, 0x2e0a, 0x2e0a, 0x2e0d, 0x2e0d, 0x2e1d, 0x2e1d, 0x2e21, 0x2e21, }; /* CR_Pf */ /* 'Pi': General Category */ static const OnigCodePoint CR_Pi[] = { 11, 0x00ab, 0x00ab, 0x2018, 0x2018, 0x201b, 0x201c, 0x201f, 0x201f, 0x2039, 0x2039, 0x2e02, 0x2e02, 0x2e04, 0x2e04, 0x2e09, 0x2e09, 0x2e0c, 0x2e0c, 0x2e1c, 0x2e1c, 0x2e20, 0x2e20, }; /* CR_Pi */ /* 'Po': General Category */ static const OnigCodePoint CR_Po[] = { 135, 0x0021, 0x0023, 0x0025, 0x0027, 0x002a, 0x002a, 0x002c, 0x002c, 0x002e, 0x002f, 0x003a, 0x003b, 0x003f, 0x0040, 0x005c, 0x005c, 0x00a1, 0x00a1, 0x00a7, 0x00a7, 0x00b6, 0x00b7, 0x00bf, 0x00bf, 0x037e, 0x037e, 0x0387, 0x0387, 0x055a, 0x055f, 0x0589, 0x0589, 0x05c0, 0x05c0, 0x05c3, 0x05c3, 0x05c6, 0x05c6, 0x05f3, 0x05f4, 0x0609, 0x060a, 0x060c, 0x060d, 0x061b, 0x061b, 0x061e, 0x061f, 0x066a, 0x066d, 0x06d4, 0x06d4, 0x0700, 0x070d, 0x07f7, 0x07f9, 0x0830, 0x083e, 0x085e, 0x085e, 0x0964, 0x0965, 0x0970, 0x0970, 0x0af0, 0x0af0, 0x0df4, 0x0df4, 0x0e4f, 0x0e4f, 0x0e5a, 0x0e5b, 0x0f04, 0x0f12, 0x0f14, 0x0f14, 0x0f85, 0x0f85, 0x0fd0, 0x0fd4, 0x0fd9, 0x0fda, 0x104a, 0x104f, 0x10fb, 0x10fb, 0x1360, 0x1368, 0x166d, 0x166e, 0x16eb, 0x16ed, 0x1735, 0x1736, 0x17d4, 0x17d6, 0x17d8, 0x17da, 0x1800, 0x1805, 0x1807, 0x180a, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa6, 0x1aa8, 0x1aad, 0x1b5a, 0x1b60, 0x1bfc, 0x1bff, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd3, 0x1cd3, 0x2016, 0x2017, 0x2020, 0x2027, 0x2030, 0x2038, 0x203b, 0x203e, 0x2041, 0x2043, 0x2047, 0x2051, 0x2053, 0x2053, 0x2055, 0x205e, 0x2cf9, 0x2cfc, 0x2cfe, 0x2cff, 0x2d70, 0x2d70, 0x2e00, 0x2e01, 0x2e06, 0x2e08, 0x2e0b, 0x2e0b, 0x2e0e, 0x2e16, 0x2e18, 0x2e19, 0x2e1b, 0x2e1b, 0x2e1e, 0x2e1f, 0x2e2a, 0x2e2e, 0x2e30, 0x2e39, 0x3001, 0x3003, 0x303d, 0x303d, 0x30fb, 0x30fb, 0xa4fe, 0xa4ff, 0xa60d, 0xa60f, 0xa673, 0xa673, 0xa67e, 0xa67e, 0xa6f2, 0xa6f7, 0xa874, 0xa877, 0xa8ce, 0xa8cf, 0xa8f8, 0xa8fa, 0xa92e, 0xa92f, 0xa95f, 0xa95f, 0xa9c1, 0xa9cd, 0xa9de, 0xa9df, 0xaa5c, 0xaa5f, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, 0xfe10, 0xfe16, 0xfe19, 0xfe19, 0xfe30, 0xfe30, 0xfe45, 0xfe46, 0xfe49, 0xfe4c, 0xfe50, 0xfe52, 0xfe54, 0xfe57, 0xfe5f, 0xfe61, 0xfe68, 0xfe68, 0xfe6a, 0xfe6b, 0xff01, 0xff03, 0xff05, 0xff07, 0xff0a, 0xff0a, 0xff0c, 0xff0c, 0xff0e, 0xff0f, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3c, 0xff3c, 0xff61, 0xff61, 0xff64, 0xff65, 0x10100, 0x10102, 0x1039f, 0x1039f, 0x103d0, 0x103d0, 0x10857, 0x10857, 0x1091f, 0x1091f, 0x1093f, 0x1093f, 0x10a50, 0x10a58, 0x10a7f, 0x10a7f, 0x10b39, 0x10b3f, 0x11047, 0x1104d, 0x110bb, 0x110bc, 0x110be, 0x110c1, 0x11140, 0x11143, 0x111c5, 0x111c8, 0x12470, 0x12473, }; /* CR_Po */ /* 'Ps': General Category */ static const OnigCodePoint CR_Ps[] = { 72, 0x0028, 0x0028, 0x005b, 0x005b, 0x007b, 0x007b, 0x0f3a, 0x0f3a, 0x0f3c, 0x0f3c, 0x169b, 0x169b, 0x201a, 0x201a, 0x201e, 0x201e, 0x2045, 0x2045, 0x207d, 0x207d, 0x208d, 0x208d, 0x2329, 0x2329, 0x2768, 0x2768, 0x276a, 0x276a, 0x276c, 0x276c, 0x276e, 0x276e, 0x2770, 0x2770, 0x2772, 0x2772, 0x2774, 0x2774, 0x27c5, 0x27c5, 0x27e6, 0x27e6, 0x27e8, 0x27e8, 0x27ea, 0x27ea, 0x27ec, 0x27ec, 0x27ee, 0x27ee, 0x2983, 0x2983, 0x2985, 0x2985, 0x2987, 0x2987, 0x2989, 0x2989, 0x298b, 0x298b, 0x298d, 0x298d, 0x298f, 0x298f, 0x2991, 0x2991, 0x2993, 0x2993, 0x2995, 0x2995, 0x2997, 0x2997, 0x29d8, 0x29d8, 0x29da, 0x29da, 0x29fc, 0x29fc, 0x2e22, 0x2e22, 0x2e24, 0x2e24, 0x2e26, 0x2e26, 0x2e28, 0x2e28, 0x3008, 0x3008, 0x300a, 0x300a, 0x300c, 0x300c, 0x300e, 0x300e, 0x3010, 0x3010, 0x3014, 0x3014, 0x3016, 0x3016, 0x3018, 0x3018, 0x301a, 0x301a, 0x301d, 0x301d, 0xfd3e, 0xfd3e, 0xfe17, 0xfe17, 0xfe35, 0xfe35, 0xfe37, 0xfe37, 0xfe39, 0xfe39, 0xfe3b, 0xfe3b, 0xfe3d, 0xfe3d, 0xfe3f, 0xfe3f, 0xfe41, 0xfe41, 0xfe43, 0xfe43, 0xfe47, 0xfe47, 0xfe59, 0xfe59, 0xfe5b, 0xfe5b, 0xfe5d, 0xfe5d, 0xff08, 0xff08, 0xff3b, 0xff3b, 0xff5b, 0xff5b, 0xff5f, 0xff5f, 0xff62, 0xff62, }; /* CR_Ps */ /* 'S': Major Category */ static const OnigCodePoint CR_S[] = { 198, 0x0024, 0x0024, 0x002b, 0x002b, 0x003c, 0x003e, 0x005e, 0x005e, 0x0060, 0x0060, 0x007c, 0x007c, 0x007e, 0x007e, 0x00a2, 0x00a6, 0x00a8, 0x00a9, 0x00ac, 0x00ac, 0x00ae, 0x00b1, 0x00b4, 0x00b4, 0x00b8, 0x00b8, 0x00d7, 0x00d7, 0x00f7, 0x00f7, 0x02c2, 0x02c5, 0x02d2, 0x02df, 0x02e5, 0x02eb, 0x02ed, 0x02ed, 0x02ef, 0x02ff, 0x0375, 0x0375, 0x0384, 0x0385, 0x03f6, 0x03f6, 0x0482, 0x0482, 0x058f, 0x058f, 0x0606, 0x0608, 0x060b, 0x060b, 0x060e, 0x060f, 0x06de, 0x06de, 0x06e9, 0x06e9, 0x06fd, 0x06fe, 0x07f6, 0x07f6, 0x09f2, 0x09f3, 0x09fa, 0x09fb, 0x0af1, 0x0af1, 0x0b70, 0x0b70, 0x0bf3, 0x0bfa, 0x0c7f, 0x0c7f, 0x0d79, 0x0d79, 0x0e3f, 0x0e3f, 0x0f01, 0x0f03, 0x0f13, 0x0f13, 0x0f15, 0x0f17, 0x0f1a, 0x0f1f, 0x0f34, 0x0f34, 0x0f36, 0x0f36, 0x0f38, 0x0f38, 0x0fbe, 0x0fc5, 0x0fc7, 0x0fcc, 0x0fce, 0x0fcf, 0x0fd5, 0x0fd8, 0x109e, 0x109f, 0x1390, 0x1399, 0x17db, 0x17db, 0x1940, 0x1940, 0x19de, 0x19ff, 0x1b61, 0x1b6a, 0x1b74, 0x1b7c, 0x1fbd, 0x1fbd, 0x1fbf, 0x1fc1, 0x1fcd, 0x1fcf, 0x1fdd, 0x1fdf, 0x1fed, 0x1fef, 0x1ffd, 0x1ffe, 0x2044, 0x2044, 0x2052, 0x2052, 0x207a, 0x207c, 0x208a, 0x208c, 0x20a0, 0x20b9, 0x2100, 0x2101, 0x2103, 0x2106, 0x2108, 0x2109, 0x2114, 0x2114, 0x2116, 0x2118, 0x211e, 0x2123, 0x2125, 0x2125, 0x2127, 0x2127, 0x2129, 0x2129, 0x212e, 0x212e, 0x213a, 0x213b, 0x2140, 0x2144, 0x214a, 0x214d, 0x214f, 0x214f, 0x2190, 0x2328, 0x232b, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x249c, 0x24e9, 0x2500, 0x26ff, 0x2701, 0x2767, 0x2794, 0x27c4, 0x27c7, 0x27e5, 0x27f0, 0x2982, 0x2999, 0x29d7, 0x29dc, 0x29fb, 0x29fe, 0x2b4c, 0x2b50, 0x2b59, 0x2ce5, 0x2cea, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3004, 0x3004, 0x3012, 0x3013, 0x3020, 0x3020, 0x3036, 0x3037, 0x303e, 0x303f, 0x309b, 0x309c, 0x3190, 0x3191, 0x3196, 0x319f, 0x31c0, 0x31e3, 0x3200, 0x321e, 0x322a, 0x3247, 0x3250, 0x3250, 0x3260, 0x327f, 0x328a, 0x32b0, 0x32c0, 0x32fe, 0x3300, 0x33ff, 0x4dc0, 0x4dff, 0xa490, 0xa4c6, 0xa700, 0xa716, 0xa720, 0xa721, 0xa789, 0xa78a, 0xa828, 0xa82b, 0xa836, 0xa839, 0xaa77, 0xaa79, 0xfb29, 0xfb29, 0xfbb2, 0xfbc1, 0xfdfc, 0xfdfd, 0xfe62, 0xfe62, 0xfe64, 0xfe66, 0xfe69, 0xfe69, 0xff04, 0xff04, 0xff0b, 0xff0b, 0xff1c, 0xff1e, 0xff3e, 0xff3e, 0xff40, 0xff40, 0xff5c, 0xff5c, 0xff5e, 0xff5e, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfffc, 0xfffd, 0x10137, 0x1013f, 0x10179, 0x10189, 0x10190, 0x1019b, 0x101d0, 0x101fc, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d164, 0x1d16a, 0x1d16c, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1dd, 0x1d200, 0x1d241, 0x1d245, 0x1d245, 0x1d300, 0x1d356, 0x1d6c1, 0x1d6c1, 0x1d6db, 0x1d6db, 0x1d6fb, 0x1d6fb, 0x1d715, 0x1d715, 0x1d735, 0x1d735, 0x1d74f, 0x1d74f, 0x1d76f, 0x1d76f, 0x1d789, 0x1d789, 0x1d7a9, 0x1d7a9, 0x1d7c3, 0x1d7c3, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, }; /* CR_S */ /* 'Sc': General Category */ static const OnigCodePoint CR_Sc[] = { 17, 0x0024, 0x0024, 0x00a2, 0x00a5, 0x058f, 0x058f, 0x060b, 0x060b, 0x09f2, 0x09f3, 0x09fb, 0x09fb, 0x0af1, 0x0af1, 0x0bf9, 0x0bf9, 0x0e3f, 0x0e3f, 0x17db, 0x17db, 0x20a0, 0x20b9, 0xa838, 0xa838, 0xfdfc, 0xfdfc, 0xfe69, 0xfe69, 0xff04, 0xff04, 0xffe0, 0xffe1, 0xffe5, 0xffe6, }; /* CR_Sc */ /* 'Sk': General Category */ static const OnigCodePoint CR_Sk[] = { 27, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, 0x00af, 0x00af, 0x00b4, 0x00b4, 0x00b8, 0x00b8, 0x02c2, 0x02c5, 0x02d2, 0x02df, 0x02e5, 0x02eb, 0x02ed, 0x02ed, 0x02ef, 0x02ff, 0x0375, 0x0375, 0x0384, 0x0385, 0x1fbd, 0x1fbd, 0x1fbf, 0x1fc1, 0x1fcd, 0x1fcf, 0x1fdd, 0x1fdf, 0x1fed, 0x1fef, 0x1ffd, 0x1ffe, 0x309b, 0x309c, 0xa700, 0xa716, 0xa720, 0xa721, 0xa789, 0xa78a, 0xfbb2, 0xfbc1, 0xff3e, 0xff3e, 0xff40, 0xff40, 0xffe3, 0xffe3, }; /* CR_Sk */ /* 'Sm': General Category */ static const OnigCodePoint CR_Sm[] = { 65, 0x002b, 0x002b, 0x003c, 0x003e, 0x007c, 0x007c, 0x007e, 0x007e, 0x00ac, 0x00ac, 0x00b1, 0x00b1, 0x00d7, 0x00d7, 0x00f7, 0x00f7, 0x03f6, 0x03f6, 0x0606, 0x0608, 0x2044, 0x2044, 0x2052, 0x2052, 0x207a, 0x207c, 0x208a, 0x208c, 0x2118, 0x2118, 0x2140, 0x2144, 0x214b, 0x214b, 0x2190, 0x2194, 0x219a, 0x219b, 0x21a0, 0x21a0, 0x21a3, 0x21a3, 0x21a6, 0x21a6, 0x21ae, 0x21ae, 0x21ce, 0x21cf, 0x21d2, 0x21d2, 0x21d4, 0x21d4, 0x21f4, 0x22ff, 0x2308, 0x230b, 0x2320, 0x2321, 0x237c, 0x237c, 0x239b, 0x23b3, 0x23dc, 0x23e1, 0x25b7, 0x25b7, 0x25c1, 0x25c1, 0x25f8, 0x25ff, 0x266f, 0x266f, 0x27c0, 0x27c4, 0x27c7, 0x27e5, 0x27f0, 0x27ff, 0x2900, 0x2982, 0x2999, 0x29d7, 0x29dc, 0x29fb, 0x29fe, 0x2aff, 0x2b30, 0x2b44, 0x2b47, 0x2b4c, 0xfb29, 0xfb29, 0xfe62, 0xfe62, 0xfe64, 0xfe66, 0xff0b, 0xff0b, 0xff1c, 0xff1e, 0xff5c, 0xff5c, 0xff5e, 0xff5e, 0xffe2, 0xffe2, 0xffe9, 0xffec, 0x1d6c1, 0x1d6c1, 0x1d6db, 0x1d6db, 0x1d6fb, 0x1d6fb, 0x1d715, 0x1d715, 0x1d735, 0x1d735, 0x1d74f, 0x1d74f, 0x1d76f, 0x1d76f, 0x1d789, 0x1d789, 0x1d7a9, 0x1d7a9, 0x1d7c3, 0x1d7c3, 0x1eef0, 0x1eef1, }; /* CR_Sm */ /* 'So': General Category */ static const OnigCodePoint CR_So[] = { 153, 0x00a6, 0x00a6, 0x00a9, 0x00a9, 0x00ae, 0x00ae, 0x00b0, 0x00b0, 0x0482, 0x0482, 0x060e, 0x060f, 0x06de, 0x06de, 0x06e9, 0x06e9, 0x06fd, 0x06fe, 0x07f6, 0x07f6, 0x09fa, 0x09fa, 0x0b70, 0x0b70, 0x0bf3, 0x0bf8, 0x0bfa, 0x0bfa, 0x0c7f, 0x0c7f, 0x0d79, 0x0d79, 0x0f01, 0x0f03, 0x0f13, 0x0f13, 0x0f15, 0x0f17, 0x0f1a, 0x0f1f, 0x0f34, 0x0f34, 0x0f36, 0x0f36, 0x0f38, 0x0f38, 0x0fbe, 0x0fc5, 0x0fc7, 0x0fcc, 0x0fce, 0x0fcf, 0x0fd5, 0x0fd8, 0x109e, 0x109f, 0x1390, 0x1399, 0x1940, 0x1940, 0x19de, 0x19ff, 0x1b61, 0x1b6a, 0x1b74, 0x1b7c, 0x2100, 0x2101, 0x2103, 0x2106, 0x2108, 0x2109, 0x2114, 0x2114, 0x2116, 0x2117, 0x211e, 0x2123, 0x2125, 0x2125, 0x2127, 0x2127, 0x2129, 0x2129, 0x212e, 0x212e, 0x213a, 0x213b, 0x214a, 0x214a, 0x214c, 0x214d, 0x214f, 0x214f, 0x2195, 0x2199, 0x219c, 0x219f, 0x21a1, 0x21a2, 0x21a4, 0x21a5, 0x21a7, 0x21ad, 0x21af, 0x21cd, 0x21d0, 0x21d1, 0x21d3, 0x21d3, 0x21d5, 0x21f3, 0x2300, 0x2307, 0x230c, 0x231f, 0x2322, 0x2328, 0x232b, 0x237b, 0x237d, 0x239a, 0x23b4, 0x23db, 0x23e2, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x249c, 0x24e9, 0x2500, 0x25b6, 0x25b8, 0x25c0, 0x25c2, 0x25f7, 0x2600, 0x266e, 0x2670, 0x26ff, 0x2701, 0x2767, 0x2794, 0x27bf, 0x2800, 0x28ff, 0x2b00, 0x2b2f, 0x2b45, 0x2b46, 0x2b50, 0x2b59, 0x2ce5, 0x2cea, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3004, 0x3004, 0x3012, 0x3013, 0x3020, 0x3020, 0x3036, 0x3037, 0x303e, 0x303f, 0x3190, 0x3191, 0x3196, 0x319f, 0x31c0, 0x31e3, 0x3200, 0x321e, 0x322a, 0x3247, 0x3250, 0x3250, 0x3260, 0x327f, 0x328a, 0x32b0, 0x32c0, 0x32fe, 0x3300, 0x33ff, 0x4dc0, 0x4dff, 0xa490, 0xa4c6, 0xa828, 0xa82b, 0xa836, 0xa837, 0xa839, 0xa839, 0xaa77, 0xaa79, 0xfdfd, 0xfdfd, 0xffe4, 0xffe4, 0xffe8, 0xffe8, 0xffed, 0xffee, 0xfffc, 0xfffd, 0x10137, 0x1013f, 0x10179, 0x10189, 0x10190, 0x1019b, 0x101d0, 0x101fc, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d164, 0x1d16a, 0x1d16c, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1dd, 0x1d200, 0x1d241, 0x1d245, 0x1d245, 0x1d300, 0x1d356, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, }; /* CR_So */ /* 'Z': Major Category */ static const OnigCodePoint CR_Z[] = { 9, 0x0020, 0x0020, 0x00a0, 0x00a0, 0x1680, 0x1680, 0x180e, 0x180e, 0x2000, 0x200a, 0x2028, 0x2029, 0x202f, 0x202f, 0x205f, 0x205f, 0x3000, 0x3000, }; /* CR_Z */ /* 'Zl': General Category */ static const OnigCodePoint CR_Zl[] = { 1, 0x2028, 0x2028, }; /* CR_Zl */ /* 'Zp': General Category */ static const OnigCodePoint CR_Zp[] = { 1, 0x2029, 0x2029, }; /* CR_Zp */ /* 'Zs': General Category */ static const OnigCodePoint CR_Zs[] = { 8, 0x0020, 0x0020, 0x00a0, 0x00a0, 0x1680, 0x1680, 0x180e, 0x180e, 0x2000, 0x200a, 0x202f, 0x202f, 0x205f, 0x205f, 0x3000, 0x3000, }; /* CR_Zs */ /* 'Math': Derived Property */ static const OnigCodePoint CR_Math[] = { 138, 0x002b, 0x002b, 0x003c, 0x003e, 0x005e, 0x005e, 0x007c, 0x007c, 0x007e, 0x007e, 0x00ac, 0x00ac, 0x00b1, 0x00b1, 0x00d7, 0x00d7, 0x00f7, 0x00f7, 0x03d0, 0x03d2, 0x03d5, 0x03d5, 0x03f0, 0x03f1, 0x03f4, 0x03f6, 0x0606, 0x0608, 0x2016, 0x2016, 0x2032, 0x2034, 0x2040, 0x2040, 0x2044, 0x2044, 0x2052, 0x2052, 0x2061, 0x2064, 0x207a, 0x207e, 0x208a, 0x208e, 0x20d0, 0x20dc, 0x20e1, 0x20e1, 0x20e5, 0x20e6, 0x20eb, 0x20ef, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124, 0x2128, 0x2129, 0x212c, 0x212d, 0x212f, 0x2131, 0x2133, 0x2138, 0x213c, 0x2149, 0x214b, 0x214b, 0x2190, 0x21a7, 0x21a9, 0x21ae, 0x21b0, 0x21b1, 0x21b6, 0x21b7, 0x21bc, 0x21db, 0x21dd, 0x21dd, 0x21e4, 0x21e5, 0x21f4, 0x22ff, 0x2308, 0x230b, 0x2320, 0x2321, 0x237c, 0x237c, 0x239b, 0x23b5, 0x23b7, 0x23b7, 0x23d0, 0x23d0, 0x23dc, 0x23e2, 0x25a0, 0x25a1, 0x25ae, 0x25b7, 0x25bc, 0x25c1, 0x25c6, 0x25c7, 0x25ca, 0x25cb, 0x25cf, 0x25d3, 0x25e2, 0x25e2, 0x25e4, 0x25e4, 0x25e7, 0x25ec, 0x25f8, 0x25ff, 0x2605, 0x2606, 0x2640, 0x2640, 0x2642, 0x2642, 0x2660, 0x2663, 0x266d, 0x266f, 0x27c0, 0x27ff, 0x2900, 0x2aff, 0x2b30, 0x2b44, 0x2b47, 0x2b4c, 0xfb29, 0xfb29, 0xfe61, 0xfe66, 0xfe68, 0xfe68, 0xff0b, 0xff0b, 0xff1c, 0xff1e, 0xff3c, 0xff3c, 0xff3e, 0xff3e, 0xff5c, 0xff5c, 0xff5e, 0xff5e, 0xffe2, 0xffe2, 0xffe9, 0xffec, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, }; /* CR_Math */ /* 'Alphabetic': Derived Property */ #define CR_Alphabetic CR_Alpha /* 'Lowercase': Derived Property */ #define CR_Lowercase CR_Lower /* 'Uppercase': Derived Property */ #define CR_Uppercase CR_Upper /* 'Cased': Derived Property */ static const OnigCodePoint CR_Cased[] = { 119, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x01ba, 0x01bc, 0x01bf, 0x01c4, 0x0293, 0x0295, 0x02b8, 0x02c0, 0x02c1, 0x02e0, 0x02e4, 0x0345, 0x0345, 0x0370, 0x0373, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0561, 0x0587, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x212d, 0x212f, 0x2134, 0x2139, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x217f, 0x2183, 0x2184, 0x24b6, 0x24e9, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa640, 0xa66d, 0xa680, 0xa697, 0xa722, 0xa787, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa7fa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff21, 0xff3a, 0xff41, 0xff5a, 0x10400, 0x1044f, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, }; /* CR_Cased */ /* 'Case_Ignorable': Derived Property */ static const OnigCodePoint CR_Case_Ignorable[] = { 295, 0x0027, 0x0027, 0x002e, 0x002e, 0x003a, 0x003a, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, 0x00ad, 0x00ad, 0x00af, 0x00af, 0x00b4, 0x00b4, 0x00b7, 0x00b8, 0x02b0, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x0384, 0x0385, 0x0387, 0x0387, 0x0483, 0x0489, 0x0559, 0x0559, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05f4, 0x05f4, 0x0600, 0x0604, 0x0610, 0x061a, 0x0640, 0x0640, 0x064b, 0x065f, 0x0670, 0x0670, 0x06d6, 0x06dd, 0x06df, 0x06e8, 0x06ea, 0x06ed, 0x070f, 0x070f, 0x0711, 0x0711, 0x0730, 0x074a, 0x07a6, 0x07b0, 0x07eb, 0x07f5, 0x07fa, 0x07fa, 0x0816, 0x082d, 0x0859, 0x085b, 0x08e4, 0x08fe, 0x0900, 0x0902, 0x093a, 0x093a, 0x093c, 0x093c, 0x0941, 0x0948, 0x094d, 0x094d, 0x0951, 0x0957, 0x0962, 0x0963, 0x0971, 0x0971, 0x0981, 0x0981, 0x09bc, 0x09bc, 0x09c1, 0x09c4, 0x09cd, 0x09cd, 0x09e2, 0x09e3, 0x0a01, 0x0a02, 0x0a3c, 0x0a3c, 0x0a41, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a70, 0x0a71, 0x0a75, 0x0a75, 0x0a81, 0x0a82, 0x0abc, 0x0abc, 0x0ac1, 0x0ac5, 0x0ac7, 0x0ac8, 0x0acd, 0x0acd, 0x0ae2, 0x0ae3, 0x0b01, 0x0b01, 0x0b3c, 0x0b3c, 0x0b3f, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, 0x0b56, 0x0b56, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bc0, 0x0bc0, 0x0bcd, 0x0bcd, 0x0c3e, 0x0c40, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c62, 0x0c63, 0x0cbc, 0x0cbc, 0x0cbf, 0x0cbf, 0x0cc6, 0x0cc6, 0x0ccc, 0x0ccd, 0x0ce2, 0x0ce3, 0x0d41, 0x0d44, 0x0d4d, 0x0d4d, 0x0d62, 0x0d63, 0x0dca, 0x0dca, 0x0dd2, 0x0dd4, 0x0dd6, 0x0dd6, 0x0e31, 0x0e31, 0x0e34, 0x0e3a, 0x0e46, 0x0e4e, 0x0eb1, 0x0eb1, 0x0eb4, 0x0eb9, 0x0ebb, 0x0ebc, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0f18, 0x0f19, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f71, 0x0f7e, 0x0f80, 0x0f84, 0x0f86, 0x0f87, 0x0f8d, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x102d, 0x1030, 0x1032, 0x1037, 0x1039, 0x103a, 0x103d, 0x103e, 0x1058, 0x1059, 0x105e, 0x1060, 0x1071, 0x1074, 0x1082, 0x1082, 0x1085, 0x1086, 0x108d, 0x108d, 0x109d, 0x109d, 0x10fc, 0x10fc, 0x135d, 0x135f, 0x1712, 0x1714, 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17b5, 0x17b7, 0x17bd, 0x17c6, 0x17c6, 0x17c9, 0x17d3, 0x17d7, 0x17d7, 0x17dd, 0x17dd, 0x180b, 0x180d, 0x1843, 0x1843, 0x18a9, 0x18a9, 0x1920, 0x1922, 0x1927, 0x1928, 0x1932, 0x1932, 0x1939, 0x193b, 0x1a17, 0x1a18, 0x1a56, 0x1a56, 0x1a58, 0x1a5e, 0x1a60, 0x1a60, 0x1a62, 0x1a62, 0x1a65, 0x1a6c, 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, 0x1aa7, 0x1aa7, 0x1b00, 0x1b03, 0x1b34, 0x1b34, 0x1b36, 0x1b3a, 0x1b3c, 0x1b3c, 0x1b42, 0x1b42, 0x1b6b, 0x1b73, 0x1b80, 0x1b81, 0x1ba2, 0x1ba5, 0x1ba8, 0x1ba9, 0x1bab, 0x1bab, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, 0x1bef, 0x1bf1, 0x1c2c, 0x1c33, 0x1c36, 0x1c37, 0x1c78, 0x1c7d, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce0, 0x1ce2, 0x1ce8, 0x1ced, 0x1ced, 0x1cf4, 0x1cf4, 0x1d2c, 0x1d6a, 0x1d78, 0x1d78, 0x1d9b, 0x1de6, 0x1dfc, 0x1dff, 0x1fbd, 0x1fbd, 0x1fbf, 0x1fc1, 0x1fcd, 0x1fcf, 0x1fdd, 0x1fdf, 0x1fed, 0x1fef, 0x1ffd, 0x1ffe, 0x200b, 0x200f, 0x2018, 0x2019, 0x2024, 0x2024, 0x2027, 0x2027, 0x202a, 0x202e, 0x2060, 0x2064, 0x206a, 0x206f, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x20d0, 0x20f0, 0x2c7c, 0x2c7d, 0x2cef, 0x2cf1, 0x2d6f, 0x2d6f, 0x2d7f, 0x2d7f, 0x2de0, 0x2dff, 0x2e2f, 0x2e2f, 0x3005, 0x3005, 0x302a, 0x302d, 0x3031, 0x3035, 0x303b, 0x303b, 0x3099, 0x309e, 0x30fc, 0x30fe, 0xa015, 0xa015, 0xa4f8, 0xa4fd, 0xa60c, 0xa60c, 0xa66f, 0xa672, 0xa674, 0xa67d, 0xa67f, 0xa67f, 0xa69f, 0xa69f, 0xa6f0, 0xa6f1, 0xa700, 0xa721, 0xa770, 0xa770, 0xa788, 0xa78a, 0xa7f8, 0xa7f9, 0xa802, 0xa802, 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, 0xa8c4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa926, 0xa92d, 0xa947, 0xa951, 0xa980, 0xa982, 0xa9b3, 0xa9b3, 0xa9b6, 0xa9b9, 0xa9bc, 0xa9bc, 0xa9cf, 0xa9cf, 0xaa29, 0xaa2e, 0xaa31, 0xaa32, 0xaa35, 0xaa36, 0xaa43, 0xaa43, 0xaa4c, 0xaa4c, 0xaa70, 0xaa70, 0xaab0, 0xaab0, 0xaab2, 0xaab4, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xaac1, 0xaadd, 0xaadd, 0xaaec, 0xaaed, 0xaaf3, 0xaaf4, 0xaaf6, 0xaaf6, 0xabe5, 0xabe5, 0xabe8, 0xabe8, 0xabed, 0xabed, 0xfb1e, 0xfb1e, 0xfbb2, 0xfbc1, 0xfe00, 0xfe0f, 0xfe13, 0xfe13, 0xfe20, 0xfe26, 0xfe52, 0xfe52, 0xfe55, 0xfe55, 0xfeff, 0xfeff, 0xff07, 0xff07, 0xff0e, 0xff0e, 0xff1a, 0xff1a, 0xff3e, 0xff3e, 0xff40, 0xff40, 0xff70, 0xff70, 0xff9e, 0xff9f, 0xffe3, 0xffe3, 0xfff9, 0xfffb, 0x101fd, 0x101fd, 0x10a01, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x11001, 0x11001, 0x11038, 0x11046, 0x11080, 0x11081, 0x110b3, 0x110b6, 0x110b9, 0x110ba, 0x110bd, 0x110bd, 0x11100, 0x11102, 0x11127, 0x1112b, 0x1112d, 0x11134, 0x11180, 0x11181, 0x111b6, 0x111be, 0x116ab, 0x116ab, 0x116ad, 0x116ad, 0x116b0, 0x116b5, 0x116b7, 0x116b7, 0x16f8f, 0x16f9f, 0x1d167, 0x1d169, 0x1d173, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, }; /* CR_Case_Ignorable */ /* 'Changes_When_Lowercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Lowercased[] = { 571, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, 0x0130, 0x0130, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, 0x0147, 0x014a, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, 0x0178, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x0181, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0189, 0x018b, 0x018e, 0x0191, 0x0193, 0x0194, 0x0196, 0x0198, 0x019c, 0x019d, 0x019f, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, 0x01a9, 0x01a9, 0x01ac, 0x01ac, 0x01ae, 0x01af, 0x01b1, 0x01b3, 0x01b5, 0x01b5, 0x01b7, 0x01b8, 0x01bc, 0x01bc, 0x01c4, 0x01c5, 0x01c7, 0x01c8, 0x01ca, 0x01cb, 0x01cd, 0x01cd, 0x01cf, 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x01de, 0x01de, 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, 0x01f1, 0x01f2, 0x01f4, 0x01f4, 0x01f6, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, 0x0220, 0x0220, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, 0x0230, 0x0230, 0x0232, 0x0232, 0x023a, 0x023b, 0x023d, 0x023e, 0x0241, 0x0241, 0x0243, 0x0246, 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, 0x0370, 0x0370, 0x0372, 0x0372, 0x0376, 0x0376, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x038f, 0x0391, 0x03a1, 0x03a3, 0x03ab, 0x03cf, 0x03cf, 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, 0x03f4, 0x03f4, 0x03f7, 0x03f7, 0x03f9, 0x03fa, 0x03fd, 0x042f, 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, 0x0480, 0x0480, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, 0x04c0, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0514, 0x0516, 0x0516, 0x0518, 0x0518, 0x051a, 0x051a, 0x051c, 0x051c, 0x051e, 0x051e, 0x0520, 0x0520, 0x0522, 0x0522, 0x0524, 0x0524, 0x0526, 0x0526, 0x0531, 0x0556, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1e00, 0x1e00, 0x1e02, 0x1e02, 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, 0x1e94, 0x1e94, 0x1e9e, 0x1e9e, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efa, 0x1efc, 0x1efc, 0x1efe, 0x1efe, 0x1f08, 0x1f0f, 0x1f18, 0x1f1d, 0x1f28, 0x1f2f, 0x1f38, 0x1f3f, 0x1f48, 0x1f4d, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f5f, 0x1f68, 0x1f6f, 0x1f88, 0x1f8f, 0x1f98, 0x1f9f, 0x1fa8, 0x1faf, 0x1fb8, 0x1fbc, 0x1fc8, 0x1fcc, 0x1fd8, 0x1fdb, 0x1fe8, 0x1fec, 0x1ff8, 0x1ffc, 0x2126, 0x2126, 0x212a, 0x212b, 0x2132, 0x2132, 0x2160, 0x216f, 0x2183, 0x2183, 0x24b6, 0x24cf, 0x2c00, 0x2c2e, 0x2c60, 0x2c60, 0x2c62, 0x2c64, 0x2c67, 0x2c67, 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c70, 0x2c72, 0x2c72, 0x2c75, 0x2c75, 0x2c7e, 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, 0x2ce0, 0x2ce2, 0x2ce2, 0x2ceb, 0x2ceb, 0x2ced, 0x2ced, 0x2cf2, 0x2cf2, 0xa640, 0xa640, 0xa642, 0xa642, 0xa644, 0xa644, 0xa646, 0xa646, 0xa648, 0xa648, 0xa64a, 0xa64a, 0xa64c, 0xa64c, 0xa64e, 0xa64e, 0xa650, 0xa650, 0xa652, 0xa652, 0xa654, 0xa654, 0xa656, 0xa656, 0xa658, 0xa658, 0xa65a, 0xa65a, 0xa65c, 0xa65c, 0xa65e, 0xa65e, 0xa660, 0xa660, 0xa662, 0xa662, 0xa664, 0xa664, 0xa666, 0xa666, 0xa668, 0xa668, 0xa66a, 0xa66a, 0xa66c, 0xa66c, 0xa680, 0xa680, 0xa682, 0xa682, 0xa684, 0xa684, 0xa686, 0xa686, 0xa688, 0xa688, 0xa68a, 0xa68a, 0xa68c, 0xa68c, 0xa68e, 0xa68e, 0xa690, 0xa690, 0xa692, 0xa692, 0xa694, 0xa694, 0xa696, 0xa696, 0xa722, 0xa722, 0xa724, 0xa724, 0xa726, 0xa726, 0xa728, 0xa728, 0xa72a, 0xa72a, 0xa72c, 0xa72c, 0xa72e, 0xa72e, 0xa732, 0xa732, 0xa734, 0xa734, 0xa736, 0xa736, 0xa738, 0xa738, 0xa73a, 0xa73a, 0xa73c, 0xa73c, 0xa73e, 0xa73e, 0xa740, 0xa740, 0xa742, 0xa742, 0xa744, 0xa744, 0xa746, 0xa746, 0xa748, 0xa748, 0xa74a, 0xa74a, 0xa74c, 0xa74c, 0xa74e, 0xa74e, 0xa750, 0xa750, 0xa752, 0xa752, 0xa754, 0xa754, 0xa756, 0xa756, 0xa758, 0xa758, 0xa75a, 0xa75a, 0xa75c, 0xa75c, 0xa75e, 0xa75e, 0xa760, 0xa760, 0xa762, 0xa762, 0xa764, 0xa764, 0xa766, 0xa766, 0xa768, 0xa768, 0xa76a, 0xa76a, 0xa76c, 0xa76c, 0xa76e, 0xa76e, 0xa779, 0xa779, 0xa77b, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa780, 0xa782, 0xa782, 0xa784, 0xa784, 0xa786, 0xa786, 0xa78b, 0xa78b, 0xa78d, 0xa78d, 0xa790, 0xa790, 0xa792, 0xa792, 0xa7a0, 0xa7a0, 0xa7a2, 0xa7a2, 0xa7a4, 0xa7a4, 0xa7a6, 0xa7a6, 0xa7a8, 0xa7a8, 0xa7aa, 0xa7aa, 0xff21, 0xff3a, 0x10400, 0x10427, }; /* CR_Changes_When_Lowercased */ /* 'Changes_When_Uppercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 586, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, 0x00f8, 0x00ff, 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, 0x0131, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x0180, 0x0183, 0x0183, 0x0185, 0x0185, 0x0188, 0x0188, 0x018c, 0x018c, 0x0192, 0x0192, 0x0195, 0x0195, 0x0199, 0x019a, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x01a8, 0x01a8, 0x01ad, 0x01ad, 0x01b0, 0x01b0, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x01b9, 0x01b9, 0x01bd, 0x01bd, 0x01bf, 0x01bf, 0x01c5, 0x01c6, 0x01c8, 0x01c9, 0x01cb, 0x01cc, 0x01ce, 0x01ce, 0x01d0, 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dd, 0x01df, 0x01df, 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01f0, 0x01f2, 0x01f3, 0x01f5, 0x01f5, 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff, 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, 0x0231, 0x0231, 0x0233, 0x0233, 0x023c, 0x023c, 0x023f, 0x0240, 0x0242, 0x0242, 0x0247, 0x0247, 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x0254, 0x0256, 0x0257, 0x0259, 0x0259, 0x025b, 0x025b, 0x0260, 0x0260, 0x0263, 0x0263, 0x0265, 0x0266, 0x0268, 0x0269, 0x026b, 0x026b, 0x026f, 0x026f, 0x0271, 0x0272, 0x0275, 0x0275, 0x027d, 0x027d, 0x0280, 0x0280, 0x0283, 0x0283, 0x0288, 0x028c, 0x0292, 0x0292, 0x0345, 0x0345, 0x0371, 0x0371, 0x0373, 0x0373, 0x0377, 0x0377, 0x037b, 0x037d, 0x0390, 0x0390, 0x03ac, 0x03ce, 0x03d0, 0x03d1, 0x03d5, 0x03d7, 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03f2, 0x03f5, 0x03f5, 0x03f8, 0x03f8, 0x03fb, 0x03fb, 0x0430, 0x045f, 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, 0x0481, 0x0481, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04cf, 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff, 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, 0x0561, 0x0587, 0x1d79, 0x1d79, 0x1d7d, 0x1d7d, 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e9b, 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45, 0x1f50, 0x1f57, 0x1f60, 0x1f67, 0x1f70, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fb7, 0x1fbc, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fc7, 0x1fcc, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fd7, 0x1fe0, 0x1fe7, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ff7, 0x1ffc, 0x1ffc, 0x214e, 0x214e, 0x2170, 0x217f, 0x2184, 0x2184, 0x24d0, 0x24e9, 0x2c30, 0x2c5e, 0x2c61, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x2c73, 0x2c73, 0x2c76, 0x2c76, 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce3, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cf3, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa72f, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa76f, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0xa77f, 0xa77f, 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, 0xa78c, 0xa78c, 0xa791, 0xa791, 0xa793, 0xa793, 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, 0xa7a9, 0xa7a9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff41, 0xff5a, 0x10428, 0x1044f, }; /* CR_Changes_When_Uppercased */ /* 'Changes_When_Titlecased': Derived Property */ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 587, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, 0x00f8, 0x00ff, 0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107, 0x0109, 0x0109, 0x010b, 0x010b, 0x010d, 0x010d, 0x010f, 0x010f, 0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117, 0x0119, 0x0119, 0x011b, 0x011b, 0x011d, 0x011d, 0x011f, 0x011f, 0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127, 0x0129, 0x0129, 0x012b, 0x012b, 0x012d, 0x012d, 0x012f, 0x012f, 0x0131, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137, 0x013a, 0x013a, 0x013c, 0x013c, 0x013e, 0x013e, 0x0140, 0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148, 0x0149, 0x014b, 0x014b, 0x014d, 0x014d, 0x014f, 0x014f, 0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157, 0x0159, 0x0159, 0x015b, 0x015b, 0x015d, 0x015d, 0x015f, 0x015f, 0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167, 0x0169, 0x0169, 0x016b, 0x016b, 0x016d, 0x016d, 0x016f, 0x016f, 0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177, 0x017a, 0x017a, 0x017c, 0x017c, 0x017e, 0x0180, 0x0183, 0x0183, 0x0185, 0x0185, 0x0188, 0x0188, 0x018c, 0x018c, 0x0192, 0x0192, 0x0195, 0x0195, 0x0199, 0x019a, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, 0x01a5, 0x01a5, 0x01a8, 0x01a8, 0x01ad, 0x01ad, 0x01b0, 0x01b0, 0x01b4, 0x01b4, 0x01b6, 0x01b6, 0x01b9, 0x01b9, 0x01bd, 0x01bd, 0x01bf, 0x01bf, 0x01c4, 0x01c4, 0x01c6, 0x01c7, 0x01c9, 0x01ca, 0x01cc, 0x01cc, 0x01ce, 0x01ce, 0x01d0, 0x01d0, 0x01d2, 0x01d2, 0x01d4, 0x01d4, 0x01d6, 0x01d6, 0x01d8, 0x01d8, 0x01da, 0x01da, 0x01dc, 0x01dd, 0x01df, 0x01df, 0x01e1, 0x01e1, 0x01e3, 0x01e3, 0x01e5, 0x01e5, 0x01e7, 0x01e7, 0x01e9, 0x01e9, 0x01eb, 0x01eb, 0x01ed, 0x01ed, 0x01ef, 0x01f1, 0x01f3, 0x01f3, 0x01f5, 0x01f5, 0x01f9, 0x01f9, 0x01fb, 0x01fb, 0x01fd, 0x01fd, 0x01ff, 0x01ff, 0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207, 0x0209, 0x0209, 0x020b, 0x020b, 0x020d, 0x020d, 0x020f, 0x020f, 0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217, 0x0219, 0x0219, 0x021b, 0x021b, 0x021d, 0x021d, 0x021f, 0x021f, 0x0223, 0x0223, 0x0225, 0x0225, 0x0227, 0x0227, 0x0229, 0x0229, 0x022b, 0x022b, 0x022d, 0x022d, 0x022f, 0x022f, 0x0231, 0x0231, 0x0233, 0x0233, 0x023c, 0x023c, 0x023f, 0x0240, 0x0242, 0x0242, 0x0247, 0x0247, 0x0249, 0x0249, 0x024b, 0x024b, 0x024d, 0x024d, 0x024f, 0x0254, 0x0256, 0x0257, 0x0259, 0x0259, 0x025b, 0x025b, 0x0260, 0x0260, 0x0263, 0x0263, 0x0265, 0x0266, 0x0268, 0x0269, 0x026b, 0x026b, 0x026f, 0x026f, 0x0271, 0x0272, 0x0275, 0x0275, 0x027d, 0x027d, 0x0280, 0x0280, 0x0283, 0x0283, 0x0288, 0x028c, 0x0292, 0x0292, 0x0345, 0x0345, 0x0371, 0x0371, 0x0373, 0x0373, 0x0377, 0x0377, 0x037b, 0x037d, 0x0390, 0x0390, 0x03ac, 0x03ce, 0x03d0, 0x03d1, 0x03d5, 0x03d7, 0x03d9, 0x03d9, 0x03db, 0x03db, 0x03dd, 0x03dd, 0x03df, 0x03df, 0x03e1, 0x03e1, 0x03e3, 0x03e3, 0x03e5, 0x03e5, 0x03e7, 0x03e7, 0x03e9, 0x03e9, 0x03eb, 0x03eb, 0x03ed, 0x03ed, 0x03ef, 0x03f2, 0x03f5, 0x03f5, 0x03f8, 0x03f8, 0x03fb, 0x03fb, 0x0430, 0x045f, 0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467, 0x0469, 0x0469, 0x046b, 0x046b, 0x046d, 0x046d, 0x046f, 0x046f, 0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477, 0x0479, 0x0479, 0x047b, 0x047b, 0x047d, 0x047d, 0x047f, 0x047f, 0x0481, 0x0481, 0x048b, 0x048b, 0x048d, 0x048d, 0x048f, 0x048f, 0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497, 0x0499, 0x0499, 0x049b, 0x049b, 0x049d, 0x049d, 0x049f, 0x049f, 0x04a1, 0x04a1, 0x04a3, 0x04a3, 0x04a5, 0x04a5, 0x04a7, 0x04a7, 0x04a9, 0x04a9, 0x04ab, 0x04ab, 0x04ad, 0x04ad, 0x04af, 0x04af, 0x04b1, 0x04b1, 0x04b3, 0x04b3, 0x04b5, 0x04b5, 0x04b7, 0x04b7, 0x04b9, 0x04b9, 0x04bb, 0x04bb, 0x04bd, 0x04bd, 0x04bf, 0x04bf, 0x04c2, 0x04c2, 0x04c4, 0x04c4, 0x04c6, 0x04c6, 0x04c8, 0x04c8, 0x04ca, 0x04ca, 0x04cc, 0x04cc, 0x04ce, 0x04cf, 0x04d1, 0x04d1, 0x04d3, 0x04d3, 0x04d5, 0x04d5, 0x04d7, 0x04d7, 0x04d9, 0x04d9, 0x04db, 0x04db, 0x04dd, 0x04dd, 0x04df, 0x04df, 0x04e1, 0x04e1, 0x04e3, 0x04e3, 0x04e5, 0x04e5, 0x04e7, 0x04e7, 0x04e9, 0x04e9, 0x04eb, 0x04eb, 0x04ed, 0x04ed, 0x04ef, 0x04ef, 0x04f1, 0x04f1, 0x04f3, 0x04f3, 0x04f5, 0x04f5, 0x04f7, 0x04f7, 0x04f9, 0x04f9, 0x04fb, 0x04fb, 0x04fd, 0x04fd, 0x04ff, 0x04ff, 0x0501, 0x0501, 0x0503, 0x0503, 0x0505, 0x0505, 0x0507, 0x0507, 0x0509, 0x0509, 0x050b, 0x050b, 0x050d, 0x050d, 0x050f, 0x050f, 0x0511, 0x0511, 0x0513, 0x0513, 0x0515, 0x0515, 0x0517, 0x0517, 0x0519, 0x0519, 0x051b, 0x051b, 0x051d, 0x051d, 0x051f, 0x051f, 0x0521, 0x0521, 0x0523, 0x0523, 0x0525, 0x0525, 0x0527, 0x0527, 0x0561, 0x0587, 0x1d79, 0x1d79, 0x1d7d, 0x1d7d, 0x1e01, 0x1e01, 0x1e03, 0x1e03, 0x1e05, 0x1e05, 0x1e07, 0x1e07, 0x1e09, 0x1e09, 0x1e0b, 0x1e0b, 0x1e0d, 0x1e0d, 0x1e0f, 0x1e0f, 0x1e11, 0x1e11, 0x1e13, 0x1e13, 0x1e15, 0x1e15, 0x1e17, 0x1e17, 0x1e19, 0x1e19, 0x1e1b, 0x1e1b, 0x1e1d, 0x1e1d, 0x1e1f, 0x1e1f, 0x1e21, 0x1e21, 0x1e23, 0x1e23, 0x1e25, 0x1e25, 0x1e27, 0x1e27, 0x1e29, 0x1e29, 0x1e2b, 0x1e2b, 0x1e2d, 0x1e2d, 0x1e2f, 0x1e2f, 0x1e31, 0x1e31, 0x1e33, 0x1e33, 0x1e35, 0x1e35, 0x1e37, 0x1e37, 0x1e39, 0x1e39, 0x1e3b, 0x1e3b, 0x1e3d, 0x1e3d, 0x1e3f, 0x1e3f, 0x1e41, 0x1e41, 0x1e43, 0x1e43, 0x1e45, 0x1e45, 0x1e47, 0x1e47, 0x1e49, 0x1e49, 0x1e4b, 0x1e4b, 0x1e4d, 0x1e4d, 0x1e4f, 0x1e4f, 0x1e51, 0x1e51, 0x1e53, 0x1e53, 0x1e55, 0x1e55, 0x1e57, 0x1e57, 0x1e59, 0x1e59, 0x1e5b, 0x1e5b, 0x1e5d, 0x1e5d, 0x1e5f, 0x1e5f, 0x1e61, 0x1e61, 0x1e63, 0x1e63, 0x1e65, 0x1e65, 0x1e67, 0x1e67, 0x1e69, 0x1e69, 0x1e6b, 0x1e6b, 0x1e6d, 0x1e6d, 0x1e6f, 0x1e6f, 0x1e71, 0x1e71, 0x1e73, 0x1e73, 0x1e75, 0x1e75, 0x1e77, 0x1e77, 0x1e79, 0x1e79, 0x1e7b, 0x1e7b, 0x1e7d, 0x1e7d, 0x1e7f, 0x1e7f, 0x1e81, 0x1e81, 0x1e83, 0x1e83, 0x1e85, 0x1e85, 0x1e87, 0x1e87, 0x1e89, 0x1e89, 0x1e8b, 0x1e8b, 0x1e8d, 0x1e8d, 0x1e8f, 0x1e8f, 0x1e91, 0x1e91, 0x1e93, 0x1e93, 0x1e95, 0x1e9b, 0x1ea1, 0x1ea1, 0x1ea3, 0x1ea3, 0x1ea5, 0x1ea5, 0x1ea7, 0x1ea7, 0x1ea9, 0x1ea9, 0x1eab, 0x1eab, 0x1ead, 0x1ead, 0x1eaf, 0x1eaf, 0x1eb1, 0x1eb1, 0x1eb3, 0x1eb3, 0x1eb5, 0x1eb5, 0x1eb7, 0x1eb7, 0x1eb9, 0x1eb9, 0x1ebb, 0x1ebb, 0x1ebd, 0x1ebd, 0x1ebf, 0x1ebf, 0x1ec1, 0x1ec1, 0x1ec3, 0x1ec3, 0x1ec5, 0x1ec5, 0x1ec7, 0x1ec7, 0x1ec9, 0x1ec9, 0x1ecb, 0x1ecb, 0x1ecd, 0x1ecd, 0x1ecf, 0x1ecf, 0x1ed1, 0x1ed1, 0x1ed3, 0x1ed3, 0x1ed5, 0x1ed5, 0x1ed7, 0x1ed7, 0x1ed9, 0x1ed9, 0x1edb, 0x1edb, 0x1edd, 0x1edd, 0x1edf, 0x1edf, 0x1ee1, 0x1ee1, 0x1ee3, 0x1ee3, 0x1ee5, 0x1ee5, 0x1ee7, 0x1ee7, 0x1ee9, 0x1ee9, 0x1eeb, 0x1eeb, 0x1eed, 0x1eed, 0x1eef, 0x1eef, 0x1ef1, 0x1ef1, 0x1ef3, 0x1ef3, 0x1ef5, 0x1ef5, 0x1ef7, 0x1ef7, 0x1ef9, 0x1ef9, 0x1efb, 0x1efb, 0x1efd, 0x1efd, 0x1eff, 0x1f07, 0x1f10, 0x1f15, 0x1f20, 0x1f27, 0x1f30, 0x1f37, 0x1f40, 0x1f45, 0x1f50, 0x1f57, 0x1f60, 0x1f67, 0x1f70, 0x1f7d, 0x1f80, 0x1f87, 0x1f90, 0x1f97, 0x1fa0, 0x1fa7, 0x1fb0, 0x1fb4, 0x1fb6, 0x1fb7, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fc7, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fd7, 0x1fe0, 0x1fe7, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ff7, 0x214e, 0x214e, 0x2170, 0x217f, 0x2184, 0x2184, 0x24d0, 0x24e9, 0x2c30, 0x2c5e, 0x2c61, 0x2c61, 0x2c65, 0x2c66, 0x2c68, 0x2c68, 0x2c6a, 0x2c6a, 0x2c6c, 0x2c6c, 0x2c73, 0x2c73, 0x2c76, 0x2c76, 0x2c81, 0x2c81, 0x2c83, 0x2c83, 0x2c85, 0x2c85, 0x2c87, 0x2c87, 0x2c89, 0x2c89, 0x2c8b, 0x2c8b, 0x2c8d, 0x2c8d, 0x2c8f, 0x2c8f, 0x2c91, 0x2c91, 0x2c93, 0x2c93, 0x2c95, 0x2c95, 0x2c97, 0x2c97, 0x2c99, 0x2c99, 0x2c9b, 0x2c9b, 0x2c9d, 0x2c9d, 0x2c9f, 0x2c9f, 0x2ca1, 0x2ca1, 0x2ca3, 0x2ca3, 0x2ca5, 0x2ca5, 0x2ca7, 0x2ca7, 0x2ca9, 0x2ca9, 0x2cab, 0x2cab, 0x2cad, 0x2cad, 0x2caf, 0x2caf, 0x2cb1, 0x2cb1, 0x2cb3, 0x2cb3, 0x2cb5, 0x2cb5, 0x2cb7, 0x2cb7, 0x2cb9, 0x2cb9, 0x2cbb, 0x2cbb, 0x2cbd, 0x2cbd, 0x2cbf, 0x2cbf, 0x2cc1, 0x2cc1, 0x2cc3, 0x2cc3, 0x2cc5, 0x2cc5, 0x2cc7, 0x2cc7, 0x2cc9, 0x2cc9, 0x2ccb, 0x2ccb, 0x2ccd, 0x2ccd, 0x2ccf, 0x2ccf, 0x2cd1, 0x2cd1, 0x2cd3, 0x2cd3, 0x2cd5, 0x2cd5, 0x2cd7, 0x2cd7, 0x2cd9, 0x2cd9, 0x2cdb, 0x2cdb, 0x2cdd, 0x2cdd, 0x2cdf, 0x2cdf, 0x2ce1, 0x2ce1, 0x2ce3, 0x2ce3, 0x2cec, 0x2cec, 0x2cee, 0x2cee, 0x2cf3, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa641, 0xa641, 0xa643, 0xa643, 0xa645, 0xa645, 0xa647, 0xa647, 0xa649, 0xa649, 0xa64b, 0xa64b, 0xa64d, 0xa64d, 0xa64f, 0xa64f, 0xa651, 0xa651, 0xa653, 0xa653, 0xa655, 0xa655, 0xa657, 0xa657, 0xa659, 0xa659, 0xa65b, 0xa65b, 0xa65d, 0xa65d, 0xa65f, 0xa65f, 0xa661, 0xa661, 0xa663, 0xa663, 0xa665, 0xa665, 0xa667, 0xa667, 0xa669, 0xa669, 0xa66b, 0xa66b, 0xa66d, 0xa66d, 0xa681, 0xa681, 0xa683, 0xa683, 0xa685, 0xa685, 0xa687, 0xa687, 0xa689, 0xa689, 0xa68b, 0xa68b, 0xa68d, 0xa68d, 0xa68f, 0xa68f, 0xa691, 0xa691, 0xa693, 0xa693, 0xa695, 0xa695, 0xa697, 0xa697, 0xa723, 0xa723, 0xa725, 0xa725, 0xa727, 0xa727, 0xa729, 0xa729, 0xa72b, 0xa72b, 0xa72d, 0xa72d, 0xa72f, 0xa72f, 0xa733, 0xa733, 0xa735, 0xa735, 0xa737, 0xa737, 0xa739, 0xa739, 0xa73b, 0xa73b, 0xa73d, 0xa73d, 0xa73f, 0xa73f, 0xa741, 0xa741, 0xa743, 0xa743, 0xa745, 0xa745, 0xa747, 0xa747, 0xa749, 0xa749, 0xa74b, 0xa74b, 0xa74d, 0xa74d, 0xa74f, 0xa74f, 0xa751, 0xa751, 0xa753, 0xa753, 0xa755, 0xa755, 0xa757, 0xa757, 0xa759, 0xa759, 0xa75b, 0xa75b, 0xa75d, 0xa75d, 0xa75f, 0xa75f, 0xa761, 0xa761, 0xa763, 0xa763, 0xa765, 0xa765, 0xa767, 0xa767, 0xa769, 0xa769, 0xa76b, 0xa76b, 0xa76d, 0xa76d, 0xa76f, 0xa76f, 0xa77a, 0xa77a, 0xa77c, 0xa77c, 0xa77f, 0xa77f, 0xa781, 0xa781, 0xa783, 0xa783, 0xa785, 0xa785, 0xa787, 0xa787, 0xa78c, 0xa78c, 0xa791, 0xa791, 0xa793, 0xa793, 0xa7a1, 0xa7a1, 0xa7a3, 0xa7a3, 0xa7a5, 0xa7a5, 0xa7a7, 0xa7a7, 0xa7a9, 0xa7a9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff41, 0xff5a, 0x10428, 0x1044f, }; /* CR_Changes_When_Titlecased */ /* 'Changes_When_Casefolded': Derived Property */ static const OnigCodePoint CR_Changes_When_Casefolded[] = { 582, 0x0041, 0x005a, 0x00b5, 0x00b5, 0x00c0, 0x00d6, 0x00d8, 0x00df, 0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106, 0x0108, 0x0108, 0x010a, 0x010a, 0x010c, 0x010c, 0x010e, 0x010e, 0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116, 0x0118, 0x0118, 0x011a, 0x011a, 0x011c, 0x011c, 0x011e, 0x011e, 0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126, 0x0128, 0x0128, 0x012a, 0x012a, 0x012c, 0x012c, 0x012e, 0x012e, 0x0130, 0x0130, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136, 0x0139, 0x0139, 0x013b, 0x013b, 0x013d, 0x013d, 0x013f, 0x013f, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147, 0x0147, 0x0149, 0x014a, 0x014c, 0x014c, 0x014e, 0x014e, 0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156, 0x0158, 0x0158, 0x015a, 0x015a, 0x015c, 0x015c, 0x015e, 0x015e, 0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166, 0x0168, 0x0168, 0x016a, 0x016a, 0x016c, 0x016c, 0x016e, 0x016e, 0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176, 0x0178, 0x0179, 0x017b, 0x017b, 0x017d, 0x017d, 0x017f, 0x017f, 0x0181, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0189, 0x018b, 0x018e, 0x0191, 0x0193, 0x0194, 0x0196, 0x0198, 0x019c, 0x019d, 0x019f, 0x01a0, 0x01a2, 0x01a2, 0x01a4, 0x01a4, 0x01a6, 0x01a7, 0x01a9, 0x01a9, 0x01ac, 0x01ac, 0x01ae, 0x01af, 0x01b1, 0x01b3, 0x01b5, 0x01b5, 0x01b7, 0x01b8, 0x01bc, 0x01bc, 0x01c4, 0x01c5, 0x01c7, 0x01c8, 0x01ca, 0x01cb, 0x01cd, 0x01cd, 0x01cf, 0x01cf, 0x01d1, 0x01d1, 0x01d3, 0x01d3, 0x01d5, 0x01d5, 0x01d7, 0x01d7, 0x01d9, 0x01d9, 0x01db, 0x01db, 0x01de, 0x01de, 0x01e0, 0x01e0, 0x01e2, 0x01e2, 0x01e4, 0x01e4, 0x01e6, 0x01e6, 0x01e8, 0x01e8, 0x01ea, 0x01ea, 0x01ec, 0x01ec, 0x01ee, 0x01ee, 0x01f1, 0x01f2, 0x01f4, 0x01f4, 0x01f6, 0x01f8, 0x01fa, 0x01fa, 0x01fc, 0x01fc, 0x01fe, 0x01fe, 0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206, 0x0208, 0x0208, 0x020a, 0x020a, 0x020c, 0x020c, 0x020e, 0x020e, 0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216, 0x0218, 0x0218, 0x021a, 0x021a, 0x021c, 0x021c, 0x021e, 0x021e, 0x0220, 0x0220, 0x0222, 0x0222, 0x0224, 0x0224, 0x0226, 0x0226, 0x0228, 0x0228, 0x022a, 0x022a, 0x022c, 0x022c, 0x022e, 0x022e, 0x0230, 0x0230, 0x0232, 0x0232, 0x023a, 0x023b, 0x023d, 0x023e, 0x0241, 0x0241, 0x0243, 0x0246, 0x0248, 0x0248, 0x024a, 0x024a, 0x024c, 0x024c, 0x024e, 0x024e, 0x0345, 0x0345, 0x0370, 0x0370, 0x0372, 0x0372, 0x0376, 0x0376, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x038f, 0x0391, 0x03a1, 0x03a3, 0x03ab, 0x03c2, 0x03c2, 0x03cf, 0x03d1, 0x03d5, 0x03d6, 0x03d8, 0x03d8, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03e2, 0x03e4, 0x03e4, 0x03e6, 0x03e6, 0x03e8, 0x03e8, 0x03ea, 0x03ea, 0x03ec, 0x03ec, 0x03ee, 0x03ee, 0x03f0, 0x03f1, 0x03f4, 0x03f5, 0x03f7, 0x03f7, 0x03f9, 0x03fa, 0x03fd, 0x042f, 0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466, 0x0468, 0x0468, 0x046a, 0x046a, 0x046c, 0x046c, 0x046e, 0x046e, 0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476, 0x0478, 0x0478, 0x047a, 0x047a, 0x047c, 0x047c, 0x047e, 0x047e, 0x0480, 0x0480, 0x048a, 0x048a, 0x048c, 0x048c, 0x048e, 0x048e, 0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496, 0x0498, 0x0498, 0x049a, 0x049a, 0x049c, 0x049c, 0x049e, 0x049e, 0x04a0, 0x04a0, 0x04a2, 0x04a2, 0x04a4, 0x04a4, 0x04a6, 0x04a6, 0x04a8, 0x04a8, 0x04aa, 0x04aa, 0x04ac, 0x04ac, 0x04ae, 0x04ae, 0x04b0, 0x04b0, 0x04b2, 0x04b2, 0x04b4, 0x04b4, 0x04b6, 0x04b6, 0x04b8, 0x04b8, 0x04ba, 0x04ba, 0x04bc, 0x04bc, 0x04be, 0x04be, 0x04c0, 0x04c1, 0x04c3, 0x04c3, 0x04c5, 0x04c5, 0x04c7, 0x04c7, 0x04c9, 0x04c9, 0x04cb, 0x04cb, 0x04cd, 0x04cd, 0x04d0, 0x04d0, 0x04d2, 0x04d2, 0x04d4, 0x04d4, 0x04d6, 0x04d6, 0x04d8, 0x04d8, 0x04da, 0x04da, 0x04dc, 0x04dc, 0x04de, 0x04de, 0x04e0, 0x04e0, 0x04e2, 0x04e2, 0x04e4, 0x04e4, 0x04e6, 0x04e6, 0x04e8, 0x04e8, 0x04ea, 0x04ea, 0x04ec, 0x04ec, 0x04ee, 0x04ee, 0x04f0, 0x04f0, 0x04f2, 0x04f2, 0x04f4, 0x04f4, 0x04f6, 0x04f6, 0x04f8, 0x04f8, 0x04fa, 0x04fa, 0x04fc, 0x04fc, 0x04fe, 0x04fe, 0x0500, 0x0500, 0x0502, 0x0502, 0x0504, 0x0504, 0x0506, 0x0506, 0x0508, 0x0508, 0x050a, 0x050a, 0x050c, 0x050c, 0x050e, 0x050e, 0x0510, 0x0510, 0x0512, 0x0512, 0x0514, 0x0514, 0x0516, 0x0516, 0x0518, 0x0518, 0x051a, 0x051a, 0x051c, 0x051c, 0x051e, 0x051e, 0x0520, 0x0520, 0x0522, 0x0522, 0x0524, 0x0524, 0x0526, 0x0526, 0x0531, 0x0556, 0x0587, 0x0587, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1e00, 0x1e00, 0x1e02, 0x1e02, 0x1e04, 0x1e04, 0x1e06, 0x1e06, 0x1e08, 0x1e08, 0x1e0a, 0x1e0a, 0x1e0c, 0x1e0c, 0x1e0e, 0x1e0e, 0x1e10, 0x1e10, 0x1e12, 0x1e12, 0x1e14, 0x1e14, 0x1e16, 0x1e16, 0x1e18, 0x1e18, 0x1e1a, 0x1e1a, 0x1e1c, 0x1e1c, 0x1e1e, 0x1e1e, 0x1e20, 0x1e20, 0x1e22, 0x1e22, 0x1e24, 0x1e24, 0x1e26, 0x1e26, 0x1e28, 0x1e28, 0x1e2a, 0x1e2a, 0x1e2c, 0x1e2c, 0x1e2e, 0x1e2e, 0x1e30, 0x1e30, 0x1e32, 0x1e32, 0x1e34, 0x1e34, 0x1e36, 0x1e36, 0x1e38, 0x1e38, 0x1e3a, 0x1e3a, 0x1e3c, 0x1e3c, 0x1e3e, 0x1e3e, 0x1e40, 0x1e40, 0x1e42, 0x1e42, 0x1e44, 0x1e44, 0x1e46, 0x1e46, 0x1e48, 0x1e48, 0x1e4a, 0x1e4a, 0x1e4c, 0x1e4c, 0x1e4e, 0x1e4e, 0x1e50, 0x1e50, 0x1e52, 0x1e52, 0x1e54, 0x1e54, 0x1e56, 0x1e56, 0x1e58, 0x1e58, 0x1e5a, 0x1e5a, 0x1e5c, 0x1e5c, 0x1e5e, 0x1e5e, 0x1e60, 0x1e60, 0x1e62, 0x1e62, 0x1e64, 0x1e64, 0x1e66, 0x1e66, 0x1e68, 0x1e68, 0x1e6a, 0x1e6a, 0x1e6c, 0x1e6c, 0x1e6e, 0x1e6e, 0x1e70, 0x1e70, 0x1e72, 0x1e72, 0x1e74, 0x1e74, 0x1e76, 0x1e76, 0x1e78, 0x1e78, 0x1e7a, 0x1e7a, 0x1e7c, 0x1e7c, 0x1e7e, 0x1e7e, 0x1e80, 0x1e80, 0x1e82, 0x1e82, 0x1e84, 0x1e84, 0x1e86, 0x1e86, 0x1e88, 0x1e88, 0x1e8a, 0x1e8a, 0x1e8c, 0x1e8c, 0x1e8e, 0x1e8e, 0x1e90, 0x1e90, 0x1e92, 0x1e92, 0x1e94, 0x1e94, 0x1e9a, 0x1e9b, 0x1e9e, 0x1e9e, 0x1ea0, 0x1ea0, 0x1ea2, 0x1ea2, 0x1ea4, 0x1ea4, 0x1ea6, 0x1ea6, 0x1ea8, 0x1ea8, 0x1eaa, 0x1eaa, 0x1eac, 0x1eac, 0x1eae, 0x1eae, 0x1eb0, 0x1eb0, 0x1eb2, 0x1eb2, 0x1eb4, 0x1eb4, 0x1eb6, 0x1eb6, 0x1eb8, 0x1eb8, 0x1eba, 0x1eba, 0x1ebc, 0x1ebc, 0x1ebe, 0x1ebe, 0x1ec0, 0x1ec0, 0x1ec2, 0x1ec2, 0x1ec4, 0x1ec4, 0x1ec6, 0x1ec6, 0x1ec8, 0x1ec8, 0x1eca, 0x1eca, 0x1ecc, 0x1ecc, 0x1ece, 0x1ece, 0x1ed0, 0x1ed0, 0x1ed2, 0x1ed2, 0x1ed4, 0x1ed4, 0x1ed6, 0x1ed6, 0x1ed8, 0x1ed8, 0x1eda, 0x1eda, 0x1edc, 0x1edc, 0x1ede, 0x1ede, 0x1ee0, 0x1ee0, 0x1ee2, 0x1ee2, 0x1ee4, 0x1ee4, 0x1ee6, 0x1ee6, 0x1ee8, 0x1ee8, 0x1eea, 0x1eea, 0x1eec, 0x1eec, 0x1eee, 0x1eee, 0x1ef0, 0x1ef0, 0x1ef2, 0x1ef2, 0x1ef4, 0x1ef4, 0x1ef6, 0x1ef6, 0x1ef8, 0x1ef8, 0x1efa, 0x1efa, 0x1efc, 0x1efc, 0x1efe, 0x1efe, 0x1f08, 0x1f0f, 0x1f18, 0x1f1d, 0x1f28, 0x1f2f, 0x1f38, 0x1f3f, 0x1f48, 0x1f4d, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f5f, 0x1f68, 0x1f6f, 0x1f80, 0x1faf, 0x1fb2, 0x1fb4, 0x1fb7, 0x1fbc, 0x1fc2, 0x1fc4, 0x1fc7, 0x1fcc, 0x1fd8, 0x1fdb, 0x1fe8, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff7, 0x1ffc, 0x2126, 0x2126, 0x212a, 0x212b, 0x2132, 0x2132, 0x2160, 0x216f, 0x2183, 0x2183, 0x24b6, 0x24cf, 0x2c00, 0x2c2e, 0x2c60, 0x2c60, 0x2c62, 0x2c64, 0x2c67, 0x2c67, 0x2c69, 0x2c69, 0x2c6b, 0x2c6b, 0x2c6d, 0x2c70, 0x2c72, 0x2c72, 0x2c75, 0x2c75, 0x2c7e, 0x2c80, 0x2c82, 0x2c82, 0x2c84, 0x2c84, 0x2c86, 0x2c86, 0x2c88, 0x2c88, 0x2c8a, 0x2c8a, 0x2c8c, 0x2c8c, 0x2c8e, 0x2c8e, 0x2c90, 0x2c90, 0x2c92, 0x2c92, 0x2c94, 0x2c94, 0x2c96, 0x2c96, 0x2c98, 0x2c98, 0x2c9a, 0x2c9a, 0x2c9c, 0x2c9c, 0x2c9e, 0x2c9e, 0x2ca0, 0x2ca0, 0x2ca2, 0x2ca2, 0x2ca4, 0x2ca4, 0x2ca6, 0x2ca6, 0x2ca8, 0x2ca8, 0x2caa, 0x2caa, 0x2cac, 0x2cac, 0x2cae, 0x2cae, 0x2cb0, 0x2cb0, 0x2cb2, 0x2cb2, 0x2cb4, 0x2cb4, 0x2cb6, 0x2cb6, 0x2cb8, 0x2cb8, 0x2cba, 0x2cba, 0x2cbc, 0x2cbc, 0x2cbe, 0x2cbe, 0x2cc0, 0x2cc0, 0x2cc2, 0x2cc2, 0x2cc4, 0x2cc4, 0x2cc6, 0x2cc6, 0x2cc8, 0x2cc8, 0x2cca, 0x2cca, 0x2ccc, 0x2ccc, 0x2cce, 0x2cce, 0x2cd0, 0x2cd0, 0x2cd2, 0x2cd2, 0x2cd4, 0x2cd4, 0x2cd6, 0x2cd6, 0x2cd8, 0x2cd8, 0x2cda, 0x2cda, 0x2cdc, 0x2cdc, 0x2cde, 0x2cde, 0x2ce0, 0x2ce0, 0x2ce2, 0x2ce2, 0x2ceb, 0x2ceb, 0x2ced, 0x2ced, 0x2cf2, 0x2cf2, 0xa640, 0xa640, 0xa642, 0xa642, 0xa644, 0xa644, 0xa646, 0xa646, 0xa648, 0xa648, 0xa64a, 0xa64a, 0xa64c, 0xa64c, 0xa64e, 0xa64e, 0xa650, 0xa650, 0xa652, 0xa652, 0xa654, 0xa654, 0xa656, 0xa656, 0xa658, 0xa658, 0xa65a, 0xa65a, 0xa65c, 0xa65c, 0xa65e, 0xa65e, 0xa660, 0xa660, 0xa662, 0xa662, 0xa664, 0xa664, 0xa666, 0xa666, 0xa668, 0xa668, 0xa66a, 0xa66a, 0xa66c, 0xa66c, 0xa680, 0xa680, 0xa682, 0xa682, 0xa684, 0xa684, 0xa686, 0xa686, 0xa688, 0xa688, 0xa68a, 0xa68a, 0xa68c, 0xa68c, 0xa68e, 0xa68e, 0xa690, 0xa690, 0xa692, 0xa692, 0xa694, 0xa694, 0xa696, 0xa696, 0xa722, 0xa722, 0xa724, 0xa724, 0xa726, 0xa726, 0xa728, 0xa728, 0xa72a, 0xa72a, 0xa72c, 0xa72c, 0xa72e, 0xa72e, 0xa732, 0xa732, 0xa734, 0xa734, 0xa736, 0xa736, 0xa738, 0xa738, 0xa73a, 0xa73a, 0xa73c, 0xa73c, 0xa73e, 0xa73e, 0xa740, 0xa740, 0xa742, 0xa742, 0xa744, 0xa744, 0xa746, 0xa746, 0xa748, 0xa748, 0xa74a, 0xa74a, 0xa74c, 0xa74c, 0xa74e, 0xa74e, 0xa750, 0xa750, 0xa752, 0xa752, 0xa754, 0xa754, 0xa756, 0xa756, 0xa758, 0xa758, 0xa75a, 0xa75a, 0xa75c, 0xa75c, 0xa75e, 0xa75e, 0xa760, 0xa760, 0xa762, 0xa762, 0xa764, 0xa764, 0xa766, 0xa766, 0xa768, 0xa768, 0xa76a, 0xa76a, 0xa76c, 0xa76c, 0xa76e, 0xa76e, 0xa779, 0xa779, 0xa77b, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa780, 0xa782, 0xa782, 0xa784, 0xa784, 0xa786, 0xa786, 0xa78b, 0xa78b, 0xa78d, 0xa78d, 0xa790, 0xa790, 0xa792, 0xa792, 0xa7a0, 0xa7a0, 0xa7a2, 0xa7a2, 0xa7a4, 0xa7a4, 0xa7a6, 0xa7a6, 0xa7a8, 0xa7a8, 0xa7aa, 0xa7aa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff21, 0xff3a, 0x10400, 0x10427, }; /* CR_Changes_When_Casefolded */ /* 'Changes_When_Casemapped': Derived Property */ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 104, 0x0041, 0x005a, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x0137, 0x0139, 0x018c, 0x018e, 0x019a, 0x019c, 0x01a9, 0x01ac, 0x01b9, 0x01bc, 0x01bd, 0x01bf, 0x01bf, 0x01c4, 0x0220, 0x0222, 0x0233, 0x023a, 0x0254, 0x0256, 0x0257, 0x0259, 0x0259, 0x025b, 0x025b, 0x0260, 0x0260, 0x0263, 0x0263, 0x0265, 0x0266, 0x0268, 0x0269, 0x026b, 0x026b, 0x026f, 0x026f, 0x0271, 0x0272, 0x0275, 0x0275, 0x027d, 0x027d, 0x0280, 0x0280, 0x0283, 0x0283, 0x0288, 0x028c, 0x0292, 0x0292, 0x0345, 0x0345, 0x0370, 0x0373, 0x0376, 0x0377, 0x037b, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03d1, 0x03d5, 0x03f2, 0x03f4, 0x03f5, 0x03f7, 0x03fb, 0x03fd, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0561, 0x0587, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x1d79, 0x1d79, 0x1d7d, 0x1d7d, 0x1e00, 0x1e9b, 0x1e9e, 0x1e9e, 0x1ea0, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2126, 0x2126, 0x212a, 0x212b, 0x2132, 0x2132, 0x214e, 0x214e, 0x2160, 0x217f, 0x2183, 0x2184, 0x24b6, 0x24e9, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2c70, 0x2c72, 0x2c73, 0x2c75, 0x2c76, 0x2c7e, 0x2ce3, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0xa640, 0xa66d, 0xa680, 0xa697, 0xa722, 0xa72f, 0xa732, 0xa76f, 0xa779, 0xa787, 0xa78b, 0xa78d, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xff21, 0xff3a, 0xff41, 0xff5a, 0x10400, 0x1044f, }; /* CR_Changes_When_Casemapped */ /* 'ID_Start': Derived Property */ static const OnigCodePoint CR_ID_Start[] = { 488, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0370, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0620, 0x064a, 0x066e, 0x066f, 0x0671, 0x06d3, 0x06d5, 0x06d5, 0x06e5, 0x06e6, 0x06ee, 0x06ef, 0x06fa, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x0710, 0x0712, 0x072f, 0x074d, 0x07a5, 0x07b1, 0x07b1, 0x07ca, 0x07ea, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x0815, 0x081a, 0x081a, 0x0824, 0x0824, 0x0828, 0x0828, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, 0x0958, 0x0961, 0x0971, 0x0977, 0x0979, 0x097f, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09bd, 0x09ce, 0x09ce, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09f0, 0x09f1, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a72, 0x0a74, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0abd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae1, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b3d, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b71, 0x0b71, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bd0, 0x0bd0, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c3d, 0x0c58, 0x0c59, 0x0c60, 0x0c61, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbd, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, 0x0d4e, 0x0d4e, 0x0d60, 0x0d61, 0x0d7a, 0x0d7f, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0e01, 0x0e30, 0x0e32, 0x0e33, 0x0e40, 0x0e46, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb3, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f88, 0x0f8c, 0x1000, 0x102a, 0x103f, 0x103f, 0x1050, 0x1055, 0x105a, 0x105d, 0x1061, 0x1061, 0x1065, 0x1066, 0x106e, 0x1070, 0x1075, 0x1081, 0x108e, 0x108e, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3, 0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x1820, 0x1877, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1950, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19c1, 0x19c7, 0x1a00, 0x1a16, 0x1a20, 0x1a54, 0x1aa7, 0x1aa7, 0x1b05, 0x1b33, 0x1b45, 0x1b4b, 0x1b83, 0x1ba0, 0x1bae, 0x1baf, 0x1bba, 0x1be5, 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, 0x1ce9, 0x1cec, 0x1cee, 0x1cf1, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309b, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa640, 0xa66e, 0xa67f, 0xa697, 0xa6a0, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, 0xa840, 0xa873, 0xa882, 0xa8b3, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa90a, 0xa925, 0xa930, 0xa946, 0xa960, 0xa97c, 0xa984, 0xa9b2, 0xa9cf, 0xa9cf, 0xaa00, 0xaa28, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaea, 0xaaf2, 0xaaf4, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11183, 0x111b2, 0x111c1, 0x111c4, 0x11680, 0x116aa, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f50, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_ID_Start */ /* 'ID_Continue': Derived Property */ static const OnigCodePoint CR_ID_Continue[] = { 564, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00b7, 0x00b7, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0300, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x0386, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x0483, 0x0487, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0610, 0x061a, 0x0620, 0x0669, 0x066e, 0x06d3, 0x06d5, 0x06dc, 0x06df, 0x06e8, 0x06ea, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x082d, 0x0840, 0x085b, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0963, 0x0966, 0x096f, 0x0971, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09f1, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, 0x0b71, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bef, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e01, 0x0e3a, 0x0e40, 0x0e4e, 0x0e50, 0x0e59, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f18, 0x0f19, 0x0f20, 0x0f29, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f3e, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f84, 0x0f86, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x1000, 0x1049, 0x1050, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x135f, 0x1369, 0x1371, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1734, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17d3, 0x17d7, 0x17d7, 0x17dc, 0x17dd, 0x17e0, 0x17e9, 0x180b, 0x180d, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1946, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, 0x1b80, 0x1bf3, 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, 0x1cd0, 0x1cd2, 0x1cd4, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x20d0, 0x20dc, 0x20e1, 0x20e1, 0x20e5, 0x20f0, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff, 0x3005, 0x3007, 0x3021, 0x302f, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x3099, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa62b, 0xa640, 0xa66f, 0xa674, 0xa67d, 0xa67f, 0xa697, 0xa69f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c4, 0xa8d0, 0xa8d9, 0xa8e0, 0xa8f7, 0xa8fb, 0xa8fb, 0xa900, 0xa92d, 0xa930, 0xa953, 0xa960, 0xa97c, 0xa980, 0xa9c0, 0xa9cf, 0xa9d9, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa60, 0xaa76, 0xaa7a, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0xfe33, 0xfe34, 0xfe4d, 0xfe4f, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff10, 0xff19, 0xff21, 0xff3a, 0xff3f, 0xff3f, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x101fd, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11000, 0x11046, 0x11066, 0x1106f, 0x11080, 0x110ba, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, 0x11180, 0x111c4, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0100, 0xe01ef, }; /* CR_ID_Continue */ /* 'XID_Start': Derived Property */ static const OnigCodePoint CR_XID_Start[] = { 495, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0370, 0x0374, 0x0376, 0x0377, 0x037b, 0x037d, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0620, 0x064a, 0x066e, 0x066f, 0x0671, 0x06d3, 0x06d5, 0x06d5, 0x06e5, 0x06e6, 0x06ee, 0x06ef, 0x06fa, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x0710, 0x0712, 0x072f, 0x074d, 0x07a5, 0x07b1, 0x07b1, 0x07ca, 0x07ea, 0x07f4, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x0815, 0x081a, 0x081a, 0x0824, 0x0824, 0x0828, 0x0828, 0x0840, 0x0858, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x0904, 0x0939, 0x093d, 0x093d, 0x0950, 0x0950, 0x0958, 0x0961, 0x0971, 0x0977, 0x0979, 0x097f, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09bd, 0x09ce, 0x09ce, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09f0, 0x09f1, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a72, 0x0a74, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0abd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae1, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b3d, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b71, 0x0b71, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bd0, 0x0bd0, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c3d, 0x0c58, 0x0c59, 0x0c60, 0x0c61, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbd, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0cf1, 0x0cf2, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, 0x0d4e, 0x0d4e, 0x0d60, 0x0d61, 0x0d7a, 0x0d7f, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0e01, 0x0e30, 0x0e32, 0x0e32, 0x0e40, 0x0e46, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb2, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f40, 0x0f47, 0x0f49, 0x0f6c, 0x0f88, 0x0f8c, 0x1000, 0x102a, 0x103f, 0x103f, 0x1050, 0x1055, 0x105a, 0x105d, 0x1061, 0x1061, 0x1065, 0x1066, 0x106e, 0x1070, 0x1075, 0x1081, 0x108e, 0x108e, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3, 0x17d7, 0x17d7, 0x17dc, 0x17dc, 0x1820, 0x1877, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1950, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19c1, 0x19c7, 0x1a00, 0x1a16, 0x1a20, 0x1a54, 0x1aa7, 0x1aa7, 0x1b05, 0x1b33, 0x1b45, 0x1b4b, 0x1b83, 0x1ba0, 0x1bae, 0x1baf, 0x1bba, 0x1be5, 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, 0x1ce9, 0x1cec, 0x1cee, 0x1cf1, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cee, 0x2cf2, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x3005, 0x3007, 0x3021, 0x3029, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa61f, 0xa62a, 0xa62b, 0xa640, 0xa66e, 0xa67f, 0xa697, 0xa6a0, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa822, 0xa840, 0xa873, 0xa882, 0xa8b3, 0xa8f2, 0xa8f7, 0xa8fb, 0xa8fb, 0xa90a, 0xa925, 0xa930, 0xa946, 0xa960, 0xa97c, 0xa984, 0xa9b2, 0xa9cf, 0xa9cf, 0xaa00, 0xaa28, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa60, 0xaa76, 0xaa7a, 0xaa7a, 0xaa80, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaea, 0xaaf2, 0xaaf4, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabe2, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfc5d, 0xfc64, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdf9, 0xfe71, 0xfe71, 0xfe73, 0xfe73, 0xfe77, 0xfe77, 0xfe79, 0xfe79, 0xfe7b, 0xfe7b, 0xfe7d, 0xfe7d, 0xfe7f, 0xfefc, 0xff21, 0xff3a, 0xff41, 0xff5a, 0xff66, 0xff9d, 0xffa0, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11003, 0x11037, 0x11083, 0x110af, 0x110d0, 0x110e8, 0x11103, 0x11126, 0x11183, 0x111b2, 0x111c1, 0x111c4, 0x11680, 0x116aa, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f50, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_XID_Start */ /* 'XID_Continue': Derived Property */ static const OnigCodePoint CR_XID_Continue[] = { 571, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, 0x00b7, 0x00b7, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0300, 0x0374, 0x0376, 0x0377, 0x037b, 0x037d, 0x0386, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03f5, 0x03f7, 0x0481, 0x0483, 0x0487, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x0559, 0x0561, 0x0587, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f2, 0x0610, 0x061a, 0x0620, 0x0669, 0x066e, 0x06d3, 0x06d5, 0x06dc, 0x06df, 0x06e8, 0x06ea, 0x06fc, 0x06ff, 0x06ff, 0x0710, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07f5, 0x07fa, 0x07fa, 0x0800, 0x082d, 0x0840, 0x085b, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0963, 0x0966, 0x096f, 0x0971, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09f1, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b6f, 0x0b71, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bef, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d6f, 0x0d7a, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e01, 0x0e3a, 0x0e40, 0x0e4e, 0x0e50, 0x0e59, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f00, 0x0f18, 0x0f19, 0x0f20, 0x0f29, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f3e, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f84, 0x0f86, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x1000, 0x1049, 0x1050, 0x109d, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x135f, 0x1369, 0x1371, 0x1380, 0x138f, 0x13a0, 0x13f4, 0x1401, 0x166c, 0x166f, 0x167f, 0x1681, 0x169a, 0x16a0, 0x16ea, 0x16ee, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1734, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17d3, 0x17d7, 0x17d7, 0x17dc, 0x17dd, 0x17e0, 0x17e9, 0x180b, 0x180d, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1946, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x1a00, 0x1a1b, 0x1a20, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa7, 0x1aa7, 0x1b00, 0x1b4b, 0x1b50, 0x1b59, 0x1b6b, 0x1b73, 0x1b80, 0x1bf3, 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, 0x1cd0, 0x1cd2, 0x1cd4, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fbc, 0x1fbe, 0x1fbe, 0x1fc2, 0x1fc4, 0x1fc6, 0x1fcc, 0x1fd0, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x20d0, 0x20dc, 0x20e1, 0x20e1, 0x20e5, 0x20f0, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2118, 0x211d, 0x2124, 0x2124, 0x2126, 0x2126, 0x2128, 0x2128, 0x212a, 0x2139, 0x213c, 0x213f, 0x2145, 0x2149, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2ce4, 0x2ceb, 0x2cf3, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d6f, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2dff, 0x3005, 0x3007, 0x3021, 0x302f, 0x3031, 0x3035, 0x3038, 0x303c, 0x3041, 0x3096, 0x3099, 0x309a, 0x309d, 0x309f, 0x30a1, 0x30fa, 0x30fc, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x31a0, 0x31ba, 0x31f0, 0x31ff, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xa000, 0xa48c, 0xa4d0, 0xa4fd, 0xa500, 0xa60c, 0xa610, 0xa62b, 0xa640, 0xa66f, 0xa674, 0xa67d, 0xa67f, 0xa697, 0xa69f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa827, 0xa840, 0xa873, 0xa880, 0xa8c4, 0xa8d0, 0xa8d9, 0xa8e0, 0xa8f7, 0xa8fb, 0xa8fb, 0xa900, 0xa92d, 0xa930, 0xa953, 0xa960, 0xa97c, 0xa980, 0xa9c0, 0xa9cf, 0xa9d9, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa60, 0xaa76, 0xaa7a, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaadd, 0xaae0, 0xaaef, 0xaaf2, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabea, 0xabec, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb28, 0xfb2a, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfc5d, 0xfc64, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdf9, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0xfe33, 0xfe34, 0xfe4d, 0xfe4f, 0xfe71, 0xfe71, 0xfe73, 0xfe73, 0xfe77, 0xfe77, 0xfe79, 0xfe79, 0xfe7b, 0xfe7b, 0xfe7d, 0xfe7d, 0xfe7f, 0xfefc, 0xff10, 0xff19, 0xff21, 0xff3a, 0xff3f, 0xff3f, 0xff41, 0xff5a, 0xff66, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10140, 0x10174, 0x101fd, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x103a0, 0x103c3, 0x103c8, 0x103cf, 0x103d1, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10900, 0x10915, 0x10920, 0x10939, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x10a60, 0x10a7c, 0x10b00, 0x10b35, 0x10b40, 0x10b55, 0x10b60, 0x10b72, 0x10c00, 0x10c48, 0x11000, 0x11046, 0x11066, 0x1106f, 0x11080, 0x110ba, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x1113f, 0x11180, 0x111c4, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d165, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0xe0100, 0xe01ef, }; /* CR_XID_Continue */ /* 'Default_Ignorable_Code_Point': Derived Property */ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = { 15, 0x00ad, 0x00ad, 0x034f, 0x034f, 0x115f, 0x1160, 0x17b4, 0x17b5, 0x180b, 0x180d, 0x200b, 0x200f, 0x202a, 0x202e, 0x2060, 0x206f, 0x3164, 0x3164, 0xfe00, 0xfe0f, 0xfeff, 0xfeff, 0xffa0, 0xffa0, 0xfff0, 0xfff8, 0x1d173, 0x1d17a, 0xe0000, 0xe0fff, }; /* CR_Default_Ignorable_Code_Point */ /* 'Grapheme_Extend': Derived Property */ static const OnigCodePoint CR_Grapheme_Extend[] = { 232, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x0610, 0x061a, 0x064b, 0x065f, 0x0670, 0x0670, 0x06d6, 0x06dc, 0x06df, 0x06e4, 0x06e7, 0x06e8, 0x06ea, 0x06ed, 0x0711, 0x0711, 0x0730, 0x074a, 0x07a6, 0x07b0, 0x07eb, 0x07f3, 0x0816, 0x0819, 0x081b, 0x0823, 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, 0x08e4, 0x08fe, 0x0900, 0x0902, 0x093a, 0x093a, 0x093c, 0x093c, 0x0941, 0x0948, 0x094d, 0x094d, 0x0951, 0x0957, 0x0962, 0x0963, 0x0981, 0x0981, 0x09bc, 0x09bc, 0x09be, 0x09be, 0x09c1, 0x09c4, 0x09cd, 0x09cd, 0x09d7, 0x09d7, 0x09e2, 0x09e3, 0x0a01, 0x0a02, 0x0a3c, 0x0a3c, 0x0a41, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a70, 0x0a71, 0x0a75, 0x0a75, 0x0a81, 0x0a82, 0x0abc, 0x0abc, 0x0ac1, 0x0ac5, 0x0ac7, 0x0ac8, 0x0acd, 0x0acd, 0x0ae2, 0x0ae3, 0x0b01, 0x0b01, 0x0b3c, 0x0b3c, 0x0b3e, 0x0b3f, 0x0b41, 0x0b44, 0x0b4d, 0x0b4d, 0x0b56, 0x0b57, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bbe, 0x0bbe, 0x0bc0, 0x0bc0, 0x0bcd, 0x0bcd, 0x0bd7, 0x0bd7, 0x0c3e, 0x0c40, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c62, 0x0c63, 0x0cbc, 0x0cbc, 0x0cbf, 0x0cbf, 0x0cc2, 0x0cc2, 0x0cc6, 0x0cc6, 0x0ccc, 0x0ccd, 0x0cd5, 0x0cd6, 0x0ce2, 0x0ce3, 0x0d3e, 0x0d3e, 0x0d41, 0x0d44, 0x0d4d, 0x0d4d, 0x0d57, 0x0d57, 0x0d62, 0x0d63, 0x0dca, 0x0dca, 0x0dcf, 0x0dcf, 0x0dd2, 0x0dd4, 0x0dd6, 0x0dd6, 0x0ddf, 0x0ddf, 0x0e31, 0x0e31, 0x0e34, 0x0e3a, 0x0e47, 0x0e4e, 0x0eb1, 0x0eb1, 0x0eb4, 0x0eb9, 0x0ebb, 0x0ebc, 0x0ec8, 0x0ecd, 0x0f18, 0x0f19, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f71, 0x0f7e, 0x0f80, 0x0f84, 0x0f86, 0x0f87, 0x0f8d, 0x0f97, 0x0f99, 0x0fbc, 0x0fc6, 0x0fc6, 0x102d, 0x1030, 0x1032, 0x1037, 0x1039, 0x103a, 0x103d, 0x103e, 0x1058, 0x1059, 0x105e, 0x1060, 0x1071, 0x1074, 0x1082, 0x1082, 0x1085, 0x1086, 0x108d, 0x108d, 0x109d, 0x109d, 0x135d, 0x135f, 0x1712, 0x1714, 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17b5, 0x17b7, 0x17bd, 0x17c6, 0x17c6, 0x17c9, 0x17d3, 0x17dd, 0x17dd, 0x180b, 0x180d, 0x18a9, 0x18a9, 0x1920, 0x1922, 0x1927, 0x1928, 0x1932, 0x1932, 0x1939, 0x193b, 0x1a17, 0x1a18, 0x1a56, 0x1a56, 0x1a58, 0x1a5e, 0x1a60, 0x1a60, 0x1a62, 0x1a62, 0x1a65, 0x1a6c, 0x1a73, 0x1a7c, 0x1a7f, 0x1a7f, 0x1b00, 0x1b03, 0x1b34, 0x1b34, 0x1b36, 0x1b3a, 0x1b3c, 0x1b3c, 0x1b42, 0x1b42, 0x1b6b, 0x1b73, 0x1b80, 0x1b81, 0x1ba2, 0x1ba5, 0x1ba8, 0x1ba9, 0x1bab, 0x1bab, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, 0x1bef, 0x1bf1, 0x1c2c, 0x1c33, 0x1c36, 0x1c37, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce0, 0x1ce2, 0x1ce8, 0x1ced, 0x1ced, 0x1cf4, 0x1cf4, 0x1dc0, 0x1de6, 0x1dfc, 0x1dff, 0x200c, 0x200d, 0x20d0, 0x20f0, 0x2cef, 0x2cf1, 0x2d7f, 0x2d7f, 0x2de0, 0x2dff, 0x302a, 0x302f, 0x3099, 0x309a, 0xa66f, 0xa672, 0xa674, 0xa67d, 0xa69f, 0xa69f, 0xa6f0, 0xa6f1, 0xa802, 0xa802, 0xa806, 0xa806, 0xa80b, 0xa80b, 0xa825, 0xa826, 0xa8c4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa926, 0xa92d, 0xa947, 0xa951, 0xa980, 0xa982, 0xa9b3, 0xa9b3, 0xa9b6, 0xa9b9, 0xa9bc, 0xa9bc, 0xaa29, 0xaa2e, 0xaa31, 0xaa32, 0xaa35, 0xaa36, 0xaa43, 0xaa43, 0xaa4c, 0xaa4c, 0xaab0, 0xaab0, 0xaab2, 0xaab4, 0xaab7, 0xaab8, 0xaabe, 0xaabf, 0xaac1, 0xaac1, 0xaaec, 0xaaed, 0xaaf6, 0xaaf6, 0xabe5, 0xabe5, 0xabe8, 0xabe8, 0xabed, 0xabed, 0xfb1e, 0xfb1e, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0xff9e, 0xff9f, 0x101fd, 0x101fd, 0x10a01, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10a38, 0x10a3a, 0x10a3f, 0x10a3f, 0x11001, 0x11001, 0x11038, 0x11046, 0x11080, 0x11081, 0x110b3, 0x110b6, 0x110b9, 0x110ba, 0x11100, 0x11102, 0x11127, 0x1112b, 0x1112d, 0x11134, 0x11180, 0x11181, 0x111b6, 0x111be, 0x116ab, 0x116ab, 0x116ad, 0x116ad, 0x116b0, 0x116b5, 0x116b7, 0x116b7, 0x16f8f, 0x16f92, 0x1d165, 0x1d165, 0x1d167, 0x1d169, 0x1d16e, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0x1d242, 0x1d244, 0xe0100, 0xe01ef, }; /* CR_Grapheme_Extend */ /* 'Grapheme_Base': Derived Property */ static const OnigCodePoint CR_Grapheme_Base[] = { 643, 0x0020, 0x007e, 0x00a0, 0x00ac, 0x00ae, 0x02ff, 0x0370, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0482, 0x048a, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x058f, 0x058f, 0x05be, 0x05be, 0x05c0, 0x05c0, 0x05c3, 0x05c3, 0x05c6, 0x05c6, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0606, 0x060f, 0x061b, 0x061b, 0x061e, 0x064a, 0x0660, 0x066f, 0x0671, 0x06d5, 0x06de, 0x06de, 0x06e5, 0x06e6, 0x06e9, 0x06e9, 0x06ee, 0x070d, 0x0710, 0x0710, 0x0712, 0x072f, 0x074d, 0x07a5, 0x07b1, 0x07b1, 0x07c0, 0x07ea, 0x07f4, 0x07fa, 0x0800, 0x0815, 0x081a, 0x081a, 0x0824, 0x0824, 0x0828, 0x0828, 0x0830, 0x083e, 0x0840, 0x0858, 0x085e, 0x085e, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x0903, 0x0939, 0x093b, 0x093b, 0x093d, 0x0940, 0x0949, 0x094c, 0x094e, 0x0950, 0x0958, 0x0961, 0x0964, 0x0977, 0x0979, 0x097f, 0x0982, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bd, 0x09bd, 0x09bf, 0x09c0, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09ce, 0x09ce, 0x09dc, 0x09dd, 0x09df, 0x09e1, 0x09e6, 0x09fb, 0x0a03, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3e, 0x0a40, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a6f, 0x0a72, 0x0a74, 0x0a83, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abd, 0x0ac0, 0x0ac9, 0x0ac9, 0x0acb, 0x0acc, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae1, 0x0ae6, 0x0af1, 0x0b02, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3d, 0x0b3d, 0x0b40, 0x0b40, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b77, 0x0b83, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbf, 0x0bbf, 0x0bc1, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd0, 0x0bd0, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c3d, 0x0c41, 0x0c44, 0x0c58, 0x0c59, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbe, 0x0cc0, 0x0cc1, 0x0cc3, 0x0cc4, 0x0cc7, 0x0cc8, 0x0cca, 0x0ccb, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d3d, 0x0d3f, 0x0d40, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d4e, 0x0d4e, 0x0d60, 0x0d61, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dd0, 0x0dd1, 0x0dd8, 0x0dde, 0x0df2, 0x0df4, 0x0e01, 0x0e30, 0x0e32, 0x0e33, 0x0e3f, 0x0e46, 0x0e4f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb0, 0x0eb2, 0x0eb3, 0x0ebd, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f17, 0x0f1a, 0x0f34, 0x0f36, 0x0f36, 0x0f38, 0x0f38, 0x0f3a, 0x0f47, 0x0f49, 0x0f6c, 0x0f7f, 0x0f7f, 0x0f85, 0x0f85, 0x0f88, 0x0f8c, 0x0fbe, 0x0fc5, 0x0fc7, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x102c, 0x1031, 0x1031, 0x1038, 0x1038, 0x103b, 0x103c, 0x103f, 0x1057, 0x105a, 0x105d, 0x1061, 0x1070, 0x1075, 0x1081, 0x1083, 0x1084, 0x1087, 0x108c, 0x108e, 0x109c, 0x109e, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x1360, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1711, 0x1720, 0x1731, 0x1735, 0x1736, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, 0x1780, 0x17b3, 0x17b6, 0x17b6, 0x17be, 0x17c5, 0x17c7, 0x17c8, 0x17d4, 0x17dc, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180a, 0x180e, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a8, 0x18aa, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1923, 0x1926, 0x1929, 0x192b, 0x1930, 0x1931, 0x1933, 0x1938, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a16, 0x1a19, 0x1a1b, 0x1a1e, 0x1a55, 0x1a57, 0x1a57, 0x1a61, 0x1a61, 0x1a63, 0x1a64, 0x1a6d, 0x1a72, 0x1a80, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b04, 0x1b33, 0x1b35, 0x1b35, 0x1b3b, 0x1b3b, 0x1b3d, 0x1b41, 0x1b43, 0x1b4b, 0x1b50, 0x1b6a, 0x1b74, 0x1b7c, 0x1b82, 0x1ba1, 0x1ba6, 0x1ba7, 0x1baa, 0x1baa, 0x1bac, 0x1be5, 0x1be7, 0x1be7, 0x1bea, 0x1bec, 0x1bee, 0x1bee, 0x1bf2, 0x1bf3, 0x1bfc, 0x1c2b, 0x1c34, 0x1c35, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd3, 0x1cd3, 0x1ce1, 0x1ce1, 0x1ce9, 0x1cec, 0x1cee, 0x1cf3, 0x1cf5, 0x1cf6, 0x1d00, 0x1dbf, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x200a, 0x2010, 0x2027, 0x202f, 0x205f, 0x2070, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cee, 0x2cf2, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2e00, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x3029, 0x3030, 0x303f, 0x3041, 0x3096, 0x309b, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa66e, 0xa673, 0xa673, 0xa67e, 0xa697, 0xa6a0, 0xa6ef, 0xa6f2, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, 0xa80c, 0xa824, 0xa827, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c3, 0xa8ce, 0xa8d9, 0xa8f2, 0xa8fb, 0xa900, 0xa925, 0xa92e, 0xa946, 0xa952, 0xa953, 0xa95f, 0xa97c, 0xa983, 0xa9b2, 0xa9b4, 0xa9b5, 0xa9ba, 0xa9bb, 0xa9bd, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa28, 0xaa2f, 0xaa30, 0xaa33, 0xaa34, 0xaa40, 0xaa42, 0xaa44, 0xaa4b, 0xaa4d, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaaaf, 0xaab1, 0xaab1, 0xaab5, 0xaab6, 0xaab9, 0xaabd, 0xaac0, 0xaac0, 0xaac2, 0xaac2, 0xaadb, 0xaaeb, 0xaaee, 0xaaf5, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabe4, 0xabe6, 0xabe7, 0xabe9, 0xabec, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb1d, 0xfb1f, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfd, 0xfe10, 0xfe19, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xff01, 0xff9d, 0xffa0, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfffc, 0xfffd, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fc, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a00, 0x10a10, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a40, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x11000, 0x11002, 0x11037, 0x11047, 0x1104d, 0x11052, 0x1106f, 0x11082, 0x110b2, 0x110b7, 0x110b8, 0x110bb, 0x110bc, 0x110be, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11103, 0x11126, 0x1112c, 0x1112c, 0x11136, 0x11143, 0x11182, 0x111b5, 0x111bf, 0x111c8, 0x111d0, 0x111d9, 0x11680, 0x116aa, 0x116ac, 0x116ac, 0x116ae, 0x116af, 0x116b6, 0x116b6, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f93, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d164, 0x1d166, 0x1d166, 0x1d16a, 0x1d16d, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1dd, 0x1d200, 0x1d241, 0x1d245, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Grapheme_Base */ /* 'Grapheme_Link': Derived Property */ static const OnigCodePoint CR_Grapheme_Link[] = { 33, 0x094d, 0x094d, 0x09cd, 0x09cd, 0x0a4d, 0x0a4d, 0x0acd, 0x0acd, 0x0b4d, 0x0b4d, 0x0bcd, 0x0bcd, 0x0c4d, 0x0c4d, 0x0ccd, 0x0ccd, 0x0d4d, 0x0d4d, 0x0dca, 0x0dca, 0x0e3a, 0x0e3a, 0x0f84, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1714, 0x1734, 0x1734, 0x17d2, 0x17d2, 0x1a60, 0x1a60, 0x1b44, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0x2d7f, 0xa806, 0xa806, 0xa8c4, 0xa8c4, 0xa953, 0xa953, 0xa9c0, 0xa9c0, 0xaaf6, 0xaaf6, 0xabed, 0xabed, 0x10a3f, 0x10a3f, 0x11046, 0x11046, 0x110b9, 0x110b9, 0x11133, 0x11134, 0x111c0, 0x111c0, 0x116b6, 0x116b6, }; /* CR_Grapheme_Link */ /* 'Common': Script */ static const OnigCodePoint CR_Common[] = { 157, 0x0000, 0x0040, 0x005b, 0x0060, 0x007b, 0x00a9, 0x00ab, 0x00b9, 0x00bb, 0x00bf, 0x00d7, 0x00d7, 0x00f7, 0x00f7, 0x02b9, 0x02df, 0x02e5, 0x02e9, 0x02ec, 0x02ff, 0x0374, 0x0374, 0x037e, 0x037e, 0x0385, 0x0385, 0x0387, 0x0387, 0x0589, 0x0589, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0640, 0x0640, 0x0660, 0x0669, 0x06dd, 0x06dd, 0x0964, 0x0965, 0x0e3f, 0x0e3f, 0x0fd5, 0x0fd8, 0x10fb, 0x10fb, 0x16eb, 0x16ed, 0x1735, 0x1736, 0x1802, 0x1803, 0x1805, 0x1805, 0x1cd3, 0x1cd3, 0x1ce1, 0x1ce1, 0x1ce9, 0x1cec, 0x1cee, 0x1cf3, 0x1cf5, 0x1cf6, 0x2000, 0x200b, 0x200e, 0x2064, 0x206a, 0x2070, 0x2074, 0x207e, 0x2080, 0x208e, 0x20a0, 0x20b9, 0x2100, 0x2125, 0x2127, 0x2129, 0x212c, 0x2131, 0x2133, 0x214d, 0x214f, 0x215f, 0x2189, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x27ff, 0x2900, 0x2b4c, 0x2b50, 0x2b59, 0x2e00, 0x2e3b, 0x2ff0, 0x2ffb, 0x3000, 0x3004, 0x3006, 0x3006, 0x3008, 0x3020, 0x3030, 0x3037, 0x303c, 0x303f, 0x309b, 0x309c, 0x30a0, 0x30a0, 0x30fb, 0x30fc, 0x3190, 0x319f, 0x31c0, 0x31e3, 0x3220, 0x325f, 0x327f, 0x32cf, 0x3358, 0x33ff, 0x4dc0, 0x4dff, 0xa700, 0xa721, 0xa788, 0xa78a, 0xa830, 0xa839, 0xfd3e, 0xfd3f, 0xfdfd, 0xfdfd, 0xfe10, 0xfe19, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfeff, 0xfeff, 0xff01, 0xff20, 0xff3b, 0xff40, 0xff5b, 0xff65, 0xff70, 0xff70, 0xff9e, 0xff9f, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xfffd, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1013f, 0x10190, 0x1019b, 0x101d0, 0x101fc, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d166, 0x1d16a, 0x1d17a, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1dd, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f1ff, 0x1f201, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0xe0001, 0xe0001, 0xe0020, 0xe007f, }; /* CR_Common */ /* 'Latin': Script */ static const OnigCodePoint CR_Latin[] = { 30, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00ba, 0x00ba, 0x00c0, 0x00d6, 0x00d8, 0x00f6, 0x00f8, 0x02b8, 0x02e0, 0x02e4, 0x1d00, 0x1d25, 0x1d2c, 0x1d5c, 0x1d62, 0x1d65, 0x1d6b, 0x1d77, 0x1d79, 0x1dbe, 0x1e00, 0x1eff, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x212a, 0x212b, 0x2132, 0x2132, 0x214e, 0x214e, 0x2160, 0x2188, 0x2c60, 0x2c7f, 0xa722, 0xa787, 0xa78b, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa7ff, 0xfb00, 0xfb06, 0xff21, 0xff3a, 0xff41, 0xff5a, }; /* CR_Latin */ /* 'Greek': Script */ static const OnigCodePoint CR_Greek[] = { 33, 0x0370, 0x0373, 0x0375, 0x0377, 0x037a, 0x037d, 0x0384, 0x0384, 0x0386, 0x0386, 0x0388, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03e1, 0x03f0, 0x03ff, 0x1d26, 0x1d2a, 0x1d5d, 0x1d61, 0x1d66, 0x1d6a, 0x1dbf, 0x1dbf, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2126, 0x2126, 0x10140, 0x1018a, 0x1d200, 0x1d245, }; /* CR_Greek */ /* 'Cyrillic': Script */ static const OnigCodePoint CR_Cyrillic[] = { 7, 0x0400, 0x0484, 0x0487, 0x0527, 0x1d2b, 0x1d2b, 0x1d78, 0x1d78, 0x2de0, 0x2dff, 0xa640, 0xa697, 0xa69f, 0xa69f, }; /* CR_Cyrillic */ /* 'Armenian': Script */ static const OnigCodePoint CR_Armenian[] = { 6, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x058a, 0x058a, 0x058f, 0x058f, 0xfb13, 0xfb17, }; /* CR_Armenian */ /* 'Hebrew': Script */ static const OnigCodePoint CR_Hebrew[] = { 9, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfb4f, }; /* CR_Hebrew */ /* 'Arabic': Script */ static const OnigCodePoint CR_Arabic[] = { 56, 0x0600, 0x0604, 0x0606, 0x060b, 0x060d, 0x061a, 0x061e, 0x061e, 0x0620, 0x063f, 0x0641, 0x064a, 0x0656, 0x065e, 0x066a, 0x066f, 0x0671, 0x06dc, 0x06de, 0x06ff, 0x0750, 0x077f, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0xfb50, 0xfbc1, 0xfbd3, 0xfd3d, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfc, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0x10e60, 0x10e7e, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, }; /* CR_Arabic */ /* 'Syriac': Script */ static const OnigCodePoint CR_Syriac[] = { 3, 0x0700, 0x070d, 0x070f, 0x074a, 0x074d, 0x074f, }; /* CR_Syriac */ /* 'Thaana': Script */ static const OnigCodePoint CR_Thaana[] = { 1, 0x0780, 0x07b1, }; /* CR_Thaana */ /* 'Devanagari': Script */ static const OnigCodePoint CR_Devanagari[] = { 5, 0x0900, 0x0950, 0x0953, 0x0963, 0x0966, 0x0977, 0x0979, 0x097f, 0xa8e0, 0xa8fb, }; /* CR_Devanagari */ /* 'Bengali': Script */ static const OnigCodePoint CR_Bengali[] = { 14, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, }; /* CR_Bengali */ /* 'Gurmukhi': Script */ static const OnigCodePoint CR_Gurmukhi[] = { 16, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, }; /* CR_Gurmukhi */ /* 'Gujarati': Script */ static const OnigCodePoint CR_Gujarati[] = { 13, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, }; /* CR_Gujarati */ /* 'Oriya': Script */ static const OnigCodePoint CR_Oriya[] = { 14, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, }; /* CR_Oriya */ /* 'Tamil': Script */ static const OnigCodePoint CR_Tamil[] = { 16, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, }; /* CR_Tamil */ /* 'Telugu': Script */ static const OnigCodePoint CR_Telugu[] = { 14, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, }; /* CR_Telugu */ /* 'Kannada': Script */ static const OnigCodePoint CR_Kannada[] = { 14, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, }; /* CR_Kannada */ /* 'Malayalam': Script */ static const OnigCodePoint CR_Malayalam[] = { 11, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, }; /* CR_Malayalam */ /* 'Sinhala': Script */ static const OnigCodePoint CR_Sinhala[] = { 11, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, }; /* CR_Sinhala */ /* 'Thai': Script */ static const OnigCodePoint CR_Thai[] = { 2, 0x0e01, 0x0e3a, 0x0e40, 0x0e5b, }; /* CR_Thai */ /* 'Lao': Script */ static const OnigCodePoint CR_Lao[] = { 18, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, }; /* CR_Lao */ /* 'Tibetan': Script */ static const OnigCodePoint CR_Tibetan[] = { 7, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fd4, 0x0fd9, 0x0fda, }; /* CR_Tibetan */ /* 'Myanmar': Script */ static const OnigCodePoint CR_Myanmar[] = { 2, 0x1000, 0x109f, 0xaa60, 0xaa7b, }; /* CR_Myanmar */ /* 'Georgian': Script */ static const OnigCodePoint CR_Georgian[] = { 8, 0x10a0, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x10fa, 0x10fc, 0x10ff, 0x2d00, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, }; /* CR_Georgian */ /* 'Hangul': Script */ static const OnigCodePoint CR_Hangul[] = { 14, 0x1100, 0x11ff, 0x302e, 0x302f, 0x3131, 0x318e, 0x3200, 0x321e, 0x3260, 0x327e, 0xa960, 0xa97c, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xffa0, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, }; /* CR_Hangul */ /* 'Ethiopic': Script */ static const OnigCodePoint CR_Ethiopic[] = { 32, 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, }; /* CR_Ethiopic */ /* 'Cherokee': Script */ static const OnigCodePoint CR_Cherokee[] = { 1, 0x13a0, 0x13f4, }; /* CR_Cherokee */ /* 'Canadian_Aboriginal': Script */ static const OnigCodePoint CR_Canadian_Aboriginal[] = { 2, 0x1400, 0x167f, 0x18b0, 0x18f5, }; /* CR_Canadian_Aboriginal */ /* 'Ogham': Script */ static const OnigCodePoint CR_Ogham[] = { 1, 0x1680, 0x169c, }; /* CR_Ogham */ /* 'Runic': Script */ static const OnigCodePoint CR_Runic[] = { 2, 0x16a0, 0x16ea, 0x16ee, 0x16f0, }; /* CR_Runic */ /* 'Khmer': Script */ static const OnigCodePoint CR_Khmer[] = { 4, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x19e0, 0x19ff, }; /* CR_Khmer */ /* 'Mongolian': Script */ static const OnigCodePoint CR_Mongolian[] = { 6, 0x1800, 0x1801, 0x1804, 0x1804, 0x1806, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, }; /* CR_Mongolian */ /* 'Hiragana': Script */ static const OnigCodePoint CR_Hiragana[] = { 4, 0x3041, 0x3096, 0x309d, 0x309f, 0x1b001, 0x1b001, 0x1f200, 0x1f200, }; /* CR_Hiragana */ /* 'Katakana': Script */ static const OnigCodePoint CR_Katakana[] = { 8, 0x30a1, 0x30fa, 0x30fd, 0x30ff, 0x31f0, 0x31ff, 0x32d0, 0x32fe, 0x3300, 0x3357, 0xff66, 0xff6f, 0xff71, 0xff9d, 0x1b000, 0x1b000, }; /* CR_Katakana */ /* 'Bopomofo': Script */ static const OnigCodePoint CR_Bopomofo[] = { 3, 0x02ea, 0x02eb, 0x3105, 0x312d, 0x31a0, 0x31ba, }; /* CR_Bopomofo */ /* 'Han': Script */ static const OnigCodePoint CR_Han[] = { 15, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x3005, 0x3005, 0x3007, 0x3007, 0x3021, 0x3029, 0x3038, 0x303b, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Han */ /* 'Yi': Script */ static const OnigCodePoint CR_Yi[] = { 2, 0xa000, 0xa48c, 0xa490, 0xa4c6, }; /* CR_Yi */ /* 'Old_Italic': Script */ static const OnigCodePoint CR_Old_Italic[] = { 2, 0x10300, 0x1031e, 0x10320, 0x10323, }; /* CR_Old_Italic */ /* 'Gothic': Script */ static const OnigCodePoint CR_Gothic[] = { 1, 0x10330, 0x1034a, }; /* CR_Gothic */ /* 'Deseret': Script */ static const OnigCodePoint CR_Deseret[] = { 1, 0x10400, 0x1044f, }; /* CR_Deseret */ /* 'Inherited': Script */ static const OnigCodePoint CR_Inherited[] = { 25, 0x0300, 0x036f, 0x0485, 0x0486, 0x064b, 0x0655, 0x065f, 0x065f, 0x0670, 0x0670, 0x0951, 0x0952, 0x1cd0, 0x1cd2, 0x1cd4, 0x1ce0, 0x1ce2, 0x1ce8, 0x1ced, 0x1ced, 0x1cf4, 0x1cf4, 0x1dc0, 0x1de6, 0x1dfc, 0x1dff, 0x200c, 0x200d, 0x20d0, 0x20f0, 0x302a, 0x302d, 0x3099, 0x309a, 0xfe00, 0xfe0f, 0xfe20, 0xfe26, 0x101fd, 0x101fd, 0x1d167, 0x1d169, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, 0xe0100, 0xe01ef, }; /* CR_Inherited */ /* 'Tagalog': Script */ static const OnigCodePoint CR_Tagalog[] = { 2, 0x1700, 0x170c, 0x170e, 0x1714, }; /* CR_Tagalog */ /* 'Hanunoo': Script */ static const OnigCodePoint CR_Hanunoo[] = { 1, 0x1720, 0x1734, }; /* CR_Hanunoo */ /* 'Buhid': Script */ static const OnigCodePoint CR_Buhid[] = { 1, 0x1740, 0x1753, }; /* CR_Buhid */ /* 'Tagbanwa': Script */ static const OnigCodePoint CR_Tagbanwa[] = { 3, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, }; /* CR_Tagbanwa */ /* 'Limbu': Script */ static const OnigCodePoint CR_Limbu[] = { 5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x194f, }; /* CR_Limbu */ /* 'Tai_Le': Script */ static const OnigCodePoint CR_Tai_Le[] = { 2, 0x1950, 0x196d, 0x1970, 0x1974, }; /* CR_Tai_Le */ /* 'Linear_B': Script */ static const OnigCodePoint CR_Linear_B[] = { 7, 0x10000, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, }; /* CR_Linear_B */ /* 'Ugaritic': Script */ static const OnigCodePoint CR_Ugaritic[] = { 2, 0x10380, 0x1039d, 0x1039f, 0x1039f, }; /* CR_Ugaritic */ /* 'Shavian': Script */ static const OnigCodePoint CR_Shavian[] = { 1, 0x10450, 0x1047f, }; /* CR_Shavian */ /* 'Osmanya': Script */ static const OnigCodePoint CR_Osmanya[] = { 2, 0x10480, 0x1049d, 0x104a0, 0x104a9, }; /* CR_Osmanya */ /* 'Cypriot': Script */ static const OnigCodePoint CR_Cypriot[] = { 6, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, }; /* CR_Cypriot */ /* 'Braille': Script */ static const OnigCodePoint CR_Braille[] = { 1, 0x2800, 0x28ff, }; /* CR_Braille */ /* 'Buginese': Script */ static const OnigCodePoint CR_Buginese[] = { 2, 0x1a00, 0x1a1b, 0x1a1e, 0x1a1f, }; /* CR_Buginese */ /* 'Coptic': Script */ static const OnigCodePoint CR_Coptic[] = { 3, 0x03e2, 0x03ef, 0x2c80, 0x2cf3, 0x2cf9, 0x2cff, }; /* CR_Coptic */ /* 'New_Tai_Lue': Script */ static const OnigCodePoint CR_New_Tai_Lue[] = { 4, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x19df, }; /* CR_New_Tai_Lue */ /* 'Glagolitic': Script */ static const OnigCodePoint CR_Glagolitic[] = { 2, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, }; /* CR_Glagolitic */ /* 'Tifinagh': Script */ static const OnigCodePoint CR_Tifinagh[] = { 3, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d7f, }; /* CR_Tifinagh */ /* 'Syloti_Nagri': Script */ static const OnigCodePoint CR_Syloti_Nagri[] = { 1, 0xa800, 0xa82b, }; /* CR_Syloti_Nagri */ /* 'Old_Persian': Script */ static const OnigCodePoint CR_Old_Persian[] = { 2, 0x103a0, 0x103c3, 0x103c8, 0x103d5, }; /* CR_Old_Persian */ /* 'Kharoshthi': Script */ static const OnigCodePoint CR_Kharoshthi[] = { 8, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, }; /* CR_Kharoshthi */ /* 'Balinese': Script */ static const OnigCodePoint CR_Balinese[] = { 2, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, }; /* CR_Balinese */ /* 'Cuneiform': Script */ static const OnigCodePoint CR_Cuneiform[] = { 3, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, }; /* CR_Cuneiform */ /* 'Phoenician': Script */ static const OnigCodePoint CR_Phoenician[] = { 2, 0x10900, 0x1091b, 0x1091f, 0x1091f, }; /* CR_Phoenician */ /* 'Phags_Pa': Script */ static const OnigCodePoint CR_Phags_Pa[] = { 1, 0xa840, 0xa877, }; /* CR_Phags_Pa */ /* 'Nko': Script */ static const OnigCodePoint CR_Nko[] = { 1, 0x07c0, 0x07fa, }; /* CR_Nko */ /* 'Sundanese': Script */ static const OnigCodePoint CR_Sundanese[] = { 2, 0x1b80, 0x1bbf, 0x1cc0, 0x1cc7, }; /* CR_Sundanese */ /* 'Lepcha': Script */ static const OnigCodePoint CR_Lepcha[] = { 3, 0x1c00, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c4f, }; /* CR_Lepcha */ /* 'Ol_Chiki': Script */ static const OnigCodePoint CR_Ol_Chiki[] = { 1, 0x1c50, 0x1c7f, }; /* CR_Ol_Chiki */ /* 'Vai': Script */ static const OnigCodePoint CR_Vai[] = { 1, 0xa500, 0xa62b, }; /* CR_Vai */ /* 'Saurashtra': Script */ static const OnigCodePoint CR_Saurashtra[] = { 2, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, }; /* CR_Saurashtra */ /* 'Kayah_Li': Script */ static const OnigCodePoint CR_Kayah_Li[] = { 1, 0xa900, 0xa92f, }; /* CR_Kayah_Li */ /* 'Rejang': Script */ static const OnigCodePoint CR_Rejang[] = { 2, 0xa930, 0xa953, 0xa95f, 0xa95f, }; /* CR_Rejang */ /* 'Lycian': Script */ static const OnigCodePoint CR_Lycian[] = { 1, 0x10280, 0x1029c, }; /* CR_Lycian */ /* 'Carian': Script */ static const OnigCodePoint CR_Carian[] = { 1, 0x102a0, 0x102d0, }; /* CR_Carian */ /* 'Lydian': Script */ static const OnigCodePoint CR_Lydian[] = { 2, 0x10920, 0x10939, 0x1093f, 0x1093f, }; /* CR_Lydian */ /* 'Cham': Script */ static const OnigCodePoint CR_Cham[] = { 4, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa5f, }; /* CR_Cham */ /* 'Tai_Tham': Script */ static const OnigCodePoint CR_Tai_Tham[] = { 5, 0x1a20, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, }; /* CR_Tai_Tham */ /* 'Tai_Viet': Script */ static const OnigCodePoint CR_Tai_Viet[] = { 2, 0xaa80, 0xaac2, 0xaadb, 0xaadf, }; /* CR_Tai_Viet */ /* 'Avestan': Script */ static const OnigCodePoint CR_Avestan[] = { 2, 0x10b00, 0x10b35, 0x10b39, 0x10b3f, }; /* CR_Avestan */ /* 'Egyptian_Hieroglyphs': Script */ static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = { 1, 0x13000, 0x1342e, }; /* CR_Egyptian_Hieroglyphs */ /* 'Samaritan': Script */ static const OnigCodePoint CR_Samaritan[] = { 2, 0x0800, 0x082d, 0x0830, 0x083e, }; /* CR_Samaritan */ /* 'Lisu': Script */ static const OnigCodePoint CR_Lisu[] = { 1, 0xa4d0, 0xa4ff, }; /* CR_Lisu */ /* 'Bamum': Script */ static const OnigCodePoint CR_Bamum[] = { 2, 0xa6a0, 0xa6f7, 0x16800, 0x16a38, }; /* CR_Bamum */ /* 'Javanese': Script */ static const OnigCodePoint CR_Javanese[] = { 3, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, }; /* CR_Javanese */ /* 'Meetei_Mayek': Script */ static const OnigCodePoint CR_Meetei_Mayek[] = { 3, 0xaae0, 0xaaf6, 0xabc0, 0xabed, 0xabf0, 0xabf9, }; /* CR_Meetei_Mayek */ /* 'Imperial_Aramaic': Script */ static const OnigCodePoint CR_Imperial_Aramaic[] = { 2, 0x10840, 0x10855, 0x10857, 0x1085f, }; /* CR_Imperial_Aramaic */ /* 'Old_South_Arabian': Script */ static const OnigCodePoint CR_Old_South_Arabian[] = { 1, 0x10a60, 0x10a7f, }; /* CR_Old_South_Arabian */ /* 'Inscriptional_Parthian': Script */ static const OnigCodePoint CR_Inscriptional_Parthian[] = { 2, 0x10b40, 0x10b55, 0x10b58, 0x10b5f, }; /* CR_Inscriptional_Parthian */ /* 'Inscriptional_Pahlavi': Script */ static const OnigCodePoint CR_Inscriptional_Pahlavi[] = { 2, 0x10b60, 0x10b72, 0x10b78, 0x10b7f, }; /* CR_Inscriptional_Pahlavi */ /* 'Old_Turkic': Script */ static const OnigCodePoint CR_Old_Turkic[] = { 1, 0x10c00, 0x10c48, }; /* CR_Old_Turkic */ /* 'Kaithi': Script */ static const OnigCodePoint CR_Kaithi[] = { 1, 0x11080, 0x110c1, }; /* CR_Kaithi */ /* 'Batak': Script */ static const OnigCodePoint CR_Batak[] = { 2, 0x1bc0, 0x1bf3, 0x1bfc, 0x1bff, }; /* CR_Batak */ /* 'Brahmi': Script */ static const OnigCodePoint CR_Brahmi[] = { 2, 0x11000, 0x1104d, 0x11052, 0x1106f, }; /* CR_Brahmi */ /* 'Mandaic': Script */ static const OnigCodePoint CR_Mandaic[] = { 2, 0x0840, 0x085b, 0x085e, 0x085e, }; /* CR_Mandaic */ /* 'Chakma': Script */ static const OnigCodePoint CR_Chakma[] = { 2, 0x11100, 0x11134, 0x11136, 0x11143, }; /* CR_Chakma */ /* 'Meroitic_Cursive': Script */ static const OnigCodePoint CR_Meroitic_Cursive[] = { 2, 0x109a0, 0x109b7, 0x109be, 0x109bf, }; /* CR_Meroitic_Cursive */ /* 'Meroitic_Hieroglyphs': Script */ static const OnigCodePoint CR_Meroitic_Hieroglyphs[] = { 1, 0x10980, 0x1099f, }; /* CR_Meroitic_Hieroglyphs */ /* 'Miao': Script */ static const OnigCodePoint CR_Miao[] = { 3, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, }; /* CR_Miao */ /* 'Sharada': Script */ static const OnigCodePoint CR_Sharada[] = { 2, 0x11180, 0x111c8, 0x111d0, 0x111d9, }; /* CR_Sharada */ /* 'Sora_Sompeng': Script */ static const OnigCodePoint CR_Sora_Sompeng[] = { 2, 0x110d0, 0x110e8, 0x110f0, 0x110f9, }; /* CR_Sora_Sompeng */ /* 'Takri': Script */ static const OnigCodePoint CR_Takri[] = { 2, 0x11680, 0x116b7, 0x116c0, 0x116c9, }; /* CR_Takri */ /* 'White_Space': Binary Property */ #define CR_White_Space CR_Space /* 'Bidi_Control': Binary Property */ static const OnigCodePoint CR_Bidi_Control[] = { 2, 0x200e, 0x200f, 0x202a, 0x202e, }; /* CR_Bidi_Control */ /* 'Join_Control': Binary Property */ static const OnigCodePoint CR_Join_Control[] = { 1, 0x200c, 0x200d, }; /* CR_Join_Control */ /* 'Dash': Binary Property */ static const OnigCodePoint CR_Dash[] = { 20, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, 0x1400, 0x1400, 0x1806, 0x1806, 0x2010, 0x2015, 0x2053, 0x2053, 0x207b, 0x207b, 0x208b, 0x208b, 0x2212, 0x2212, 0x2e17, 0x2e17, 0x2e1a, 0x2e1a, 0x2e3a, 0x2e3b, 0x301c, 0x301c, 0x3030, 0x3030, 0x30a0, 0x30a0, 0xfe31, 0xfe32, 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, }; /* CR_Dash */ /* 'Hyphen': Binary Property */ static const OnigCodePoint CR_Hyphen[] = { 10, 0x002d, 0x002d, 0x00ad, 0x00ad, 0x058a, 0x058a, 0x1806, 0x1806, 0x2010, 0x2011, 0x2e17, 0x2e17, 0x30fb, 0x30fb, 0xfe63, 0xfe63, 0xff0d, 0xff0d, 0xff65, 0xff65, }; /* CR_Hyphen */ /* 'Quotation_Mark': Binary Property */ static const OnigCodePoint CR_Quotation_Mark[] = { 12, 0x0022, 0x0022, 0x0027, 0x0027, 0x00ab, 0x00ab, 0x00bb, 0x00bb, 0x2018, 0x201f, 0x2039, 0x203a, 0x300c, 0x300f, 0x301d, 0x301f, 0xfe41, 0xfe44, 0xff02, 0xff02, 0xff07, 0xff07, 0xff62, 0xff63, }; /* CR_Quotation_Mark */ /* 'Terminal_Punctuation': Binary Property */ static const OnigCodePoint CR_Terminal_Punctuation[] = { 70, 0x0021, 0x0021, 0x002c, 0x002c, 0x002e, 0x002e, 0x003a, 0x003b, 0x003f, 0x003f, 0x037e, 0x037e, 0x0387, 0x0387, 0x0589, 0x0589, 0x05c3, 0x05c3, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x06d4, 0x06d4, 0x0700, 0x070a, 0x070c, 0x070c, 0x07f8, 0x07f9, 0x0830, 0x083e, 0x085e, 0x085e, 0x0964, 0x0965, 0x0e5a, 0x0e5b, 0x0f08, 0x0f08, 0x0f0d, 0x0f12, 0x104a, 0x104b, 0x1361, 0x1368, 0x166d, 0x166e, 0x16eb, 0x16ed, 0x17d4, 0x17d6, 0x17da, 0x17da, 0x1802, 0x1805, 0x1808, 0x1809, 0x1944, 0x1945, 0x1aa8, 0x1aab, 0x1b5a, 0x1b5b, 0x1b5d, 0x1b5f, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, 0x203c, 0x203d, 0x2047, 0x2049, 0x2e2e, 0x2e2e, 0x3001, 0x3002, 0xa4fe, 0xa4ff, 0xa60d, 0xa60f, 0xa6f3, 0xa6f7, 0xa876, 0xa877, 0xa8ce, 0xa8cf, 0xa92f, 0xa92f, 0xa9c7, 0xa9c9, 0xaa5d, 0xaa5f, 0xaadf, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, 0xfe50, 0xfe52, 0xfe54, 0xfe57, 0xff01, 0xff01, 0xff0c, 0xff0c, 0xff0e, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff1f, 0xff61, 0xff61, 0xff64, 0xff64, 0x1039f, 0x1039f, 0x103d0, 0x103d0, 0x10857, 0x10857, 0x1091f, 0x1091f, 0x10b3a, 0x10b3f, 0x11047, 0x1104d, 0x110be, 0x110c1, 0x11141, 0x11143, 0x111c5, 0x111c6, 0x12470, 0x12473, }; /* CR_Terminal_Punctuation */ /* 'Other_Math': Binary Property */ static const OnigCodePoint CR_Other_Math[] = { 133, 0x005e, 0x005e, 0x03d0, 0x03d2, 0x03d5, 0x03d5, 0x03f0, 0x03f1, 0x03f4, 0x03f5, 0x2016, 0x2016, 0x2032, 0x2034, 0x2040, 0x2040, 0x2061, 0x2064, 0x207d, 0x207e, 0x208d, 0x208e, 0x20d0, 0x20dc, 0x20e1, 0x20e1, 0x20e5, 0x20e6, 0x20eb, 0x20ef, 0x2102, 0x2102, 0x2107, 0x2107, 0x210a, 0x2113, 0x2115, 0x2115, 0x2119, 0x211d, 0x2124, 0x2124, 0x2128, 0x2129, 0x212c, 0x212d, 0x212f, 0x2131, 0x2133, 0x2138, 0x213c, 0x213f, 0x2145, 0x2149, 0x2195, 0x2199, 0x219c, 0x219f, 0x21a1, 0x21a2, 0x21a4, 0x21a5, 0x21a7, 0x21a7, 0x21a9, 0x21ad, 0x21b0, 0x21b1, 0x21b6, 0x21b7, 0x21bc, 0x21cd, 0x21d0, 0x21d1, 0x21d3, 0x21d3, 0x21d5, 0x21db, 0x21dd, 0x21dd, 0x21e4, 0x21e5, 0x23b4, 0x23b5, 0x23b7, 0x23b7, 0x23d0, 0x23d0, 0x23e2, 0x23e2, 0x25a0, 0x25a1, 0x25ae, 0x25b6, 0x25bc, 0x25c0, 0x25c6, 0x25c7, 0x25ca, 0x25cb, 0x25cf, 0x25d3, 0x25e2, 0x25e2, 0x25e4, 0x25e4, 0x25e7, 0x25ec, 0x2605, 0x2606, 0x2640, 0x2640, 0x2642, 0x2642, 0x2660, 0x2663, 0x266d, 0x266e, 0x27c5, 0x27c6, 0x27e6, 0x27ef, 0x2983, 0x2998, 0x29d8, 0x29db, 0x29fc, 0x29fd, 0xfe61, 0xfe61, 0xfe63, 0xfe63, 0xfe68, 0xfe68, 0xff3c, 0xff3c, 0xff3e, 0xff3e, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d6c0, 0x1d6c2, 0x1d6da, 0x1d6dc, 0x1d6fa, 0x1d6fc, 0x1d714, 0x1d716, 0x1d734, 0x1d736, 0x1d74e, 0x1d750, 0x1d76e, 0x1d770, 0x1d788, 0x1d78a, 0x1d7a8, 0x1d7aa, 0x1d7c2, 0x1d7c4, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, }; /* CR_Other_Math */ /* 'Hex_Digit': Binary Property */ static const OnigCodePoint CR_Hex_Digit[] = { 6, 0x0030, 0x0039, 0x0041, 0x0046, 0x0061, 0x0066, 0xff10, 0xff19, 0xff21, 0xff26, 0xff41, 0xff46, }; /* CR_Hex_Digit */ /* 'ASCII_Hex_Digit': Binary Property */ #define CR_ASCII_Hex_Digit CR_XDigit /* 'Other_Alphabetic': Binary Property */ static const OnigCodePoint CR_Other_Alphabetic[] = { 158, 0x0345, 0x0345, 0x05b0, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c5, 0x05c7, 0x05c7, 0x0610, 0x061a, 0x064b, 0x0657, 0x0659, 0x065f, 0x0670, 0x0670, 0x06d6, 0x06dc, 0x06e1, 0x06e4, 0x06e7, 0x06e8, 0x06ed, 0x06ed, 0x0711, 0x0711, 0x0730, 0x073f, 0x07a6, 0x07b0, 0x0816, 0x0817, 0x081b, 0x0823, 0x0825, 0x0827, 0x0829, 0x082c, 0x08e4, 0x08e9, 0x08f0, 0x08fe, 0x0900, 0x0903, 0x093a, 0x093b, 0x093e, 0x094c, 0x094e, 0x094f, 0x0955, 0x0957, 0x0962, 0x0963, 0x0981, 0x0983, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cc, 0x09d7, 0x09d7, 0x09e2, 0x09e3, 0x0a01, 0x0a03, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4c, 0x0a51, 0x0a51, 0x0a70, 0x0a71, 0x0a75, 0x0a75, 0x0a81, 0x0a83, 0x0abe, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acc, 0x0ae2, 0x0ae3, 0x0b01, 0x0b03, 0x0b3e, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4c, 0x0b56, 0x0b57, 0x0b62, 0x0b63, 0x0b82, 0x0b82, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcc, 0x0bd7, 0x0bd7, 0x0c01, 0x0c03, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4c, 0x0c55, 0x0c56, 0x0c62, 0x0c63, 0x0c82, 0x0c83, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccc, 0x0cd5, 0x0cd6, 0x0ce2, 0x0ce3, 0x0d02, 0x0d03, 0x0d3e, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4c, 0x0d57, 0x0d57, 0x0d62, 0x0d63, 0x0d82, 0x0d83, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df3, 0x0e31, 0x0e31, 0x0e34, 0x0e3a, 0x0e4d, 0x0e4d, 0x0eb1, 0x0eb1, 0x0eb4, 0x0eb9, 0x0ebb, 0x0ebc, 0x0ecd, 0x0ecd, 0x0f71, 0x0f81, 0x0f8d, 0x0f97, 0x0f99, 0x0fbc, 0x102b, 0x1036, 0x1038, 0x1038, 0x103b, 0x103e, 0x1056, 0x1059, 0x105e, 0x1060, 0x1062, 0x1062, 0x1067, 0x1068, 0x1071, 0x1074, 0x1082, 0x1086, 0x109c, 0x109d, 0x135f, 0x135f, 0x1712, 0x1713, 0x1732, 0x1733, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b6, 0x17c8, 0x18a9, 0x18a9, 0x1920, 0x192b, 0x1930, 0x1938, 0x19b0, 0x19c0, 0x19c8, 0x19c9, 0x1a17, 0x1a1b, 0x1a55, 0x1a5e, 0x1a61, 0x1a74, 0x1b00, 0x1b04, 0x1b35, 0x1b43, 0x1b80, 0x1b82, 0x1ba1, 0x1ba9, 0x1bac, 0x1bad, 0x1be7, 0x1bf1, 0x1c24, 0x1c35, 0x1cf2, 0x1cf3, 0x24b6, 0x24e9, 0x2de0, 0x2dff, 0xa674, 0xa67b, 0xa69f, 0xa69f, 0xa823, 0xa827, 0xa880, 0xa881, 0xa8b4, 0xa8c3, 0xa926, 0xa92a, 0xa947, 0xa952, 0xa980, 0xa983, 0xa9b4, 0xa9bf, 0xaa29, 0xaa36, 0xaa43, 0xaa43, 0xaa4c, 0xaa4d, 0xaab0, 0xaab0, 0xaab2, 0xaab4, 0xaab7, 0xaab8, 0xaabe, 0xaabe, 0xaaeb, 0xaaef, 0xaaf5, 0xaaf5, 0xabe3, 0xabea, 0xfb1e, 0xfb1e, 0x10a01, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x11000, 0x11002, 0x11038, 0x11045, 0x11082, 0x11082, 0x110b0, 0x110b8, 0x11100, 0x11102, 0x11127, 0x11132, 0x11180, 0x11182, 0x111b3, 0x111bf, 0x116ab, 0x116b5, 0x16f51, 0x16f7e, }; /* CR_Other_Alphabetic */ /* 'Ideographic': Binary Property */ static const OnigCodePoint CR_Ideographic[] = { 11, 0x3006, 0x3007, 0x3021, 0x3029, 0x3038, 0x303a, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xf900, 0xfa6d, 0xfa70, 0xfad9, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, }; /* CR_Ideographic */ /* 'Diacritic': Binary Property */ static const OnigCodePoint CR_Diacritic[] = { 125, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, 0x00af, 0x00af, 0x00b4, 0x00b4, 0x00b7, 0x00b8, 0x02b0, 0x034e, 0x0350, 0x0357, 0x035d, 0x0362, 0x0374, 0x0375, 0x037a, 0x037a, 0x0384, 0x0385, 0x0483, 0x0487, 0x0559, 0x0559, 0x0591, 0x05a1, 0x05a3, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, 0x05c4, 0x05c4, 0x064b, 0x0652, 0x0657, 0x0658, 0x06df, 0x06e0, 0x06e5, 0x06e6, 0x06ea, 0x06ec, 0x0730, 0x074a, 0x07a6, 0x07b0, 0x07eb, 0x07f5, 0x0818, 0x0819, 0x08e4, 0x08fe, 0x093c, 0x093c, 0x094d, 0x094d, 0x0951, 0x0954, 0x0971, 0x0971, 0x09bc, 0x09bc, 0x09cd, 0x09cd, 0x0a3c, 0x0a3c, 0x0a4d, 0x0a4d, 0x0abc, 0x0abc, 0x0acd, 0x0acd, 0x0b3c, 0x0b3c, 0x0b4d, 0x0b4d, 0x0bcd, 0x0bcd, 0x0c4d, 0x0c4d, 0x0cbc, 0x0cbc, 0x0ccd, 0x0ccd, 0x0d4d, 0x0d4d, 0x0dca, 0x0dca, 0x0e47, 0x0e4c, 0x0e4e, 0x0e4e, 0x0ec8, 0x0ecc, 0x0f18, 0x0f19, 0x0f35, 0x0f35, 0x0f37, 0x0f37, 0x0f39, 0x0f39, 0x0f3e, 0x0f3f, 0x0f82, 0x0f84, 0x0f86, 0x0f87, 0x0fc6, 0x0fc6, 0x1037, 0x1037, 0x1039, 0x103a, 0x1087, 0x108d, 0x108f, 0x108f, 0x109a, 0x109b, 0x17c9, 0x17d3, 0x17dd, 0x17dd, 0x1939, 0x193b, 0x1a75, 0x1a7c, 0x1a7f, 0x1a7f, 0x1b34, 0x1b34, 0x1b44, 0x1b44, 0x1b6b, 0x1b73, 0x1baa, 0x1bab, 0x1c36, 0x1c37, 0x1c78, 0x1c7d, 0x1cd0, 0x1ce8, 0x1ced, 0x1ced, 0x1cf4, 0x1cf4, 0x1d2c, 0x1d6a, 0x1dc4, 0x1dcf, 0x1dfd, 0x1dff, 0x1fbd, 0x1fbd, 0x1fbf, 0x1fc1, 0x1fcd, 0x1fcf, 0x1fdd, 0x1fdf, 0x1fed, 0x1fef, 0x1ffd, 0x1ffe, 0x2cef, 0x2cf1, 0x2e2f, 0x2e2f, 0x302a, 0x302f, 0x3099, 0x309c, 0x30fc, 0x30fc, 0xa66f, 0xa66f, 0xa67c, 0xa67d, 0xa67f, 0xa67f, 0xa6f0, 0xa6f1, 0xa717, 0xa721, 0xa788, 0xa788, 0xa7f8, 0xa7f9, 0xa8c4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa92b, 0xa92e, 0xa953, 0xa953, 0xa9b3, 0xa9b3, 0xa9c0, 0xa9c0, 0xaa7b, 0xaa7b, 0xaabf, 0xaac2, 0xaaf6, 0xaaf6, 0xabec, 0xabed, 0xfb1e, 0xfb1e, 0xfe20, 0xfe26, 0xff3e, 0xff3e, 0xff40, 0xff40, 0xff70, 0xff70, 0xff9e, 0xff9f, 0xffe3, 0xffe3, 0x110b9, 0x110ba, 0x11133, 0x11134, 0x111c0, 0x111c0, 0x116b6, 0x116b7, 0x16f8f, 0x16f9f, 0x1d167, 0x1d169, 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, }; /* CR_Diacritic */ /* 'Extender': Binary Property */ static const OnigCodePoint CR_Extender[] = { 22, 0x00b7, 0x00b7, 0x02d0, 0x02d1, 0x0640, 0x0640, 0x07fa, 0x07fa, 0x0e46, 0x0e46, 0x0ec6, 0x0ec6, 0x180a, 0x180a, 0x1843, 0x1843, 0x1aa7, 0x1aa7, 0x1c36, 0x1c36, 0x1c7b, 0x1c7b, 0x3005, 0x3005, 0x3031, 0x3035, 0x309d, 0x309e, 0x30fc, 0x30fe, 0xa015, 0xa015, 0xa60c, 0xa60c, 0xa9cf, 0xa9cf, 0xaa70, 0xaa70, 0xaadd, 0xaadd, 0xaaf3, 0xaaf4, 0xff70, 0xff70, }; /* CR_Extender */ /* 'Other_Lowercase': Binary Property */ static const OnigCodePoint CR_Other_Lowercase[] = { 18, 0x00aa, 0x00aa, 0x00ba, 0x00ba, 0x02b0, 0x02b8, 0x02c0, 0x02c1, 0x02e0, 0x02e4, 0x0345, 0x0345, 0x037a, 0x037a, 0x1d2c, 0x1d6a, 0x1d78, 0x1d78, 0x1d9b, 0x1dbf, 0x2071, 0x2071, 0x207f, 0x207f, 0x2090, 0x209c, 0x2170, 0x217f, 0x24d0, 0x24e9, 0x2c7c, 0x2c7d, 0xa770, 0xa770, 0xa7f8, 0xa7f9, }; /* CR_Other_Lowercase */ /* 'Other_Uppercase': Binary Property */ static const OnigCodePoint CR_Other_Uppercase[] = { 2, 0x2160, 0x216f, 0x24b6, 0x24cf, }; /* CR_Other_Uppercase */ /* 'Noncharacter_Code_Point': Binary Property */ static const OnigCodePoint CR_Noncharacter_Code_Point[] = { 18, 0xfdd0, 0xfdef, 0xfffe, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0xeffff, 0xffffe, 0xfffff, 0x10fffe, 0x10ffff, }; /* CR_Noncharacter_Code_Point */ /* 'Other_Grapheme_Extend': Binary Property */ static const OnigCodePoint CR_Other_Grapheme_Extend[] = { 17, 0x09be, 0x09be, 0x09d7, 0x09d7, 0x0b3e, 0x0b3e, 0x0b57, 0x0b57, 0x0bbe, 0x0bbe, 0x0bd7, 0x0bd7, 0x0cc2, 0x0cc2, 0x0cd5, 0x0cd6, 0x0d3e, 0x0d3e, 0x0d57, 0x0d57, 0x0dcf, 0x0dcf, 0x0ddf, 0x0ddf, 0x200c, 0x200d, 0x302e, 0x302f, 0xff9e, 0xff9f, 0x1d165, 0x1d165, 0x1d16e, 0x1d172, }; /* CR_Other_Grapheme_Extend */ /* 'IDS_Binary_Operator': Binary Property */ static const OnigCodePoint CR_IDS_Binary_Operator[] = { 2, 0x2ff0, 0x2ff1, 0x2ff4, 0x2ffb, }; /* CR_IDS_Binary_Operator */ /* 'IDS_Trinary_Operator': Binary Property */ static const OnigCodePoint CR_IDS_Trinary_Operator[] = { 1, 0x2ff2, 0x2ff3, }; /* CR_IDS_Trinary_Operator */ /* 'Radical': Binary Property */ static const OnigCodePoint CR_Radical[] = { 3, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, }; /* CR_Radical */ /* 'Unified_Ideograph': Binary Property */ static const OnigCodePoint CR_Unified_Ideograph[] = { 12, 0x3400, 0x4db5, 0x4e00, 0x9fcc, 0xfa0e, 0xfa0f, 0xfa11, 0xfa11, 0xfa13, 0xfa14, 0xfa1f, 0xfa1f, 0xfa21, 0xfa21, 0xfa23, 0xfa24, 0xfa27, 0xfa29, 0x20000, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, }; /* CR_Unified_Ideograph */ /* 'Other_Default_Ignorable_Code_Point': Binary Property */ static const OnigCodePoint CR_Other_Default_Ignorable_Code_Point[] = { 11, 0x034f, 0x034f, 0x115f, 0x1160, 0x17b4, 0x17b5, 0x2065, 0x2069, 0x3164, 0x3164, 0xffa0, 0xffa0, 0xfff0, 0xfff8, 0xe0000, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xe00ff, 0xe01f0, 0xe0fff, }; /* CR_Other_Default_Ignorable_Code_Point */ /* 'Deprecated': Binary Property */ static const OnigCodePoint CR_Deprecated[] = { 9, 0x0149, 0x0149, 0x0673, 0x0673, 0x0f77, 0x0f77, 0x0f79, 0x0f79, 0x17a3, 0x17a4, 0x206a, 0x206f, 0x2329, 0x232a, 0xe0001, 0xe0001, 0xe0020, 0xe007f, }; /* CR_Deprecated */ /* 'Soft_Dotted': Binary Property */ static const OnigCodePoint CR_Soft_Dotted[] = { 31, 0x0069, 0x006a, 0x012f, 0x012f, 0x0249, 0x0249, 0x0268, 0x0268, 0x029d, 0x029d, 0x02b2, 0x02b2, 0x03f3, 0x03f3, 0x0456, 0x0456, 0x0458, 0x0458, 0x1d62, 0x1d62, 0x1d96, 0x1d96, 0x1da4, 0x1da4, 0x1da8, 0x1da8, 0x1e2d, 0x1e2d, 0x1ecb, 0x1ecb, 0x2071, 0x2071, 0x2148, 0x2149, 0x2c7c, 0x2c7c, 0x1d422, 0x1d423, 0x1d456, 0x1d457, 0x1d48a, 0x1d48b, 0x1d4be, 0x1d4bf, 0x1d4f2, 0x1d4f3, 0x1d526, 0x1d527, 0x1d55a, 0x1d55b, 0x1d58e, 0x1d58f, 0x1d5c2, 0x1d5c3, 0x1d5f6, 0x1d5f7, 0x1d62a, 0x1d62b, 0x1d65e, 0x1d65f, 0x1d692, 0x1d693, }; /* CR_Soft_Dotted */ /* 'Logical_Order_Exception': Binary Property */ static const OnigCodePoint CR_Logical_Order_Exception[] = { 5, 0x0e40, 0x0e44, 0x0ec0, 0x0ec4, 0xaab5, 0xaab6, 0xaab9, 0xaab9, 0xaabb, 0xaabc, }; /* CR_Logical_Order_Exception */ /* 'Other_ID_Start': Binary Property */ static const OnigCodePoint CR_Other_ID_Start[] = { 3, 0x2118, 0x2118, 0x212e, 0x212e, 0x309b, 0x309c, }; /* CR_Other_ID_Start */ /* 'Other_ID_Continue': Binary Property */ static const OnigCodePoint CR_Other_ID_Continue[] = { 4, 0x00b7, 0x00b7, 0x0387, 0x0387, 0x1369, 0x1371, 0x19da, 0x19da, }; /* CR_Other_ID_Continue */ /* 'STerm': Binary Property */ static const OnigCodePoint CR_STerm[] = { 50, 0x0021, 0x0021, 0x002e, 0x002e, 0x003f, 0x003f, 0x055c, 0x055c, 0x055e, 0x055e, 0x0589, 0x0589, 0x061f, 0x061f, 0x06d4, 0x06d4, 0x0700, 0x0702, 0x07f9, 0x07f9, 0x0964, 0x0965, 0x104a, 0x104b, 0x1362, 0x1362, 0x1367, 0x1368, 0x166e, 0x166e, 0x1735, 0x1736, 0x1803, 0x1803, 0x1809, 0x1809, 0x1944, 0x1945, 0x1aa8, 0x1aab, 0x1b5a, 0x1b5b, 0x1b5e, 0x1b5f, 0x1c3b, 0x1c3c, 0x1c7e, 0x1c7f, 0x203c, 0x203d, 0x2047, 0x2049, 0x2e2e, 0x2e2e, 0x3002, 0x3002, 0xa4ff, 0xa4ff, 0xa60e, 0xa60f, 0xa6f3, 0xa6f3, 0xa6f7, 0xa6f7, 0xa876, 0xa877, 0xa8ce, 0xa8cf, 0xa92f, 0xa92f, 0xa9c8, 0xa9c9, 0xaa5d, 0xaa5f, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, 0xfe52, 0xfe52, 0xfe56, 0xfe57, 0xff01, 0xff01, 0xff0e, 0xff0e, 0xff1f, 0xff1f, 0xff61, 0xff61, 0x10a56, 0x10a57, 0x11047, 0x11048, 0x110be, 0x110c1, 0x11141, 0x11143, 0x111c5, 0x111c6, }; /* CR_STerm */ /* 'Variation_Selector': Binary Property */ static const OnigCodePoint CR_Variation_Selector[] = { 3, 0x180b, 0x180d, 0xfe00, 0xfe0f, 0xe0100, 0xe01ef, }; /* CR_Variation_Selector */ /* 'Pattern_White_Space': Binary Property */ static const OnigCodePoint CR_Pattern_White_Space[] = { 5, 0x0009, 0x000d, 0x0020, 0x0020, 0x0085, 0x0085, 0x200e, 0x200f, 0x2028, 0x2029, }; /* CR_Pattern_White_Space */ /* 'Pattern_Syntax': Binary Property */ static const OnigCodePoint CR_Pattern_Syntax[] = { 28, 0x0021, 0x002f, 0x003a, 0x0040, 0x005b, 0x005e, 0x0060, 0x0060, 0x007b, 0x007e, 0x00a1, 0x00a7, 0x00a9, 0x00a9, 0x00ab, 0x00ac, 0x00ae, 0x00ae, 0x00b0, 0x00b1, 0x00b6, 0x00b6, 0x00bb, 0x00bb, 0x00bf, 0x00bf, 0x00d7, 0x00d7, 0x00f7, 0x00f7, 0x2010, 0x2027, 0x2030, 0x203e, 0x2041, 0x2053, 0x2055, 0x205e, 0x2190, 0x245f, 0x2500, 0x2775, 0x2794, 0x2bff, 0x2e00, 0x2e7f, 0x3001, 0x3003, 0x3008, 0x3020, 0x3030, 0x3030, 0xfd3e, 0xfd3f, 0xfe45, 0xfe46, }; /* CR_Pattern_Syntax */ /* 'Unknown': Script */ static const OnigCodePoint CR_Unknown[] = { 537, 0x0378, 0x0379, 0x037f, 0x0383, 0x038b, 0x038b, 0x038d, 0x038d, 0x03a2, 0x03a2, 0x0528, 0x0530, 0x0557, 0x0558, 0x0560, 0x0560, 0x0588, 0x0588, 0x058b, 0x058e, 0x0590, 0x0590, 0x05c8, 0x05cf, 0x05eb, 0x05ef, 0x05f5, 0x05ff, 0x0605, 0x0605, 0x061c, 0x061d, 0x070e, 0x070e, 0x074b, 0x074c, 0x07b2, 0x07bf, 0x07fb, 0x07ff, 0x082e, 0x082f, 0x083f, 0x083f, 0x085c, 0x085d, 0x085f, 0x089f, 0x08a1, 0x08a1, 0x08ad, 0x08e3, 0x08ff, 0x08ff, 0x0978, 0x0978, 0x0980, 0x0980, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, 0x09a9, 0x09a9, 0x09b1, 0x09b1, 0x09b3, 0x09b5, 0x09ba, 0x09bb, 0x09c5, 0x09c6, 0x09c9, 0x09ca, 0x09cf, 0x09d6, 0x09d8, 0x09db, 0x09de, 0x09de, 0x09e4, 0x09e5, 0x09fc, 0x0a00, 0x0a04, 0x0a04, 0x0a0b, 0x0a0e, 0x0a11, 0x0a12, 0x0a29, 0x0a29, 0x0a31, 0x0a31, 0x0a34, 0x0a34, 0x0a37, 0x0a37, 0x0a3a, 0x0a3b, 0x0a3d, 0x0a3d, 0x0a43, 0x0a46, 0x0a49, 0x0a4a, 0x0a4e, 0x0a50, 0x0a52, 0x0a58, 0x0a5d, 0x0a5d, 0x0a5f, 0x0a65, 0x0a76, 0x0a80, 0x0a84, 0x0a84, 0x0a8e, 0x0a8e, 0x0a92, 0x0a92, 0x0aa9, 0x0aa9, 0x0ab1, 0x0ab1, 0x0ab4, 0x0ab4, 0x0aba, 0x0abb, 0x0ac6, 0x0ac6, 0x0aca, 0x0aca, 0x0ace, 0x0acf, 0x0ad1, 0x0adf, 0x0ae4, 0x0ae5, 0x0af2, 0x0b00, 0x0b04, 0x0b04, 0x0b0d, 0x0b0e, 0x0b11, 0x0b12, 0x0b29, 0x0b29, 0x0b31, 0x0b31, 0x0b34, 0x0b34, 0x0b3a, 0x0b3b, 0x0b45, 0x0b46, 0x0b49, 0x0b4a, 0x0b4e, 0x0b55, 0x0b58, 0x0b5b, 0x0b5e, 0x0b5e, 0x0b64, 0x0b65, 0x0b78, 0x0b81, 0x0b84, 0x0b84, 0x0b8b, 0x0b8d, 0x0b91, 0x0b91, 0x0b96, 0x0b98, 0x0b9b, 0x0b9b, 0x0b9d, 0x0b9d, 0x0ba0, 0x0ba2, 0x0ba5, 0x0ba7, 0x0bab, 0x0bad, 0x0bba, 0x0bbd, 0x0bc3, 0x0bc5, 0x0bc9, 0x0bc9, 0x0bce, 0x0bcf, 0x0bd1, 0x0bd6, 0x0bd8, 0x0be5, 0x0bfb, 0x0c00, 0x0c04, 0x0c04, 0x0c0d, 0x0c0d, 0x0c11, 0x0c11, 0x0c29, 0x0c29, 0x0c34, 0x0c34, 0x0c3a, 0x0c3c, 0x0c45, 0x0c45, 0x0c49, 0x0c49, 0x0c4e, 0x0c54, 0x0c57, 0x0c57, 0x0c5a, 0x0c5f, 0x0c64, 0x0c65, 0x0c70, 0x0c77, 0x0c80, 0x0c81, 0x0c84, 0x0c84, 0x0c8d, 0x0c8d, 0x0c91, 0x0c91, 0x0ca9, 0x0ca9, 0x0cb4, 0x0cb4, 0x0cba, 0x0cbb, 0x0cc5, 0x0cc5, 0x0cc9, 0x0cc9, 0x0cce, 0x0cd4, 0x0cd7, 0x0cdd, 0x0cdf, 0x0cdf, 0x0ce4, 0x0ce5, 0x0cf0, 0x0cf0, 0x0cf3, 0x0d01, 0x0d04, 0x0d04, 0x0d0d, 0x0d0d, 0x0d11, 0x0d11, 0x0d3b, 0x0d3c, 0x0d45, 0x0d45, 0x0d49, 0x0d49, 0x0d4f, 0x0d56, 0x0d58, 0x0d5f, 0x0d64, 0x0d65, 0x0d76, 0x0d78, 0x0d80, 0x0d81, 0x0d84, 0x0d84, 0x0d97, 0x0d99, 0x0db2, 0x0db2, 0x0dbc, 0x0dbc, 0x0dbe, 0x0dbf, 0x0dc7, 0x0dc9, 0x0dcb, 0x0dce, 0x0dd5, 0x0dd5, 0x0dd7, 0x0dd7, 0x0de0, 0x0df1, 0x0df5, 0x0e00, 0x0e3b, 0x0e3e, 0x0e5c, 0x0e80, 0x0e83, 0x0e83, 0x0e85, 0x0e86, 0x0e89, 0x0e89, 0x0e8b, 0x0e8c, 0x0e8e, 0x0e93, 0x0e98, 0x0e98, 0x0ea0, 0x0ea0, 0x0ea4, 0x0ea4, 0x0ea6, 0x0ea6, 0x0ea8, 0x0ea9, 0x0eac, 0x0eac, 0x0eba, 0x0eba, 0x0ebe, 0x0ebf, 0x0ec5, 0x0ec5, 0x0ec7, 0x0ec7, 0x0ece, 0x0ecf, 0x0eda, 0x0edb, 0x0ee0, 0x0eff, 0x0f48, 0x0f48, 0x0f6d, 0x0f70, 0x0f98, 0x0f98, 0x0fbd, 0x0fbd, 0x0fcd, 0x0fcd, 0x0fdb, 0x0fff, 0x10c6, 0x10c6, 0x10c8, 0x10cc, 0x10ce, 0x10cf, 0x1249, 0x1249, 0x124e, 0x124f, 0x1257, 0x1257, 0x1259, 0x1259, 0x125e, 0x125f, 0x1289, 0x1289, 0x128e, 0x128f, 0x12b1, 0x12b1, 0x12b6, 0x12b7, 0x12bf, 0x12bf, 0x12c1, 0x12c1, 0x12c6, 0x12c7, 0x12d7, 0x12d7, 0x1311, 0x1311, 0x1316, 0x1317, 0x135b, 0x135c, 0x137d, 0x137f, 0x139a, 0x139f, 0x13f5, 0x13ff, 0x169d, 0x169f, 0x16f1, 0x16ff, 0x170d, 0x170d, 0x1715, 0x171f, 0x1737, 0x173f, 0x1754, 0x175f, 0x176d, 0x176d, 0x1771, 0x1771, 0x1774, 0x177f, 0x17de, 0x17df, 0x17ea, 0x17ef, 0x17fa, 0x17ff, 0x180f, 0x180f, 0x181a, 0x181f, 0x1878, 0x187f, 0x18ab, 0x18af, 0x18f6, 0x18ff, 0x191d, 0x191f, 0x192c, 0x192f, 0x193c, 0x193f, 0x1941, 0x1943, 0x196e, 0x196f, 0x1975, 0x197f, 0x19ac, 0x19af, 0x19ca, 0x19cf, 0x19db, 0x19dd, 0x1a1c, 0x1a1d, 0x1a5f, 0x1a5f, 0x1a7d, 0x1a7e, 0x1a8a, 0x1a8f, 0x1a9a, 0x1a9f, 0x1aae, 0x1aff, 0x1b4c, 0x1b4f, 0x1b7d, 0x1b7f, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, 0x1c80, 0x1cbf, 0x1cc8, 0x1ccf, 0x1cf7, 0x1cff, 0x1de7, 0x1dfb, 0x1f16, 0x1f17, 0x1f1e, 0x1f1f, 0x1f46, 0x1f47, 0x1f4e, 0x1f4f, 0x1f58, 0x1f58, 0x1f5a, 0x1f5a, 0x1f5c, 0x1f5c, 0x1f5e, 0x1f5e, 0x1f7e, 0x1f7f, 0x1fb5, 0x1fb5, 0x1fc5, 0x1fc5, 0x1fd4, 0x1fd5, 0x1fdc, 0x1fdc, 0x1ff0, 0x1ff1, 0x1ff5, 0x1ff5, 0x1fff, 0x1fff, 0x2065, 0x2069, 0x2072, 0x2073, 0x208f, 0x208f, 0x209d, 0x209f, 0x20ba, 0x20cf, 0x20f1, 0x20ff, 0x218a, 0x218f, 0x23f4, 0x23ff, 0x2427, 0x243f, 0x244b, 0x245f, 0x2700, 0x2700, 0x2b4d, 0x2b4f, 0x2b5a, 0x2bff, 0x2c2f, 0x2c2f, 0x2c5f, 0x2c5f, 0x2cf4, 0x2cf8, 0x2d26, 0x2d26, 0x2d28, 0x2d2c, 0x2d2e, 0x2d2f, 0x2d68, 0x2d6e, 0x2d71, 0x2d7e, 0x2d97, 0x2d9f, 0x2da7, 0x2da7, 0x2daf, 0x2daf, 0x2db7, 0x2db7, 0x2dbf, 0x2dbf, 0x2dc7, 0x2dc7, 0x2dcf, 0x2dcf, 0x2dd7, 0x2dd7, 0x2ddf, 0x2ddf, 0x2e3c, 0x2e7f, 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x312e, 0x3130, 0x318f, 0x318f, 0x31bb, 0x31bf, 0x31e4, 0x31ef, 0x321f, 0x321f, 0x32ff, 0x32ff, 0x4db6, 0x4dbf, 0x9fcd, 0x9fff, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa698, 0xa69e, 0xa6f8, 0xa6ff, 0xa78f, 0xa78f, 0xa794, 0xa79f, 0xa7ab, 0xa7f7, 0xa82c, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, 0xa8c5, 0xa8cd, 0xa8da, 0xa8df, 0xa8fc, 0xa8ff, 0xa954, 0xa95e, 0xa97d, 0xa97f, 0xa9ce, 0xa9ce, 0xa9da, 0xa9dd, 0xa9e0, 0xa9ff, 0xaa37, 0xaa3f, 0xaa4e, 0xaa4f, 0xaa5a, 0xaa5b, 0xaa7c, 0xaa7f, 0xaac3, 0xaada, 0xaaf7, 0xab00, 0xab07, 0xab08, 0xab0f, 0xab10, 0xab17, 0xab1f, 0xab27, 0xab27, 0xab2f, 0xabbf, 0xabee, 0xabef, 0xabfa, 0xabff, 0xd7a4, 0xd7af, 0xd7c7, 0xd7ca, 0xd7fc, 0xf8ff, 0xfa6e, 0xfa6f, 0xfada, 0xfaff, 0xfb07, 0xfb12, 0xfb18, 0xfb1c, 0xfb37, 0xfb37, 0xfb3d, 0xfb3d, 0xfb3f, 0xfb3f, 0xfb42, 0xfb42, 0xfb45, 0xfb45, 0xfbc2, 0xfbd2, 0xfd40, 0xfd4f, 0xfd90, 0xfd91, 0xfdc8, 0xfdef, 0xfdfe, 0xfdff, 0xfe1a, 0xfe1f, 0xfe27, 0xfe2f, 0xfe53, 0xfe53, 0xfe67, 0xfe67, 0xfe6c, 0xfe6f, 0xfe75, 0xfe75, 0xfefd, 0xfefe, 0xff00, 0xff00, 0xffbf, 0xffc1, 0xffc8, 0xffc9, 0xffd0, 0xffd1, 0xffd8, 0xffd9, 0xffdd, 0xffdf, 0xffe7, 0xffe7, 0xffef, 0xfff8, 0xfffe, 0xffff, 0x1000c, 0x1000c, 0x10027, 0x10027, 0x1003b, 0x1003b, 0x1003e, 0x1003e, 0x1004e, 0x1004f, 0x1005e, 0x1007f, 0x100fb, 0x100ff, 0x10103, 0x10106, 0x10134, 0x10136, 0x1018b, 0x1018f, 0x1019c, 0x101cf, 0x101fe, 0x1027f, 0x1029d, 0x1029f, 0x102d1, 0x102ff, 0x1031f, 0x1031f, 0x10324, 0x1032f, 0x1034b, 0x1037f, 0x1039e, 0x1039e, 0x103c4, 0x103c7, 0x103d6, 0x103ff, 0x1049e, 0x1049f, 0x104aa, 0x107ff, 0x10806, 0x10807, 0x10809, 0x10809, 0x10836, 0x10836, 0x10839, 0x1083b, 0x1083d, 0x1083e, 0x10856, 0x10856, 0x10860, 0x108ff, 0x1091c, 0x1091e, 0x1093a, 0x1093e, 0x10940, 0x1097f, 0x109b8, 0x109bd, 0x109c0, 0x109ff, 0x10a04, 0x10a04, 0x10a07, 0x10a0b, 0x10a14, 0x10a14, 0x10a18, 0x10a18, 0x10a34, 0x10a37, 0x10a3b, 0x10a3e, 0x10a48, 0x10a4f, 0x10a59, 0x10a5f, 0x10a80, 0x10aff, 0x10b36, 0x10b38, 0x10b56, 0x10b57, 0x10b73, 0x10b77, 0x10b80, 0x10bff, 0x10c49, 0x10e5f, 0x10e7f, 0x10fff, 0x1104e, 0x11051, 0x11070, 0x1107f, 0x110c2, 0x110cf, 0x110e9, 0x110ef, 0x110fa, 0x110ff, 0x11135, 0x11135, 0x11144, 0x1117f, 0x111c9, 0x111cf, 0x111da, 0x1167f, 0x116b8, 0x116bf, 0x116ca, 0x11fff, 0x1236f, 0x123ff, 0x12463, 0x1246f, 0x12474, 0x12fff, 0x1342f, 0x167ff, 0x16a39, 0x16eff, 0x16f45, 0x16f4f, 0x16f7f, 0x16f8e, 0x16fa0, 0x1afff, 0x1b002, 0x1cfff, 0x1d0f6, 0x1d0ff, 0x1d127, 0x1d128, 0x1d1de, 0x1d1ff, 0x1d246, 0x1d2ff, 0x1d357, 0x1d35f, 0x1d372, 0x1d3ff, 0x1d455, 0x1d455, 0x1d49d, 0x1d49d, 0x1d4a0, 0x1d4a1, 0x1d4a3, 0x1d4a4, 0x1d4a7, 0x1d4a8, 0x1d4ad, 0x1d4ad, 0x1d4ba, 0x1d4ba, 0x1d4bc, 0x1d4bc, 0x1d4c4, 0x1d4c4, 0x1d506, 0x1d506, 0x1d50b, 0x1d50c, 0x1d515, 0x1d515, 0x1d51d, 0x1d51d, 0x1d53a, 0x1d53a, 0x1d53f, 0x1d53f, 0x1d545, 0x1d545, 0x1d547, 0x1d549, 0x1d551, 0x1d551, 0x1d6a6, 0x1d6a7, 0x1d7cc, 0x1d7cd, 0x1d800, 0x1edff, 0x1ee04, 0x1ee04, 0x1ee20, 0x1ee20, 0x1ee23, 0x1ee23, 0x1ee25, 0x1ee26, 0x1ee28, 0x1ee28, 0x1ee33, 0x1ee33, 0x1ee38, 0x1ee38, 0x1ee3a, 0x1ee3a, 0x1ee3c, 0x1ee41, 0x1ee43, 0x1ee46, 0x1ee48, 0x1ee48, 0x1ee4a, 0x1ee4a, 0x1ee4c, 0x1ee4c, 0x1ee50, 0x1ee50, 0x1ee53, 0x1ee53, 0x1ee55, 0x1ee56, 0x1ee58, 0x1ee58, 0x1ee5a, 0x1ee5a, 0x1ee5c, 0x1ee5c, 0x1ee5e, 0x1ee5e, 0x1ee60, 0x1ee60, 0x1ee63, 0x1ee63, 0x1ee65, 0x1ee66, 0x1ee6b, 0x1ee6b, 0x1ee73, 0x1ee73, 0x1ee78, 0x1ee78, 0x1ee7d, 0x1ee7d, 0x1ee7f, 0x1ee7f, 0x1ee8a, 0x1ee8a, 0x1ee9c, 0x1eea0, 0x1eea4, 0x1eea4, 0x1eeaa, 0x1eeaa, 0x1eebc, 0x1eeef, 0x1eef2, 0x1efff, 0x1f02c, 0x1f02f, 0x1f094, 0x1f09f, 0x1f0af, 0x1f0b0, 0x1f0bf, 0x1f0c0, 0x1f0d0, 0x1f0d0, 0x1f0e0, 0x1f0ff, 0x1f10b, 0x1f10f, 0x1f12f, 0x1f12f, 0x1f16c, 0x1f16f, 0x1f19b, 0x1f1e5, 0x1f203, 0x1f20f, 0x1f23b, 0x1f23f, 0x1f249, 0x1f24f, 0x1f252, 0x1f2ff, 0x1f321, 0x1f32f, 0x1f336, 0x1f336, 0x1f37d, 0x1f37f, 0x1f394, 0x1f39f, 0x1f3c5, 0x1f3c5, 0x1f3cb, 0x1f3df, 0x1f3f1, 0x1f3ff, 0x1f43f, 0x1f43f, 0x1f441, 0x1f441, 0x1f4f8, 0x1f4f8, 0x1f4fd, 0x1f4ff, 0x1f53e, 0x1f53f, 0x1f544, 0x1f54f, 0x1f568, 0x1f5fa, 0x1f641, 0x1f644, 0x1f650, 0x1f67f, 0x1f6c6, 0x1f6ff, 0x1f774, 0x1ffff, 0x2a6d7, 0x2a6ff, 0x2b735, 0x2b73f, 0x2b81e, 0x2f7ff, 0x2fa1e, 0xe0000, 0xe0002, 0xe001f, 0xe0080, 0xe00ff, 0xe01f0, 0x10ffff, }; /* CR_Unknown */ /* 'Age_1_1': Derived Age 1.1 */ static const OnigCodePoint CR_Age_1_1[] = { 288, 0x0000, 0x01f5, 0x01fa, 0x0217, 0x0250, 0x02a8, 0x02b0, 0x02de, 0x02e0, 0x02e9, 0x0300, 0x0345, 0x0360, 0x0361, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03d6, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03f3, 0x0401, 0x040c, 0x040e, 0x044f, 0x0451, 0x045c, 0x045e, 0x0486, 0x0490, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04d0, 0x04eb, 0x04ee, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x0589, 0x05b0, 0x05b9, 0x05bb, 0x05c3, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0652, 0x0660, 0x066d, 0x0670, 0x06b7, 0x06ba, 0x06be, 0x06c0, 0x06ce, 0x06d0, 0x06ed, 0x06f0, 0x06f9, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1e00, 0x1e9a, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x202e, 0x2030, 0x2046, 0x206a, 0x2070, 0x2074, 0x208e, 0x20a0, 0x20aa, 0x20d0, 0x20e1, 0x2100, 0x2138, 0x2153, 0x2182, 0x2190, 0x21ea, 0x2200, 0x22f1, 0x2300, 0x2300, 0x2302, 0x237a, 0x2400, 0x2424, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, 0x25a0, 0x25ef, 0x2600, 0x2613, 0x261a, 0x266f, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2767, 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x3000, 0x3037, 0x303f, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x319f, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x4e00, 0x9fa5, 0xe000, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1e, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe72, 0xfe74, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xff5e, 0xff61, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfffd, 0xffff, }; /* CR_Age_1_1 */ /* 'Age_2_0': Derived Age 2.0 */ static const OnigCodePoint CR_Age_2_0[] = { 312, 0x0000, 0x01f5, 0x01fa, 0x0217, 0x0250, 0x02a8, 0x02b0, 0x02de, 0x02e0, 0x02e9, 0x0300, 0x0345, 0x0360, 0x0361, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03d6, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03f3, 0x0401, 0x040c, 0x040e, 0x044f, 0x0451, 0x045c, 0x045e, 0x0486, 0x0490, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04d0, 0x04eb, 0x04ee, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x0589, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0652, 0x0660, 0x066d, 0x0670, 0x06b7, 0x06ba, 0x06be, 0x06c0, 0x06ce, 0x06d0, 0x06ed, 0x06f0, 0x06f9, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f69, 0x0f71, 0x0f8b, 0x0f90, 0x0f95, 0x0f97, 0x0f97, 0x0f99, 0x0fad, 0x0fb1, 0x0fb7, 0x0fb9, 0x0fb9, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x202e, 0x2030, 0x2046, 0x206a, 0x2070, 0x2074, 0x208e, 0x20a0, 0x20ab, 0x20d0, 0x20e1, 0x2100, 0x2138, 0x2153, 0x2182, 0x2190, 0x21ea, 0x2200, 0x22f1, 0x2300, 0x2300, 0x2302, 0x237a, 0x2400, 0x2424, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, 0x25a0, 0x25ef, 0x2600, 0x2613, 0x261a, 0x266f, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2767, 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x3000, 0x3037, 0x303f, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x319f, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x4e00, 0x9fa5, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1e, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe72, 0xfe74, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xff5e, 0xff61, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfffd, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0x10ffff, }; /* CR_Age_2_0 */ /* 'Age_2_1': Derived Age 2.1 */ static const OnigCodePoint CR_Age_2_1[] = { 312, 0x0000, 0x01f5, 0x01fa, 0x0217, 0x0250, 0x02a8, 0x02b0, 0x02de, 0x02e0, 0x02e9, 0x0300, 0x0345, 0x0360, 0x0361, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03d6, 0x03da, 0x03da, 0x03dc, 0x03dc, 0x03de, 0x03de, 0x03e0, 0x03e0, 0x03e2, 0x03f3, 0x0401, 0x040c, 0x040e, 0x044f, 0x0451, 0x045c, 0x045e, 0x0486, 0x0490, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04d0, 0x04eb, 0x04ee, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x0589, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0652, 0x0660, 0x066d, 0x0670, 0x06b7, 0x06ba, 0x06be, 0x06c0, 0x06ce, 0x06d0, 0x06ed, 0x06f0, 0x06f9, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f69, 0x0f71, 0x0f8b, 0x0f90, 0x0f95, 0x0f97, 0x0f97, 0x0f99, 0x0fad, 0x0fb1, 0x0fb7, 0x0fb9, 0x0fb9, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x202e, 0x2030, 0x2046, 0x206a, 0x2070, 0x2074, 0x208e, 0x20a0, 0x20ac, 0x20d0, 0x20e1, 0x2100, 0x2138, 0x2153, 0x2182, 0x2190, 0x21ea, 0x2200, 0x22f1, 0x2300, 0x2300, 0x2302, 0x237a, 0x2400, 0x2424, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, 0x25a0, 0x25ef, 0x2600, 0x2613, 0x261a, 0x266f, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2767, 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x3000, 0x3037, 0x303f, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x319f, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x4e00, 0x9fa5, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1e, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe72, 0xfe74, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xff5e, 0xff61, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfffc, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0x10ffff, }; /* CR_Age_2_1 */ /* 'Age_3_0': Derived Age 3.0 */ static const OnigCodePoint CR_Age_3_0[] = { 369, 0x0000, 0x021f, 0x0222, 0x0233, 0x0250, 0x02ad, 0x02b0, 0x02ee, 0x0300, 0x034e, 0x0360, 0x0362, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03d7, 0x03da, 0x03f3, 0x0400, 0x0486, 0x0488, 0x0489, 0x048c, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0655, 0x0660, 0x066d, 0x0670, 0x06ed, 0x06f0, 0x06fe, 0x0700, 0x070d, 0x070f, 0x072c, 0x0730, 0x074a, 0x0780, 0x07b0, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fcf, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1206, 0x1208, 0x1246, 0x1248, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1286, 0x1288, 0x1288, 0x128a, 0x128d, 0x1290, 0x12ae, 0x12b0, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12ce, 0x12d0, 0x12d6, 0x12d8, 0x12ee, 0x12f0, 0x130e, 0x1310, 0x1310, 0x1312, 0x1315, 0x1318, 0x131e, 0x1320, 0x1346, 0x1348, 0x135a, 0x1361, 0x137c, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1780, 0x17dc, 0x17e0, 0x17e9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2046, 0x2048, 0x204d, 0x206a, 0x2070, 0x2074, 0x208e, 0x20a0, 0x20af, 0x20d0, 0x20e3, 0x2100, 0x213a, 0x2153, 0x2183, 0x2190, 0x21f3, 0x2200, 0x22f1, 0x2300, 0x237b, 0x237d, 0x239a, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, 0x25a0, 0x25f7, 0x2600, 0x2613, 0x2619, 0x2671, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2767, 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x2800, 0x28ff, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303a, 0x303e, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x3400, 0x4db5, 0x4e00, 0x9fa5, 0xa000, 0xa48c, 0xa490, 0xa4a1, 0xa4a4, 0xa4b3, 0xa4b5, 0xa4c0, 0xa4c2, 0xa4c4, 0xa4c6, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdf0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe72, 0xfe74, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xff5e, 0xff61, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0x10ffff, }; /* CR_Age_3_0 */ /* 'Age_3_1': Derived Age 3.1 */ static const OnigCodePoint CR_Age_3_1[] = { 402, 0x0000, 0x021f, 0x0222, 0x0233, 0x0250, 0x02ad, 0x02b0, 0x02ee, 0x0300, 0x034e, 0x0360, 0x0362, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03d7, 0x03da, 0x03f5, 0x0400, 0x0486, 0x0488, 0x0489, 0x048c, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0655, 0x0660, 0x066d, 0x0670, 0x06ed, 0x06f0, 0x06fe, 0x0700, 0x070d, 0x070f, 0x072c, 0x0730, 0x074a, 0x0780, 0x07b0, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fcf, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1206, 0x1208, 0x1246, 0x1248, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1286, 0x1288, 0x1288, 0x128a, 0x128d, 0x1290, 0x12ae, 0x12b0, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12ce, 0x12d0, 0x12d6, 0x12d8, 0x12ee, 0x12f0, 0x130e, 0x1310, 0x1310, 0x1312, 0x1315, 0x1318, 0x131e, 0x1320, 0x1346, 0x1348, 0x135a, 0x1361, 0x137c, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1780, 0x17dc, 0x17e0, 0x17e9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2046, 0x2048, 0x204d, 0x206a, 0x2070, 0x2074, 0x208e, 0x20a0, 0x20af, 0x20d0, 0x20e3, 0x2100, 0x213a, 0x2153, 0x2183, 0x2190, 0x21f3, 0x2200, 0x22f1, 0x2300, 0x237b, 0x237d, 0x239a, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, 0x25a0, 0x25f7, 0x2600, 0x2613, 0x2619, 0x2671, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2767, 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x2800, 0x28ff, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303a, 0x303e, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, 0x327f, 0x32b0, 0x32c0, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x3400, 0x4db5, 0x4e00, 0x9fa5, 0xa000, 0xa48c, 0xa490, 0xa4a1, 0xa4a4, 0xa4b3, 0xa4b5, 0xa4c0, 0xa4c2, 0xa4c4, 0xa4c6, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe72, 0xfe74, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xff5e, 0xff61, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xffff, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10400, 0x10425, 0x10428, 0x1044d, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c0, 0x1d4c2, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a3, 0x1d6a8, 0x1d7c9, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xefffe, 0x10ffff, }; /* CR_Age_3_1 */ /* 'Age_3_2': Derived Age 3.2 */ static const OnigCodePoint CR_Age_3_2[] = { 397, 0x0000, 0x0220, 0x0222, 0x0233, 0x0250, 0x02ad, 0x02b0, 0x02ee, 0x0300, 0x034f, 0x0360, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03f6, 0x0400, 0x0486, 0x0488, 0x04ce, 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0655, 0x0660, 0x06ed, 0x06f0, 0x06fe, 0x0700, 0x070d, 0x070f, 0x072c, 0x0730, 0x074a, 0x0780, 0x07b1, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09bc, 0x09be, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a02, 0x0a02, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8b, 0x0a8d, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae0, 0x0ae6, 0x0aef, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b36, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b70, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bf2, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbe, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fcf, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f8, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1206, 0x1208, 0x1246, 0x1248, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1286, 0x1288, 0x1288, 0x128a, 0x128d, 0x1290, 0x12ae, 0x12b0, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12ce, 0x12d0, 0x12d6, 0x12d8, 0x12ee, 0x12f0, 0x130e, 0x1310, 0x1310, 0x1312, 0x1315, 0x1318, 0x131e, 0x1320, 0x1346, 0x1348, 0x135a, 0x1361, 0x137c, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dc, 0x17e0, 0x17e9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2052, 0x2057, 0x2057, 0x205f, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, 0x20a0, 0x20b1, 0x20d0, 0x20ea, 0x2100, 0x213a, 0x213d, 0x214b, 0x2153, 0x2183, 0x2190, 0x23ce, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x24fe, 0x2500, 0x2613, 0x2616, 0x2617, 0x2619, 0x267d, 0x2680, 0x2689, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27d0, 0x27eb, 0x27f0, 0x2aff, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31f0, 0x321c, 0x3220, 0x3243, 0x3251, 0x327b, 0x327f, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x3400, 0x4db5, 0x4e00, 0x9fa5, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfc, 0xfe00, 0xfe0f, 0xfe20, 0xfe23, 0xfe30, 0xfe46, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xffff, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10400, 0x10425, 0x10428, 0x1044d, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c0, 0x1d4c2, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a3, 0x1d6a8, 0x1d7c9, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xefffe, 0x10ffff, }; /* CR_Age_3_2 */ /* 'Age_4_0': Derived Age 4.0 */ static const OnigCodePoint CR_Age_4_0[] = { 412, 0x0000, 0x0236, 0x0250, 0x0357, 0x035d, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x03fb, 0x0400, 0x0486, 0x0488, 0x04ce, 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x060c, 0x0615, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0658, 0x0660, 0x070d, 0x070f, 0x074a, 0x074d, 0x074f, 0x0780, 0x07b1, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb5, 0x0bb7, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be7, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fcf, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f8, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1206, 0x1208, 0x1246, 0x1248, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1286, 0x1288, 0x1288, 0x128a, 0x128d, 0x1290, 0x12ae, 0x12b0, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12ce, 0x12d0, 0x12d6, 0x12d8, 0x12ee, 0x12f0, 0x130e, 0x1310, 0x1310, 0x1312, 0x1315, 0x1318, 0x131e, 0x1320, 0x1346, 0x1348, 0x135a, 0x1361, 0x137c, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x19e0, 0x19ff, 0x1d00, 0x1d6b, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2054, 0x2057, 0x2057, 0x205f, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, 0x20a0, 0x20b1, 0x20d0, 0x20ea, 0x2100, 0x213b, 0x213d, 0x214b, 0x2153, 0x2183, 0x2190, 0x23d0, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x2617, 0x2619, 0x267d, 0x2680, 0x2691, 0x26a0, 0x26a1, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27d0, 0x27eb, 0x27f0, 0x2b0d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31f0, 0x321e, 0x3220, 0x3243, 0x3250, 0x327d, 0x327f, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fa5, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe0f, 0xfe20, 0xfe23, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1013f, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x1039f, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, 0x1d300, 0x1d356, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a3, 0x1d6a8, 0x1d7c9, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_4_0 */ /* 'Age_4_1': Derived Age 4.1 */ static const OnigCodePoint CR_Age_4_1[] = { 430, 0x0000, 0x0241, 0x0250, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x0486, 0x0488, 0x04ce, 0x04d0, 0x04f9, 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05b9, 0x05bb, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x060b, 0x0615, 0x061b, 0x061b, 0x061e, 0x061f, 0x0621, 0x063a, 0x0640, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, 0x074d, 0x076d, 0x0780, 0x07b1, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x097d, 0x097d, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fd1, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19a9, 0x19b0, 0x19c9, 0x19d0, 0x19d9, 0x19de, 0x1a1b, 0x1a1e, 0x1a1f, 0x1d00, 0x1dc3, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, 0x20a0, 0x20b5, 0x20d0, 0x20eb, 0x2100, 0x214c, 0x2153, 0x2183, 0x2190, 0x23db, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x269c, 0x26a0, 0x26b1, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27c0, 0x27c6, 0x27d0, 0x27eb, 0x27f0, 0x2b13, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c80, 0x2cea, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2e00, 0x2e17, 0x2e1c, 0x2e1d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31c0, 0x31cf, 0x31f0, 0x321e, 0x3220, 0x3243, 0x3250, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fbb, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa700, 0xa716, 0xa800, 0xa82b, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe23, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7c9, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_4_1 */ /* 'Age_5_0': Derived Age 5.0 */ static const OnigCodePoint CR_Age_5_0[] = { 440, 0x0000, 0x036f, 0x0374, 0x0375, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, 0x03d0, 0x0486, 0x0488, 0x0513, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x060b, 0x0615, 0x061b, 0x061b, 0x061e, 0x061f, 0x0621, 0x063a, 0x0640, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, 0x074d, 0x076d, 0x0780, 0x07b1, 0x07c0, 0x07fa, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, 0x097b, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3e, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c60, 0x0c61, 0x0c66, 0x0c6f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3e, 0x0d43, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fcf, 0x0fd1, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, 0x102c, 0x1032, 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19a9, 0x19b0, 0x19c9, 0x19d0, 0x19d9, 0x19de, 0x1a1b, 0x1a1e, 0x1a1f, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1d00, 0x1dca, 0x1dfe, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, 0x20a0, 0x20b5, 0x20d0, 0x20ef, 0x2100, 0x214e, 0x2153, 0x2184, 0x2190, 0x23e7, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x269c, 0x26a0, 0x26b2, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27c0, 0x27ca, 0x27d0, 0x27eb, 0x27f0, 0x2b1a, 0x2b20, 0x2b23, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2c6c, 0x2c74, 0x2c77, 0x2c80, 0x2cea, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2e00, 0x2e17, 0x2e1c, 0x2e1d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31c0, 0x31cf, 0x31f0, 0x321e, 0x3220, 0x3243, 0x3250, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fbb, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa700, 0xa71a, 0xa720, 0xa721, 0xa800, 0xa82b, 0xa840, 0xa877, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe23, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, 0x10900, 0x10919, 0x1091f, 0x1091f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_5_0 */ /* 'Age_5_1': Derived Age 5.1 */ static const OnigCodePoint CR_Age_5_1[] = { 455, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0523, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x0606, 0x061b, 0x061e, 0x061f, 0x0621, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0972, 0x097b, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fd4, 0x1000, 0x1099, 0x109e, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19a9, 0x19b0, 0x19c9, 0x19d0, 0x19d9, 0x19de, 0x1a1b, 0x1a1e, 0x1a1f, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1baa, 0x1bae, 0x1bb9, 0x1c00, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1d00, 0x1de6, 0x1dfe, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, 0x20a0, 0x20b5, 0x20d0, 0x20f0, 0x2100, 0x214f, 0x2153, 0x2188, 0x2190, 0x23e7, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x269d, 0x26a0, 0x26bc, 0x26c0, 0x26c3, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27c0, 0x27ca, 0x27cc, 0x27cc, 0x27d0, 0x2b4c, 0x2b50, 0x2b54, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2c6f, 0x2c71, 0x2c7d, 0x2c80, 0x2cea, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e30, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x3243, 0x3250, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fc3, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa500, 0xa62b, 0xa640, 0xa65f, 0xa662, 0xa673, 0xa67c, 0xa697, 0xa700, 0xa78c, 0xa7fb, 0xa82b, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa900, 0xa953, 0xa95f, 0xa95f, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa5f, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, 0x10900, 0x10919, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_5_1 */ /* 'Age_5_2': Derived Age 5.2 */ static const OnigCodePoint CR_Age_5_2[] = { 495, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0525, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x0606, 0x061b, 0x061e, 0x061f, 0x0621, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0900, 0x0939, 0x093c, 0x094e, 0x0950, 0x0955, 0x0958, 0x0972, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fd8, 0x1000, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135f, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1baa, 0x1bae, 0x1bb9, 0x1c00, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cd0, 0x1cf2, 0x1d00, 0x1de6, 0x1dfd, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, 0x20a0, 0x20b8, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23e8, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26cd, 0x26cf, 0x26e1, 0x26e3, 0x26e3, 0x26e8, 0x26ff, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, 0x2756, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27c0, 0x27ca, 0x27cc, 0x27cc, 0x27d0, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf1, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d6f, 0x2d80, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e31, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31b7, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcb, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa65f, 0xa662, 0xa673, 0xa67c, 0xa697, 0xa6a0, 0xa6f7, 0xa700, 0xa78c, 0xa7fb, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaadf, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xd800, 0xfa2d, 0xfa30, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbb1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11080, 0x110c1, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f131, 0x1f131, 0x1f13d, 0x1f13d, 0x1f13f, 0x1f13f, 0x1f142, 0x1f142, 0x1f146, 0x1f146, 0x1f14a, 0x1f14e, 0x1f157, 0x1f157, 0x1f15f, 0x1f15f, 0x1f179, 0x1f179, 0x1f17b, 0x1f17c, 0x1f17f, 0x1f17f, 0x1f18a, 0x1f18d, 0x1f190, 0x1f190, 0x1f200, 0x1f200, 0x1f210, 0x1f231, 0x1f240, 0x1f248, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_5_2 */ /* 'Age_6_0': Derived Age 6.0 */ static const OnigCodePoint CR_Age_6_0[] = { 511, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1baa, 0x1bae, 0x1bb9, 0x1bc0, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cd0, 0x1cf2, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x27ca, 0x27cc, 0x27cc, 0x27ce, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf1, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e31, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcb, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa673, 0xa67c, 0xa697, 0xa6a0, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa791, 0xa7a0, 0xa7a9, 0xa7fa, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaadf, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xd800, 0xfa2d, 0xfa30, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f169, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f550, 0x1f567, 0x1f5fb, 0x1f5ff, 0x1f601, 0x1f610, 0x1f612, 0x1f614, 0x1f616, 0x1f616, 0x1f618, 0x1f618, 0x1f61a, 0x1f61a, 0x1f61c, 0x1f61e, 0x1f620, 0x1f625, 0x1f628, 0x1f62b, 0x1f62d, 0x1f62d, 0x1f630, 0x1f633, 0x1f635, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_6_0 */ /* 'Age_6_1': Derived Age 6.1 */ static const OnigCodePoint CR_Age_6_1[] = { 549, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0604, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x08a0, 0x08a0, 0x08a2, 0x08ac, 0x08e4, 0x08fe, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, 0x0a2a, 0x0a30, 0x0a32, 0x0a33, 0x0a35, 0x0a36, 0x0a38, 0x0a39, 0x0a3c, 0x0a3c, 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, 0x0ab2, 0x0ab3, 0x0ab5, 0x0ab9, 0x0abc, 0x0ac5, 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, 0x0b92, 0x0b95, 0x0b99, 0x0b9a, 0x0b9c, 0x0b9c, 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c59, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, 0x0dbd, 0x0dbd, 0x0dc0, 0x0dc6, 0x0dca, 0x0dca, 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, 0x0e87, 0x0e88, 0x0e8a, 0x0e8a, 0x0e8d, 0x0e8d, 0x0e94, 0x0e97, 0x0e99, 0x0e9f, 0x0ea1, 0x0ea3, 0x0ea5, 0x0ea5, 0x0ea7, 0x0ea7, 0x0eaa, 0x0eab, 0x0ead, 0x0eb9, 0x0ebb, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, 0x1260, 0x1288, 0x128a, 0x128d, 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, 0x12c8, 0x12d6, 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, 0x1980, 0x19ab, 0x19b0, 0x19c9, 0x19d0, 0x19da, 0x19de, 0x1a1b, 0x1a1e, 0x1a5e, 0x1a60, 0x1a7c, 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, 0x1f50, 0x1f57, 0x1f59, 0x1f59, 0x1f5b, 0x1f5b, 0x1f5d, 0x1f5d, 0x1f5f, 0x1f7d, 0x1f80, 0x1fb4, 0x1fb6, 0x1fc4, 0x1fc6, 0x1fd3, 0x1fd6, 0x1fdb, 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, 0x2db8, 0x2dbe, 0x2dc0, 0x2dc6, 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa697, 0xa69f, 0xa6f7, 0xa700, 0xa78e, 0xa790, 0xa793, 0xa7a0, 0xa7aa, 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fb, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, 0xd800, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0x1000b, 0x1000d, 0x10026, 0x10028, 0x1003a, 0x1003c, 0x1003d, 0x1003f, 0x1004d, 0x10050, 0x1005d, 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, 0x10190, 0x1019b, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, 0x10857, 0x1085f, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, 0x10a19, 0x10a33, 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, 0x10a60, 0x10a7f, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, 0x11180, 0x111c8, 0x111d0, 0x111d9, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, 0x1d516, 0x1d51c, 0x1d51e, 0x1d539, 0x1d53b, 0x1d53e, 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee24, 0x1ee27, 0x1ee27, 0x1ee29, 0x1ee32, 0x1ee34, 0x1ee37, 0x1ee39, 0x1ee39, 0x1ee3b, 0x1ee3b, 0x1ee42, 0x1ee42, 0x1ee47, 0x1ee47, 0x1ee49, 0x1ee49, 0x1ee4b, 0x1ee4b, 0x1ee4d, 0x1ee4f, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee54, 0x1ee57, 0x1ee57, 0x1ee59, 0x1ee59, 0x1ee5b, 0x1ee5b, 0x1ee5d, 0x1ee5d, 0x1ee5f, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee64, 0x1ee67, 0x1ee6a, 0x1ee6c, 0x1ee72, 0x1ee74, 0x1ee77, 0x1ee79, 0x1ee7c, 0x1ee7e, 0x1ee7e, 0x1ee80, 0x1ee89, 0x1ee8b, 0x1ee9b, 0x1eea1, 0x1eea3, 0x1eea5, 0x1eea9, 0x1eeab, 0x1eebb, 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, 0x1f0b1, 0x1f0be, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f300, 0x1f320, 0x1f330, 0x1f335, 0x1f337, 0x1f37c, 0x1f380, 0x1f393, 0x1f3a0, 0x1f3c4, 0x1f3c6, 0x1f3ca, 0x1f3e0, 0x1f3f0, 0x1f400, 0x1f43e, 0x1f440, 0x1f440, 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, 0x1f540, 0x1f543, 0x1f550, 0x1f567, 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, 0x6fffe, 0x6ffff, 0x7fffe, 0x7ffff, 0x8fffe, 0x8ffff, 0x9fffe, 0x9ffff, 0xafffe, 0xaffff, 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, }; /* CR_Age_6_1 */ /* 'In_Basic_Latin': Block */ #define CR_In_Basic_Latin CR_ASCII /* 'In_Latin_1_Supplement': Block */ static const OnigCodePoint CR_In_Latin_1_Supplement[] = { 1, 0x0080, 0x00ff, }; /* CR_In_Latin_1_Supplement */ /* 'In_Latin_Extended_A': Block */ static const OnigCodePoint CR_In_Latin_Extended_A[] = { 1, 0x0100, 0x017f, }; /* CR_In_Latin_Extended_A */ /* 'In_Latin_Extended_B': Block */ static const OnigCodePoint CR_In_Latin_Extended_B[] = { 1, 0x0180, 0x024f, }; /* CR_In_Latin_Extended_B */ /* 'In_IPA_Extensions': Block */ static const OnigCodePoint CR_In_IPA_Extensions[] = { 1, 0x0250, 0x02af, }; /* CR_In_IPA_Extensions */ /* 'In_Spacing_Modifier_Letters': Block */ static const OnigCodePoint CR_In_Spacing_Modifier_Letters[] = { 1, 0x02b0, 0x02ff, }; /* CR_In_Spacing_Modifier_Letters */ /* 'In_Combining_Diacritical_Marks': Block */ static const OnigCodePoint CR_In_Combining_Diacritical_Marks[] = { 1, 0x0300, 0x036f, }; /* CR_In_Combining_Diacritical_Marks */ /* 'In_Greek_and_Coptic': Block */ static const OnigCodePoint CR_In_Greek_and_Coptic[] = { 1, 0x0370, 0x03ff, }; /* CR_In_Greek_and_Coptic */ /* 'In_Cyrillic': Block */ static const OnigCodePoint CR_In_Cyrillic[] = { 1, 0x0400, 0x04ff, }; /* CR_In_Cyrillic */ /* 'In_Cyrillic_Supplement': Block */ static const OnigCodePoint CR_In_Cyrillic_Supplement[] = { 1, 0x0500, 0x052f, }; /* CR_In_Cyrillic_Supplement */ /* 'In_Armenian': Block */ static const OnigCodePoint CR_In_Armenian[] = { 1, 0x0530, 0x058f, }; /* CR_In_Armenian */ /* 'In_Hebrew': Block */ static const OnigCodePoint CR_In_Hebrew[] = { 1, 0x0590, 0x05ff, }; /* CR_In_Hebrew */ /* 'In_Arabic': Block */ static const OnigCodePoint CR_In_Arabic[] = { 1, 0x0600, 0x06ff, }; /* CR_In_Arabic */ /* 'In_Syriac': Block */ static const OnigCodePoint CR_In_Syriac[] = { 1, 0x0700, 0x074f, }; /* CR_In_Syriac */ /* 'In_Arabic_Supplement': Block */ static const OnigCodePoint CR_In_Arabic_Supplement[] = { 1, 0x0750, 0x077f, }; /* CR_In_Arabic_Supplement */ /* 'In_Thaana': Block */ static const OnigCodePoint CR_In_Thaana[] = { 1, 0x0780, 0x07bf, }; /* CR_In_Thaana */ /* 'In_NKo': Block */ static const OnigCodePoint CR_In_NKo[] = { 1, 0x07c0, 0x07ff, }; /* CR_In_NKo */ /* 'In_Samaritan': Block */ static const OnigCodePoint CR_In_Samaritan[] = { 1, 0x0800, 0x083f, }; /* CR_In_Samaritan */ /* 'In_Mandaic': Block */ static const OnigCodePoint CR_In_Mandaic[] = { 1, 0x0840, 0x085f, }; /* CR_In_Mandaic */ /* 'In_Arabic_Extended_A': Block */ static const OnigCodePoint CR_In_Arabic_Extended_A[] = { 1, 0x08a0, 0x08ff, }; /* CR_In_Arabic_Extended_A */ /* 'In_Devanagari': Block */ static const OnigCodePoint CR_In_Devanagari[] = { 1, 0x0900, 0x097f, }; /* CR_In_Devanagari */ /* 'In_Bengali': Block */ static const OnigCodePoint CR_In_Bengali[] = { 1, 0x0980, 0x09ff, }; /* CR_In_Bengali */ /* 'In_Gurmukhi': Block */ static const OnigCodePoint CR_In_Gurmukhi[] = { 1, 0x0a00, 0x0a7f, }; /* CR_In_Gurmukhi */ /* 'In_Gujarati': Block */ static const OnigCodePoint CR_In_Gujarati[] = { 1, 0x0a80, 0x0aff, }; /* CR_In_Gujarati */ /* 'In_Oriya': Block */ static const OnigCodePoint CR_In_Oriya[] = { 1, 0x0b00, 0x0b7f, }; /* CR_In_Oriya */ /* 'In_Tamil': Block */ static const OnigCodePoint CR_In_Tamil[] = { 1, 0x0b80, 0x0bff, }; /* CR_In_Tamil */ /* 'In_Telugu': Block */ static const OnigCodePoint CR_In_Telugu[] = { 1, 0x0c00, 0x0c7f, }; /* CR_In_Telugu */ /* 'In_Kannada': Block */ static const OnigCodePoint CR_In_Kannada[] = { 1, 0x0c80, 0x0cff, }; /* CR_In_Kannada */ /* 'In_Malayalam': Block */ static const OnigCodePoint CR_In_Malayalam[] = { 1, 0x0d00, 0x0d7f, }; /* CR_In_Malayalam */ /* 'In_Sinhala': Block */ static const OnigCodePoint CR_In_Sinhala[] = { 1, 0x0d80, 0x0dff, }; /* CR_In_Sinhala */ /* 'In_Thai': Block */ static const OnigCodePoint CR_In_Thai[] = { 1, 0x0e00, 0x0e7f, }; /* CR_In_Thai */ /* 'In_Lao': Block */ static const OnigCodePoint CR_In_Lao[] = { 1, 0x0e80, 0x0eff, }; /* CR_In_Lao */ /* 'In_Tibetan': Block */ static const OnigCodePoint CR_In_Tibetan[] = { 1, 0x0f00, 0x0fff, }; /* CR_In_Tibetan */ /* 'In_Myanmar': Block */ static const OnigCodePoint CR_In_Myanmar[] = { 1, 0x1000, 0x109f, }; /* CR_In_Myanmar */ /* 'In_Georgian': Block */ static const OnigCodePoint CR_In_Georgian[] = { 1, 0x10a0, 0x10ff, }; /* CR_In_Georgian */ /* 'In_Hangul_Jamo': Block */ static const OnigCodePoint CR_In_Hangul_Jamo[] = { 1, 0x1100, 0x11ff, }; /* CR_In_Hangul_Jamo */ /* 'In_Ethiopic': Block */ static const OnigCodePoint CR_In_Ethiopic[] = { 1, 0x1200, 0x137f, }; /* CR_In_Ethiopic */ /* 'In_Ethiopic_Supplement': Block */ static const OnigCodePoint CR_In_Ethiopic_Supplement[] = { 1, 0x1380, 0x139f, }; /* CR_In_Ethiopic_Supplement */ /* 'In_Cherokee': Block */ static const OnigCodePoint CR_In_Cherokee[] = { 1, 0x13a0, 0x13ff, }; /* CR_In_Cherokee */ /* 'In_Unified_Canadian_Aboriginal_Syllabics': Block */ static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics[] = { 1, 0x1400, 0x167f, }; /* CR_In_Unified_Canadian_Aboriginal_Syllabics */ /* 'In_Ogham': Block */ static const OnigCodePoint CR_In_Ogham[] = { 1, 0x1680, 0x169f, }; /* CR_In_Ogham */ /* 'In_Runic': Block */ static const OnigCodePoint CR_In_Runic[] = { 1, 0x16a0, 0x16ff, }; /* CR_In_Runic */ /* 'In_Tagalog': Block */ static const OnigCodePoint CR_In_Tagalog[] = { 1, 0x1700, 0x171f, }; /* CR_In_Tagalog */ /* 'In_Hanunoo': Block */ static const OnigCodePoint CR_In_Hanunoo[] = { 1, 0x1720, 0x173f, }; /* CR_In_Hanunoo */ /* 'In_Buhid': Block */ static const OnigCodePoint CR_In_Buhid[] = { 1, 0x1740, 0x175f, }; /* CR_In_Buhid */ /* 'In_Tagbanwa': Block */ static const OnigCodePoint CR_In_Tagbanwa[] = { 1, 0x1760, 0x177f, }; /* CR_In_Tagbanwa */ /* 'In_Khmer': Block */ static const OnigCodePoint CR_In_Khmer[] = { 1, 0x1780, 0x17ff, }; /* CR_In_Khmer */ /* 'In_Mongolian': Block */ static const OnigCodePoint CR_In_Mongolian[] = { 1, 0x1800, 0x18af, }; /* CR_In_Mongolian */ /* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended': Block */ static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended[] = { 1, 0x18b0, 0x18ff, }; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended */ /* 'In_Limbu': Block */ static const OnigCodePoint CR_In_Limbu[] = { 1, 0x1900, 0x194f, }; /* CR_In_Limbu */ /* 'In_Tai_Le': Block */ static const OnigCodePoint CR_In_Tai_Le[] = { 1, 0x1950, 0x197f, }; /* CR_In_Tai_Le */ /* 'In_New_Tai_Lue': Block */ static const OnigCodePoint CR_In_New_Tai_Lue[] = { 1, 0x1980, 0x19df, }; /* CR_In_New_Tai_Lue */ /* 'In_Khmer_Symbols': Block */ static const OnigCodePoint CR_In_Khmer_Symbols[] = { 1, 0x19e0, 0x19ff, }; /* CR_In_Khmer_Symbols */ /* 'In_Buginese': Block */ static const OnigCodePoint CR_In_Buginese[] = { 1, 0x1a00, 0x1a1f, }; /* CR_In_Buginese */ /* 'In_Tai_Tham': Block */ static const OnigCodePoint CR_In_Tai_Tham[] = { 1, 0x1a20, 0x1aaf, }; /* CR_In_Tai_Tham */ /* 'In_Balinese': Block */ static const OnigCodePoint CR_In_Balinese[] = { 1, 0x1b00, 0x1b7f, }; /* CR_In_Balinese */ /* 'In_Sundanese': Block */ static const OnigCodePoint CR_In_Sundanese[] = { 1, 0x1b80, 0x1bbf, }; /* CR_In_Sundanese */ /* 'In_Batak': Block */ static const OnigCodePoint CR_In_Batak[] = { 1, 0x1bc0, 0x1bff, }; /* CR_In_Batak */ /* 'In_Lepcha': Block */ static const OnigCodePoint CR_In_Lepcha[] = { 1, 0x1c00, 0x1c4f, }; /* CR_In_Lepcha */ /* 'In_Ol_Chiki': Block */ #define CR_In_Ol_Chiki CR_Ol_Chiki /* 'In_Sundanese_Supplement': Block */ static const OnigCodePoint CR_In_Sundanese_Supplement[] = { 1, 0x1cc0, 0x1ccf, }; /* CR_In_Sundanese_Supplement */ /* 'In_Vedic_Extensions': Block */ static const OnigCodePoint CR_In_Vedic_Extensions[] = { 1, 0x1cd0, 0x1cff, }; /* CR_In_Vedic_Extensions */ /* 'In_Phonetic_Extensions': Block */ static const OnigCodePoint CR_In_Phonetic_Extensions[] = { 1, 0x1d00, 0x1d7f, }; /* CR_In_Phonetic_Extensions */ /* 'In_Phonetic_Extensions_Supplement': Block */ static const OnigCodePoint CR_In_Phonetic_Extensions_Supplement[] = { 1, 0x1d80, 0x1dbf, }; /* CR_In_Phonetic_Extensions_Supplement */ /* 'In_Combining_Diacritical_Marks_Supplement': Block */ static const OnigCodePoint CR_In_Combining_Diacritical_Marks_Supplement[] = { 1, 0x1dc0, 0x1dff, }; /* CR_In_Combining_Diacritical_Marks_Supplement */ /* 'In_Latin_Extended_Additional': Block */ static const OnigCodePoint CR_In_Latin_Extended_Additional[] = { 1, 0x1e00, 0x1eff, }; /* CR_In_Latin_Extended_Additional */ /* 'In_Greek_Extended': Block */ static const OnigCodePoint CR_In_Greek_Extended[] = { 1, 0x1f00, 0x1fff, }; /* CR_In_Greek_Extended */ /* 'In_General_Punctuation': Block */ static const OnigCodePoint CR_In_General_Punctuation[] = { 1, 0x2000, 0x206f, }; /* CR_In_General_Punctuation */ /* 'In_Superscripts_and_Subscripts': Block */ static const OnigCodePoint CR_In_Superscripts_and_Subscripts[] = { 1, 0x2070, 0x209f, }; /* CR_In_Superscripts_and_Subscripts */ /* 'In_Currency_Symbols': Block */ static const OnigCodePoint CR_In_Currency_Symbols[] = { 1, 0x20a0, 0x20cf, }; /* CR_In_Currency_Symbols */ /* 'In_Combining_Diacritical_Marks_for_Symbols': Block */ static const OnigCodePoint CR_In_Combining_Diacritical_Marks_for_Symbols[] = { 1, 0x20d0, 0x20ff, }; /* CR_In_Combining_Diacritical_Marks_for_Symbols */ /* 'In_Letterlike_Symbols': Block */ static const OnigCodePoint CR_In_Letterlike_Symbols[] = { 1, 0x2100, 0x214f, }; /* CR_In_Letterlike_Symbols */ /* 'In_Number_Forms': Block */ static const OnigCodePoint CR_In_Number_Forms[] = { 1, 0x2150, 0x218f, }; /* CR_In_Number_Forms */ /* 'In_Arrows': Block */ static const OnigCodePoint CR_In_Arrows[] = { 1, 0x2190, 0x21ff, }; /* CR_In_Arrows */ /* 'In_Mathematical_Operators': Block */ static const OnigCodePoint CR_In_Mathematical_Operators[] = { 1, 0x2200, 0x22ff, }; /* CR_In_Mathematical_Operators */ /* 'In_Miscellaneous_Technical': Block */ static const OnigCodePoint CR_In_Miscellaneous_Technical[] = { 1, 0x2300, 0x23ff, }; /* CR_In_Miscellaneous_Technical */ /* 'In_Control_Pictures': Block */ static const OnigCodePoint CR_In_Control_Pictures[] = { 1, 0x2400, 0x243f, }; /* CR_In_Control_Pictures */ /* 'In_Optical_Character_Recognition': Block */ static const OnigCodePoint CR_In_Optical_Character_Recognition[] = { 1, 0x2440, 0x245f, }; /* CR_In_Optical_Character_Recognition */ /* 'In_Enclosed_Alphanumerics': Block */ static const OnigCodePoint CR_In_Enclosed_Alphanumerics[] = { 1, 0x2460, 0x24ff, }; /* CR_In_Enclosed_Alphanumerics */ /* 'In_Box_Drawing': Block */ static const OnigCodePoint CR_In_Box_Drawing[] = { 1, 0x2500, 0x257f, }; /* CR_In_Box_Drawing */ /* 'In_Block_Elements': Block */ static const OnigCodePoint CR_In_Block_Elements[] = { 1, 0x2580, 0x259f, }; /* CR_In_Block_Elements */ /* 'In_Geometric_Shapes': Block */ static const OnigCodePoint CR_In_Geometric_Shapes[] = { 1, 0x25a0, 0x25ff, }; /* CR_In_Geometric_Shapes */ /* 'In_Miscellaneous_Symbols': Block */ static const OnigCodePoint CR_In_Miscellaneous_Symbols[] = { 1, 0x2600, 0x26ff, }; /* CR_In_Miscellaneous_Symbols */ /* 'In_Dingbats': Block */ static const OnigCodePoint CR_In_Dingbats[] = { 1, 0x2700, 0x27bf, }; /* CR_In_Dingbats */ /* 'In_Miscellaneous_Mathematical_Symbols_A': Block */ static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_A[] = { 1, 0x27c0, 0x27ef, }; /* CR_In_Miscellaneous_Mathematical_Symbols_A */ /* 'In_Supplemental_Arrows_A': Block */ static const OnigCodePoint CR_In_Supplemental_Arrows_A[] = { 1, 0x27f0, 0x27ff, }; /* CR_In_Supplemental_Arrows_A */ /* 'In_Braille_Patterns': Block */ #define CR_In_Braille_Patterns CR_Braille /* 'In_Supplemental_Arrows_B': Block */ static const OnigCodePoint CR_In_Supplemental_Arrows_B[] = { 1, 0x2900, 0x297f, }; /* CR_In_Supplemental_Arrows_B */ /* 'In_Miscellaneous_Mathematical_Symbols_B': Block */ static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_B[] = { 1, 0x2980, 0x29ff, }; /* CR_In_Miscellaneous_Mathematical_Symbols_B */ /* 'In_Supplemental_Mathematical_Operators': Block */ static const OnigCodePoint CR_In_Supplemental_Mathematical_Operators[] = { 1, 0x2a00, 0x2aff, }; /* CR_In_Supplemental_Mathematical_Operators */ /* 'In_Miscellaneous_Symbols_and_Arrows': Block */ static const OnigCodePoint CR_In_Miscellaneous_Symbols_and_Arrows[] = { 1, 0x2b00, 0x2bff, }; /* CR_In_Miscellaneous_Symbols_and_Arrows */ /* 'In_Glagolitic': Block */ static const OnigCodePoint CR_In_Glagolitic[] = { 1, 0x2c00, 0x2c5f, }; /* CR_In_Glagolitic */ /* 'In_Latin_Extended_C': Block */ static const OnigCodePoint CR_In_Latin_Extended_C[] = { 1, 0x2c60, 0x2c7f, }; /* CR_In_Latin_Extended_C */ /* 'In_Coptic': Block */ static const OnigCodePoint CR_In_Coptic[] = { 1, 0x2c80, 0x2cff, }; /* CR_In_Coptic */ /* 'In_Georgian_Supplement': Block */ static const OnigCodePoint CR_In_Georgian_Supplement[] = { 1, 0x2d00, 0x2d2f, }; /* CR_In_Georgian_Supplement */ /* 'In_Tifinagh': Block */ static const OnigCodePoint CR_In_Tifinagh[] = { 1, 0x2d30, 0x2d7f, }; /* CR_In_Tifinagh */ /* 'In_Ethiopic_Extended': Block */ static const OnigCodePoint CR_In_Ethiopic_Extended[] = { 1, 0x2d80, 0x2ddf, }; /* CR_In_Ethiopic_Extended */ /* 'In_Cyrillic_Extended_A': Block */ static const OnigCodePoint CR_In_Cyrillic_Extended_A[] = { 1, 0x2de0, 0x2dff, }; /* CR_In_Cyrillic_Extended_A */ /* 'In_Supplemental_Punctuation': Block */ static const OnigCodePoint CR_In_Supplemental_Punctuation[] = { 1, 0x2e00, 0x2e7f, }; /* CR_In_Supplemental_Punctuation */ /* 'In_CJK_Radicals_Supplement': Block */ static const OnigCodePoint CR_In_CJK_Radicals_Supplement[] = { 1, 0x2e80, 0x2eff, }; /* CR_In_CJK_Radicals_Supplement */ /* 'In_Kangxi_Radicals': Block */ static const OnigCodePoint CR_In_Kangxi_Radicals[] = { 1, 0x2f00, 0x2fdf, }; /* CR_In_Kangxi_Radicals */ /* 'In_Ideographic_Description_Characters': Block */ static const OnigCodePoint CR_In_Ideographic_Description_Characters[] = { 1, 0x2ff0, 0x2fff, }; /* CR_In_Ideographic_Description_Characters */ /* 'In_CJK_Symbols_and_Punctuation': Block */ static const OnigCodePoint CR_In_CJK_Symbols_and_Punctuation[] = { 1, 0x3000, 0x303f, }; /* CR_In_CJK_Symbols_and_Punctuation */ /* 'In_Hiragana': Block */ static const OnigCodePoint CR_In_Hiragana[] = { 1, 0x3040, 0x309f, }; /* CR_In_Hiragana */ /* 'In_Katakana': Block */ static const OnigCodePoint CR_In_Katakana[] = { 1, 0x30a0, 0x30ff, }; /* CR_In_Katakana */ /* 'In_Bopomofo': Block */ static const OnigCodePoint CR_In_Bopomofo[] = { 1, 0x3100, 0x312f, }; /* CR_In_Bopomofo */ /* 'In_Hangul_Compatibility_Jamo': Block */ static const OnigCodePoint CR_In_Hangul_Compatibility_Jamo[] = { 1, 0x3130, 0x318f, }; /* CR_In_Hangul_Compatibility_Jamo */ /* 'In_Kanbun': Block */ static const OnigCodePoint CR_In_Kanbun[] = { 1, 0x3190, 0x319f, }; /* CR_In_Kanbun */ /* 'In_Bopomofo_Extended': Block */ static const OnigCodePoint CR_In_Bopomofo_Extended[] = { 1, 0x31a0, 0x31bf, }; /* CR_In_Bopomofo_Extended */ /* 'In_CJK_Strokes': Block */ static const OnigCodePoint CR_In_CJK_Strokes[] = { 1, 0x31c0, 0x31ef, }; /* CR_In_CJK_Strokes */ /* 'In_Katakana_Phonetic_Extensions': Block */ static const OnigCodePoint CR_In_Katakana_Phonetic_Extensions[] = { 1, 0x31f0, 0x31ff, }; /* CR_In_Katakana_Phonetic_Extensions */ /* 'In_Enclosed_CJK_Letters_and_Months': Block */ static const OnigCodePoint CR_In_Enclosed_CJK_Letters_and_Months[] = { 1, 0x3200, 0x32ff, }; /* CR_In_Enclosed_CJK_Letters_and_Months */ /* 'In_CJK_Compatibility': Block */ static const OnigCodePoint CR_In_CJK_Compatibility[] = { 1, 0x3300, 0x33ff, }; /* CR_In_CJK_Compatibility */ /* 'In_CJK_Unified_Ideographs_Extension_A': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_A[] = { 1, 0x3400, 0x4dbf, }; /* CR_In_CJK_Unified_Ideographs_Extension_A */ /* 'In_Yijing_Hexagram_Symbols': Block */ static const OnigCodePoint CR_In_Yijing_Hexagram_Symbols[] = { 1, 0x4dc0, 0x4dff, }; /* CR_In_Yijing_Hexagram_Symbols */ /* 'In_CJK_Unified_Ideographs': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs[] = { 1, 0x4e00, 0x9fff, }; /* CR_In_CJK_Unified_Ideographs */ /* 'In_Yi_Syllables': Block */ static const OnigCodePoint CR_In_Yi_Syllables[] = { 1, 0xa000, 0xa48f, }; /* CR_In_Yi_Syllables */ /* 'In_Yi_Radicals': Block */ static const OnigCodePoint CR_In_Yi_Radicals[] = { 1, 0xa490, 0xa4cf, }; /* CR_In_Yi_Radicals */ /* 'In_Lisu': Block */ #define CR_In_Lisu CR_Lisu /* 'In_Vai': Block */ static const OnigCodePoint CR_In_Vai[] = { 1, 0xa500, 0xa63f, }; /* CR_In_Vai */ /* 'In_Cyrillic_Extended_B': Block */ static const OnigCodePoint CR_In_Cyrillic_Extended_B[] = { 1, 0xa640, 0xa69f, }; /* CR_In_Cyrillic_Extended_B */ /* 'In_Bamum': Block */ static const OnigCodePoint CR_In_Bamum[] = { 1, 0xa6a0, 0xa6ff, }; /* CR_In_Bamum */ /* 'In_Modifier_Tone_Letters': Block */ static const OnigCodePoint CR_In_Modifier_Tone_Letters[] = { 1, 0xa700, 0xa71f, }; /* CR_In_Modifier_Tone_Letters */ /* 'In_Latin_Extended_D': Block */ static const OnigCodePoint CR_In_Latin_Extended_D[] = { 1, 0xa720, 0xa7ff, }; /* CR_In_Latin_Extended_D */ /* 'In_Syloti_Nagri': Block */ static const OnigCodePoint CR_In_Syloti_Nagri[] = { 1, 0xa800, 0xa82f, }; /* CR_In_Syloti_Nagri */ /* 'In_Common_Indic_Number_Forms': Block */ static const OnigCodePoint CR_In_Common_Indic_Number_Forms[] = { 1, 0xa830, 0xa83f, }; /* CR_In_Common_Indic_Number_Forms */ /* 'In_Phags_pa': Block */ static const OnigCodePoint CR_In_Phags_pa[] = { 1, 0xa840, 0xa87f, }; /* CR_In_Phags_pa */ /* 'In_Saurashtra': Block */ static const OnigCodePoint CR_In_Saurashtra[] = { 1, 0xa880, 0xa8df, }; /* CR_In_Saurashtra */ /* 'In_Devanagari_Extended': Block */ static const OnigCodePoint CR_In_Devanagari_Extended[] = { 1, 0xa8e0, 0xa8ff, }; /* CR_In_Devanagari_Extended */ /* 'In_Kayah_Li': Block */ #define CR_In_Kayah_Li CR_Kayah_Li /* 'In_Rejang': Block */ static const OnigCodePoint CR_In_Rejang[] = { 1, 0xa930, 0xa95f, }; /* CR_In_Rejang */ /* 'In_Hangul_Jamo_Extended_A': Block */ static const OnigCodePoint CR_In_Hangul_Jamo_Extended_A[] = { 1, 0xa960, 0xa97f, }; /* CR_In_Hangul_Jamo_Extended_A */ /* 'In_Javanese': Block */ static const OnigCodePoint CR_In_Javanese[] = { 1, 0xa980, 0xa9df, }; /* CR_In_Javanese */ /* 'In_Cham': Block */ static const OnigCodePoint CR_In_Cham[] = { 1, 0xaa00, 0xaa5f, }; /* CR_In_Cham */ /* 'In_Myanmar_Extended_A': Block */ static const OnigCodePoint CR_In_Myanmar_Extended_A[] = { 1, 0xaa60, 0xaa7f, }; /* CR_In_Myanmar_Extended_A */ /* 'In_Tai_Viet': Block */ static const OnigCodePoint CR_In_Tai_Viet[] = { 1, 0xaa80, 0xaadf, }; /* CR_In_Tai_Viet */ /* 'In_Meetei_Mayek_Extensions': Block */ static const OnigCodePoint CR_In_Meetei_Mayek_Extensions[] = { 1, 0xaae0, 0xaaff, }; /* CR_In_Meetei_Mayek_Extensions */ /* 'In_Ethiopic_Extended_A': Block */ static const OnigCodePoint CR_In_Ethiopic_Extended_A[] = { 1, 0xab00, 0xab2f, }; /* CR_In_Ethiopic_Extended_A */ /* 'In_Meetei_Mayek': Block */ static const OnigCodePoint CR_In_Meetei_Mayek[] = { 1, 0xabc0, 0xabff, }; /* CR_In_Meetei_Mayek */ /* 'In_Hangul_Syllables': Block */ static const OnigCodePoint CR_In_Hangul_Syllables[] = { 1, 0xac00, 0xd7af, }; /* CR_In_Hangul_Syllables */ /* 'In_Hangul_Jamo_Extended_B': Block */ static const OnigCodePoint CR_In_Hangul_Jamo_Extended_B[] = { 1, 0xd7b0, 0xd7ff, }; /* CR_In_Hangul_Jamo_Extended_B */ /* 'In_High_Surrogates': Block */ static const OnigCodePoint CR_In_High_Surrogates[] = { 1, 0xd800, 0xdb7f, }; /* CR_In_High_Surrogates */ /* 'In_High_Private_Use_Surrogates': Block */ static const OnigCodePoint CR_In_High_Private_Use_Surrogates[] = { 1, 0xdb80, 0xdbff, }; /* CR_In_High_Private_Use_Surrogates */ /* 'In_Low_Surrogates': Block */ static const OnigCodePoint CR_In_Low_Surrogates[] = { 1, 0xdc00, 0xdfff, }; /* CR_In_Low_Surrogates */ /* 'In_Private_Use_Area': Block */ static const OnigCodePoint CR_In_Private_Use_Area[] = { 1, 0xe000, 0xf8ff, }; /* CR_In_Private_Use_Area */ /* 'In_CJK_Compatibility_Ideographs': Block */ static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs[] = { 1, 0xf900, 0xfaff, }; /* CR_In_CJK_Compatibility_Ideographs */ /* 'In_Alphabetic_Presentation_Forms': Block */ static const OnigCodePoint CR_In_Alphabetic_Presentation_Forms[] = { 1, 0xfb00, 0xfb4f, }; /* CR_In_Alphabetic_Presentation_Forms */ /* 'In_Arabic_Presentation_Forms_A': Block */ static const OnigCodePoint CR_In_Arabic_Presentation_Forms_A[] = { 1, 0xfb50, 0xfdff, }; /* CR_In_Arabic_Presentation_Forms_A */ /* 'In_Variation_Selectors': Block */ static const OnigCodePoint CR_In_Variation_Selectors[] = { 1, 0xfe00, 0xfe0f, }; /* CR_In_Variation_Selectors */ /* 'In_Vertical_Forms': Block */ static const OnigCodePoint CR_In_Vertical_Forms[] = { 1, 0xfe10, 0xfe1f, }; /* CR_In_Vertical_Forms */ /* 'In_Combining_Half_Marks': Block */ static const OnigCodePoint CR_In_Combining_Half_Marks[] = { 1, 0xfe20, 0xfe2f, }; /* CR_In_Combining_Half_Marks */ /* 'In_CJK_Compatibility_Forms': Block */ static const OnigCodePoint CR_In_CJK_Compatibility_Forms[] = { 1, 0xfe30, 0xfe4f, }; /* CR_In_CJK_Compatibility_Forms */ /* 'In_Small_Form_Variants': Block */ static const OnigCodePoint CR_In_Small_Form_Variants[] = { 1, 0xfe50, 0xfe6f, }; /* CR_In_Small_Form_Variants */ /* 'In_Arabic_Presentation_Forms_B': Block */ static const OnigCodePoint CR_In_Arabic_Presentation_Forms_B[] = { 1, 0xfe70, 0xfeff, }; /* CR_In_Arabic_Presentation_Forms_B */ /* 'In_Halfwidth_and_Fullwidth_Forms': Block */ static const OnigCodePoint CR_In_Halfwidth_and_Fullwidth_Forms[] = { 1, 0xff00, 0xffef, }; /* CR_In_Halfwidth_and_Fullwidth_Forms */ /* 'In_Specials': Block */ static const OnigCodePoint CR_In_Specials[] = { 1, 0xfff0, 0xffff, }; /* CR_In_Specials */ /* 'In_Linear_B_Syllabary': Block */ static const OnigCodePoint CR_In_Linear_B_Syllabary[] = { 1, 0x10000, 0x1007f, }; /* CR_In_Linear_B_Syllabary */ /* 'In_Linear_B_Ideograms': Block */ static const OnigCodePoint CR_In_Linear_B_Ideograms[] = { 1, 0x10080, 0x100ff, }; /* CR_In_Linear_B_Ideograms */ /* 'In_Aegean_Numbers': Block */ static const OnigCodePoint CR_In_Aegean_Numbers[] = { 1, 0x10100, 0x1013f, }; /* CR_In_Aegean_Numbers */ /* 'In_Ancient_Greek_Numbers': Block */ static const OnigCodePoint CR_In_Ancient_Greek_Numbers[] = { 1, 0x10140, 0x1018f, }; /* CR_In_Ancient_Greek_Numbers */ /* 'In_Ancient_Symbols': Block */ static const OnigCodePoint CR_In_Ancient_Symbols[] = { 1, 0x10190, 0x101cf, }; /* CR_In_Ancient_Symbols */ /* 'In_Phaistos_Disc': Block */ static const OnigCodePoint CR_In_Phaistos_Disc[] = { 1, 0x101d0, 0x101ff, }; /* CR_In_Phaistos_Disc */ /* 'In_Lycian': Block */ static const OnigCodePoint CR_In_Lycian[] = { 1, 0x10280, 0x1029f, }; /* CR_In_Lycian */ /* 'In_Carian': Block */ static const OnigCodePoint CR_In_Carian[] = { 1, 0x102a0, 0x102df, }; /* CR_In_Carian */ /* 'In_Old_Italic': Block */ static const OnigCodePoint CR_In_Old_Italic[] = { 1, 0x10300, 0x1032f, }; /* CR_In_Old_Italic */ /* 'In_Gothic': Block */ static const OnigCodePoint CR_In_Gothic[] = { 1, 0x10330, 0x1034f, }; /* CR_In_Gothic */ /* 'In_Ugaritic': Block */ static const OnigCodePoint CR_In_Ugaritic[] = { 1, 0x10380, 0x1039f, }; /* CR_In_Ugaritic */ /* 'In_Old_Persian': Block */ static const OnigCodePoint CR_In_Old_Persian[] = { 1, 0x103a0, 0x103df, }; /* CR_In_Old_Persian */ /* 'In_Deseret': Block */ #define CR_In_Deseret CR_Deseret /* 'In_Shavian': Block */ #define CR_In_Shavian CR_Shavian /* 'In_Osmanya': Block */ static const OnigCodePoint CR_In_Osmanya[] = { 1, 0x10480, 0x104af, }; /* CR_In_Osmanya */ /* 'In_Cypriot_Syllabary': Block */ static const OnigCodePoint CR_In_Cypriot_Syllabary[] = { 1, 0x10800, 0x1083f, }; /* CR_In_Cypriot_Syllabary */ /* 'In_Imperial_Aramaic': Block */ static const OnigCodePoint CR_In_Imperial_Aramaic[] = { 1, 0x10840, 0x1085f, }; /* CR_In_Imperial_Aramaic */ /* 'In_Phoenician': Block */ static const OnigCodePoint CR_In_Phoenician[] = { 1, 0x10900, 0x1091f, }; /* CR_In_Phoenician */ /* 'In_Lydian': Block */ static const OnigCodePoint CR_In_Lydian[] = { 1, 0x10920, 0x1093f, }; /* CR_In_Lydian */ /* 'In_Meroitic_Hieroglyphs': Block */ #define CR_In_Meroitic_Hieroglyphs CR_Meroitic_Hieroglyphs /* 'In_Meroitic_Cursive': Block */ static const OnigCodePoint CR_In_Meroitic_Cursive[] = { 1, 0x109a0, 0x109ff, }; /* CR_In_Meroitic_Cursive */ /* 'In_Kharoshthi': Block */ static const OnigCodePoint CR_In_Kharoshthi[] = { 1, 0x10a00, 0x10a5f, }; /* CR_In_Kharoshthi */ /* 'In_Old_South_Arabian': Block */ #define CR_In_Old_South_Arabian CR_Old_South_Arabian /* 'In_Avestan': Block */ static const OnigCodePoint CR_In_Avestan[] = { 1, 0x10b00, 0x10b3f, }; /* CR_In_Avestan */ /* 'In_Inscriptional_Parthian': Block */ static const OnigCodePoint CR_In_Inscriptional_Parthian[] = { 1, 0x10b40, 0x10b5f, }; /* CR_In_Inscriptional_Parthian */ /* 'In_Inscriptional_Pahlavi': Block */ static const OnigCodePoint CR_In_Inscriptional_Pahlavi[] = { 1, 0x10b60, 0x10b7f, }; /* CR_In_Inscriptional_Pahlavi */ /* 'In_Old_Turkic': Block */ static const OnigCodePoint CR_In_Old_Turkic[] = { 1, 0x10c00, 0x10c4f, }; /* CR_In_Old_Turkic */ /* 'In_Rumi_Numeral_Symbols': Block */ static const OnigCodePoint CR_In_Rumi_Numeral_Symbols[] = { 1, 0x10e60, 0x10e7f, }; /* CR_In_Rumi_Numeral_Symbols */ /* 'In_Brahmi': Block */ static const OnigCodePoint CR_In_Brahmi[] = { 1, 0x11000, 0x1107f, }; /* CR_In_Brahmi */ /* 'In_Kaithi': Block */ static const OnigCodePoint CR_In_Kaithi[] = { 1, 0x11080, 0x110cf, }; /* CR_In_Kaithi */ /* 'In_Sora_Sompeng': Block */ static const OnigCodePoint CR_In_Sora_Sompeng[] = { 1, 0x110d0, 0x110ff, }; /* CR_In_Sora_Sompeng */ /* 'In_Chakma': Block */ static const OnigCodePoint CR_In_Chakma[] = { 1, 0x11100, 0x1114f, }; /* CR_In_Chakma */ /* 'In_Sharada': Block */ static const OnigCodePoint CR_In_Sharada[] = { 1, 0x11180, 0x111df, }; /* CR_In_Sharada */ /* 'In_Takri': Block */ static const OnigCodePoint CR_In_Takri[] = { 1, 0x11680, 0x116cf, }; /* CR_In_Takri */ /* 'In_Cuneiform': Block */ static const OnigCodePoint CR_In_Cuneiform[] = { 1, 0x12000, 0x123ff, }; /* CR_In_Cuneiform */ /* 'In_Cuneiform_Numbers_and_Punctuation': Block */ static const OnigCodePoint CR_In_Cuneiform_Numbers_and_Punctuation[] = { 1, 0x12400, 0x1247f, }; /* CR_In_Cuneiform_Numbers_and_Punctuation */ /* 'In_Egyptian_Hieroglyphs': Block */ static const OnigCodePoint CR_In_Egyptian_Hieroglyphs[] = { 1, 0x13000, 0x1342f, }; /* CR_In_Egyptian_Hieroglyphs */ /* 'In_Bamum_Supplement': Block */ static const OnigCodePoint CR_In_Bamum_Supplement[] = { 1, 0x16800, 0x16a3f, }; /* CR_In_Bamum_Supplement */ /* 'In_Miao': Block */ static const OnigCodePoint CR_In_Miao[] = { 1, 0x16f00, 0x16f9f, }; /* CR_In_Miao */ /* 'In_Kana_Supplement': Block */ static const OnigCodePoint CR_In_Kana_Supplement[] = { 1, 0x1b000, 0x1b0ff, }; /* CR_In_Kana_Supplement */ /* 'In_Byzantine_Musical_Symbols': Block */ static const OnigCodePoint CR_In_Byzantine_Musical_Symbols[] = { 1, 0x1d000, 0x1d0ff, }; /* CR_In_Byzantine_Musical_Symbols */ /* 'In_Musical_Symbols': Block */ static const OnigCodePoint CR_In_Musical_Symbols[] = { 1, 0x1d100, 0x1d1ff, }; /* CR_In_Musical_Symbols */ /* 'In_Ancient_Greek_Musical_Notation': Block */ static const OnigCodePoint CR_In_Ancient_Greek_Musical_Notation[] = { 1, 0x1d200, 0x1d24f, }; /* CR_In_Ancient_Greek_Musical_Notation */ /* 'In_Tai_Xuan_Jing_Symbols': Block */ static const OnigCodePoint CR_In_Tai_Xuan_Jing_Symbols[] = { 1, 0x1d300, 0x1d35f, }; /* CR_In_Tai_Xuan_Jing_Symbols */ /* 'In_Counting_Rod_Numerals': Block */ static const OnigCodePoint CR_In_Counting_Rod_Numerals[] = { 1, 0x1d360, 0x1d37f, }; /* CR_In_Counting_Rod_Numerals */ /* 'In_Mathematical_Alphanumeric_Symbols': Block */ static const OnigCodePoint CR_In_Mathematical_Alphanumeric_Symbols[] = { 1, 0x1d400, 0x1d7ff, }; /* CR_In_Mathematical_Alphanumeric_Symbols */ /* 'In_Arabic_Mathematical_Alphabetic_Symbols': Block */ static const OnigCodePoint CR_In_Arabic_Mathematical_Alphabetic_Symbols[] = { 1, 0x1ee00, 0x1eeff, }; /* CR_In_Arabic_Mathematical_Alphabetic_Symbols */ /* 'In_Mahjong_Tiles': Block */ static const OnigCodePoint CR_In_Mahjong_Tiles[] = { 1, 0x1f000, 0x1f02f, }; /* CR_In_Mahjong_Tiles */ /* 'In_Domino_Tiles': Block */ static const OnigCodePoint CR_In_Domino_Tiles[] = { 1, 0x1f030, 0x1f09f, }; /* CR_In_Domino_Tiles */ /* 'In_Playing_Cards': Block */ static const OnigCodePoint CR_In_Playing_Cards[] = { 1, 0x1f0a0, 0x1f0ff, }; /* CR_In_Playing_Cards */ /* 'In_Enclosed_Alphanumeric_Supplement': Block */ static const OnigCodePoint CR_In_Enclosed_Alphanumeric_Supplement[] = { 1, 0x1f100, 0x1f1ff, }; /* CR_In_Enclosed_Alphanumeric_Supplement */ /* 'In_Enclosed_Ideographic_Supplement': Block */ static const OnigCodePoint CR_In_Enclosed_Ideographic_Supplement[] = { 1, 0x1f200, 0x1f2ff, }; /* CR_In_Enclosed_Ideographic_Supplement */ /* 'In_Miscellaneous_Symbols_And_Pictographs': Block */ static const OnigCodePoint CR_In_Miscellaneous_Symbols_And_Pictographs[] = { 1, 0x1f300, 0x1f5ff, }; /* CR_In_Miscellaneous_Symbols_And_Pictographs */ /* 'In_Emoticons': Block */ static const OnigCodePoint CR_In_Emoticons[] = { 1, 0x1f600, 0x1f64f, }; /* CR_In_Emoticons */ /* 'In_Transport_And_Map_Symbols': Block */ static const OnigCodePoint CR_In_Transport_And_Map_Symbols[] = { 1, 0x1f680, 0x1f6ff, }; /* CR_In_Transport_And_Map_Symbols */ /* 'In_Alchemical_Symbols': Block */ static const OnigCodePoint CR_In_Alchemical_Symbols[] = { 1, 0x1f700, 0x1f77f, }; /* CR_In_Alchemical_Symbols */ /* 'In_CJK_Unified_Ideographs_Extension_B': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_B[] = { 1, 0x20000, 0x2a6df, }; /* CR_In_CJK_Unified_Ideographs_Extension_B */ /* 'In_CJK_Unified_Ideographs_Extension_C': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_C[] = { 1, 0x2a700, 0x2b73f, }; /* CR_In_CJK_Unified_Ideographs_Extension_C */ /* 'In_CJK_Unified_Ideographs_Extension_D': Block */ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_D[] = { 1, 0x2b740, 0x2b81f, }; /* CR_In_CJK_Unified_Ideographs_Extension_D */ /* 'In_CJK_Compatibility_Ideographs_Supplement': Block */ static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs_Supplement[] = { 1, 0x2f800, 0x2fa1f, }; /* CR_In_CJK_Compatibility_Ideographs_Supplement */ /* 'In_Tags': Block */ static const OnigCodePoint CR_In_Tags[] = { 1, 0xe0000, 0xe007f, }; /* CR_In_Tags */ /* 'In_Variation_Selectors_Supplement': Block */ static const OnigCodePoint CR_In_Variation_Selectors_Supplement[] = { 1, 0xe0100, 0xe01ef, }; /* CR_In_Variation_Selectors_Supplement */ /* 'In_Supplementary_Private_Use_Area_A': Block */ static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_A[] = { 1, 0xf0000, 0xfffff, }; /* CR_In_Supplementary_Private_Use_Area_A */ /* 'In_Supplementary_Private_Use_Area_B': Block */ static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_B[] = { 1, 0x100000, 0x10ffff, }; /* CR_In_Supplementary_Private_Use_Area_B */ /* 'In_No_Block': Block */ static const OnigCodePoint CR_In_No_Block[] = { 36, 0x0860, 0x089f, 0x1ab0, 0x1aff, 0x1c80, 0x1cbf, 0x2fe0, 0x2fef, 0xa9e0, 0xa9ff, 0xab30, 0xabbf, 0x10200, 0x1027f, 0x102e0, 0x102ff, 0x10350, 0x1037f, 0x103e0, 0x103ff, 0x104b0, 0x107ff, 0x10860, 0x108ff, 0x10940, 0x1097f, 0x10a80, 0x10aff, 0x10b80, 0x10bff, 0x10c50, 0x10e5f, 0x10e80, 0x10fff, 0x11150, 0x1117f, 0x111e0, 0x1167f, 0x116d0, 0x11fff, 0x12480, 0x12fff, 0x13430, 0x167ff, 0x16a40, 0x16eff, 0x16fa0, 0x1afff, 0x1b100, 0x1cfff, 0x1d250, 0x1d2ff, 0x1d380, 0x1d3ff, 0x1d800, 0x1edff, 0x1ef00, 0x1efff, 0x1f650, 0x1f67f, 0x1f780, 0x1ffff, 0x2a6e0, 0x2a6ff, 0x2b820, 0x2f7ff, 0x2fa20, 0xdffff, 0xe0080, 0xe00ff, 0xe01f0, 0xeffff, }; /* CR_In_No_Block */ #endif /* USE_UNICODE_PROPERTIES */ static const OnigCodePoint* const CodeRanges[] = { CR_NEWLINE, CR_Alpha, CR_Blank, CR_Cntrl, CR_Digit, CR_Graph, CR_Lower, CR_Print, CR_Punct, CR_Space, CR_Upper, CR_XDigit, CR_Word, CR_Alnum, CR_ASCII, #ifdef USE_UNICODE_PROPERTIES CR_Any, CR_Assigned, CR_C, CR_Cc, CR_Cf, CR_Cn, CR_Co, CR_Cs, CR_L, CR_LC, CR_Ll, CR_Lm, CR_Lo, CR_Lt, CR_Lu, CR_M, CR_Mc, CR_Me, CR_Mn, CR_N, CR_Nd, CR_Nl, CR_No, CR_P, CR_Pc, CR_Pd, CR_Pe, CR_Pf, CR_Pi, CR_Po, CR_Ps, CR_S, CR_Sc, CR_Sk, CR_Sm, CR_So, CR_Z, CR_Zl, CR_Zp, CR_Zs, CR_Math, CR_Alphabetic, CR_Lowercase, CR_Uppercase, CR_Cased, CR_Case_Ignorable, CR_Changes_When_Lowercased, CR_Changes_When_Uppercased, CR_Changes_When_Titlecased, CR_Changes_When_Casefolded, CR_Changes_When_Casemapped, CR_ID_Start, CR_ID_Continue, CR_XID_Start, CR_XID_Continue, CR_Default_Ignorable_Code_Point, CR_Grapheme_Extend, CR_Grapheme_Base, CR_Grapheme_Link, CR_Common, CR_Latin, CR_Greek, CR_Cyrillic, CR_Armenian, CR_Hebrew, CR_Arabic, CR_Syriac, CR_Thaana, CR_Devanagari, CR_Bengali, CR_Gurmukhi, CR_Gujarati, CR_Oriya, CR_Tamil, CR_Telugu, CR_Kannada, CR_Malayalam, CR_Sinhala, CR_Thai, CR_Lao, CR_Tibetan, CR_Myanmar, CR_Georgian, CR_Hangul, CR_Ethiopic, CR_Cherokee, CR_Canadian_Aboriginal, CR_Ogham, CR_Runic, CR_Khmer, CR_Mongolian, CR_Hiragana, CR_Katakana, CR_Bopomofo, CR_Han, CR_Yi, CR_Old_Italic, CR_Gothic, CR_Deseret, CR_Inherited, CR_Tagalog, CR_Hanunoo, CR_Buhid, CR_Tagbanwa, CR_Limbu, CR_Tai_Le, CR_Linear_B, CR_Ugaritic, CR_Shavian, CR_Osmanya, CR_Cypriot, CR_Braille, CR_Buginese, CR_Coptic, CR_New_Tai_Lue, CR_Glagolitic, CR_Tifinagh, CR_Syloti_Nagri, CR_Old_Persian, CR_Kharoshthi, CR_Balinese, CR_Cuneiform, CR_Phoenician, CR_Phags_Pa, CR_Nko, CR_Sundanese, CR_Lepcha, CR_Ol_Chiki, CR_Vai, CR_Saurashtra, CR_Kayah_Li, CR_Rejang, CR_Lycian, CR_Carian, CR_Lydian, CR_Cham, CR_Tai_Tham, CR_Tai_Viet, CR_Avestan, CR_Egyptian_Hieroglyphs, CR_Samaritan, CR_Lisu, CR_Bamum, CR_Javanese, CR_Meetei_Mayek, CR_Imperial_Aramaic, CR_Old_South_Arabian, CR_Inscriptional_Parthian, CR_Inscriptional_Pahlavi, CR_Old_Turkic, CR_Kaithi, CR_Batak, CR_Brahmi, CR_Mandaic, CR_Chakma, CR_Meroitic_Cursive, CR_Meroitic_Hieroglyphs, CR_Miao, CR_Sharada, CR_Sora_Sompeng, CR_Takri, CR_White_Space, CR_Bidi_Control, CR_Join_Control, CR_Dash, CR_Hyphen, CR_Quotation_Mark, CR_Terminal_Punctuation, CR_Other_Math, CR_Hex_Digit, CR_ASCII_Hex_Digit, CR_Other_Alphabetic, CR_Ideographic, CR_Diacritic, CR_Extender, CR_Other_Lowercase, CR_Other_Uppercase, CR_Noncharacter_Code_Point, CR_Other_Grapheme_Extend, CR_IDS_Binary_Operator, CR_IDS_Trinary_Operator, CR_Radical, CR_Unified_Ideograph, CR_Other_Default_Ignorable_Code_Point, CR_Deprecated, CR_Soft_Dotted, CR_Logical_Order_Exception, CR_Other_ID_Start, CR_Other_ID_Continue, CR_STerm, CR_Variation_Selector, CR_Pattern_White_Space, CR_Pattern_Syntax, CR_Unknown, CR_Age_1_1, CR_Age_2_0, CR_Age_2_1, CR_Age_3_0, CR_Age_3_1, CR_Age_3_2, CR_Age_4_0, CR_Age_4_1, CR_Age_5_0, CR_Age_5_1, CR_Age_5_2, CR_Age_6_0, CR_Age_6_1, CR_In_Basic_Latin, CR_In_Latin_1_Supplement, CR_In_Latin_Extended_A, CR_In_Latin_Extended_B, CR_In_IPA_Extensions, CR_In_Spacing_Modifier_Letters, CR_In_Combining_Diacritical_Marks, CR_In_Greek_and_Coptic, CR_In_Cyrillic, CR_In_Cyrillic_Supplement, CR_In_Armenian, CR_In_Hebrew, CR_In_Arabic, CR_In_Syriac, CR_In_Arabic_Supplement, CR_In_Thaana, CR_In_NKo, CR_In_Samaritan, CR_In_Mandaic, CR_In_Arabic_Extended_A, CR_In_Devanagari, CR_In_Bengali, CR_In_Gurmukhi, CR_In_Gujarati, CR_In_Oriya, CR_In_Tamil, CR_In_Telugu, CR_In_Kannada, CR_In_Malayalam, CR_In_Sinhala, CR_In_Thai, CR_In_Lao, CR_In_Tibetan, CR_In_Myanmar, CR_In_Georgian, CR_In_Hangul_Jamo, CR_In_Ethiopic, CR_In_Ethiopic_Supplement, CR_In_Cherokee, CR_In_Unified_Canadian_Aboriginal_Syllabics, CR_In_Ogham, CR_In_Runic, CR_In_Tagalog, CR_In_Hanunoo, CR_In_Buhid, CR_In_Tagbanwa, CR_In_Khmer, CR_In_Mongolian, CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended, CR_In_Limbu, CR_In_Tai_Le, CR_In_New_Tai_Lue, CR_In_Khmer_Symbols, CR_In_Buginese, CR_In_Tai_Tham, CR_In_Balinese, CR_In_Sundanese, CR_In_Batak, CR_In_Lepcha, CR_In_Ol_Chiki, CR_In_Sundanese_Supplement, CR_In_Vedic_Extensions, CR_In_Phonetic_Extensions, CR_In_Phonetic_Extensions_Supplement, CR_In_Combining_Diacritical_Marks_Supplement, CR_In_Latin_Extended_Additional, CR_In_Greek_Extended, CR_In_General_Punctuation, CR_In_Superscripts_and_Subscripts, CR_In_Currency_Symbols, CR_In_Combining_Diacritical_Marks_for_Symbols, CR_In_Letterlike_Symbols, CR_In_Number_Forms, CR_In_Arrows, CR_In_Mathematical_Operators, CR_In_Miscellaneous_Technical, CR_In_Control_Pictures, CR_In_Optical_Character_Recognition, CR_In_Enclosed_Alphanumerics, CR_In_Box_Drawing, CR_In_Block_Elements, CR_In_Geometric_Shapes, CR_In_Miscellaneous_Symbols, CR_In_Dingbats, CR_In_Miscellaneous_Mathematical_Symbols_A, CR_In_Supplemental_Arrows_A, CR_In_Braille_Patterns, CR_In_Supplemental_Arrows_B, CR_In_Miscellaneous_Mathematical_Symbols_B, CR_In_Supplemental_Mathematical_Operators, CR_In_Miscellaneous_Symbols_and_Arrows, CR_In_Glagolitic, CR_In_Latin_Extended_C, CR_In_Coptic, CR_In_Georgian_Supplement, CR_In_Tifinagh, CR_In_Ethiopic_Extended, CR_In_Cyrillic_Extended_A, CR_In_Supplemental_Punctuation, CR_In_CJK_Radicals_Supplement, CR_In_Kangxi_Radicals, CR_In_Ideographic_Description_Characters, CR_In_CJK_Symbols_and_Punctuation, CR_In_Hiragana, CR_In_Katakana, CR_In_Bopomofo, CR_In_Hangul_Compatibility_Jamo, CR_In_Kanbun, CR_In_Bopomofo_Extended, CR_In_CJK_Strokes, CR_In_Katakana_Phonetic_Extensions, CR_In_Enclosed_CJK_Letters_and_Months, CR_In_CJK_Compatibility, CR_In_CJK_Unified_Ideographs_Extension_A, CR_In_Yijing_Hexagram_Symbols, CR_In_CJK_Unified_Ideographs, CR_In_Yi_Syllables, CR_In_Yi_Radicals, CR_In_Lisu, CR_In_Vai, CR_In_Cyrillic_Extended_B, CR_In_Bamum, CR_In_Modifier_Tone_Letters, CR_In_Latin_Extended_D, CR_In_Syloti_Nagri, CR_In_Common_Indic_Number_Forms, CR_In_Phags_pa, CR_In_Saurashtra, CR_In_Devanagari_Extended, CR_In_Kayah_Li, CR_In_Rejang, CR_In_Hangul_Jamo_Extended_A, CR_In_Javanese, CR_In_Cham, CR_In_Myanmar_Extended_A, CR_In_Tai_Viet, CR_In_Meetei_Mayek_Extensions, CR_In_Ethiopic_Extended_A, CR_In_Meetei_Mayek, CR_In_Hangul_Syllables, CR_In_Hangul_Jamo_Extended_B, CR_In_High_Surrogates, CR_In_High_Private_Use_Surrogates, CR_In_Low_Surrogates, CR_In_Private_Use_Area, CR_In_CJK_Compatibility_Ideographs, CR_In_Alphabetic_Presentation_Forms, CR_In_Arabic_Presentation_Forms_A, CR_In_Variation_Selectors, CR_In_Vertical_Forms, CR_In_Combining_Half_Marks, CR_In_CJK_Compatibility_Forms, CR_In_Small_Form_Variants, CR_In_Arabic_Presentation_Forms_B, CR_In_Halfwidth_and_Fullwidth_Forms, CR_In_Specials, CR_In_Linear_B_Syllabary, CR_In_Linear_B_Ideograms, CR_In_Aegean_Numbers, CR_In_Ancient_Greek_Numbers, CR_In_Ancient_Symbols, CR_In_Phaistos_Disc, CR_In_Lycian, CR_In_Carian, CR_In_Old_Italic, CR_In_Gothic, CR_In_Ugaritic, CR_In_Old_Persian, CR_In_Deseret, CR_In_Shavian, CR_In_Osmanya, CR_In_Cypriot_Syllabary, CR_In_Imperial_Aramaic, CR_In_Phoenician, CR_In_Lydian, CR_In_Meroitic_Hieroglyphs, CR_In_Meroitic_Cursive, CR_In_Kharoshthi, CR_In_Old_South_Arabian, CR_In_Avestan, CR_In_Inscriptional_Parthian, CR_In_Inscriptional_Pahlavi, CR_In_Old_Turkic, CR_In_Rumi_Numeral_Symbols, CR_In_Brahmi, CR_In_Kaithi, CR_In_Sora_Sompeng, CR_In_Chakma, CR_In_Sharada, CR_In_Takri, CR_In_Cuneiform, CR_In_Cuneiform_Numbers_and_Punctuation, CR_In_Egyptian_Hieroglyphs, CR_In_Bamum_Supplement, CR_In_Miao, CR_In_Kana_Supplement, CR_In_Byzantine_Musical_Symbols, CR_In_Musical_Symbols, CR_In_Ancient_Greek_Musical_Notation, CR_In_Tai_Xuan_Jing_Symbols, CR_In_Counting_Rod_Numerals, CR_In_Mathematical_Alphanumeric_Symbols, CR_In_Arabic_Mathematical_Alphabetic_Symbols, CR_In_Mahjong_Tiles, CR_In_Domino_Tiles, CR_In_Playing_Cards, CR_In_Enclosed_Alphanumeric_Supplement, CR_In_Enclosed_Ideographic_Supplement, CR_In_Miscellaneous_Symbols_And_Pictographs, CR_In_Emoticons, CR_In_Transport_And_Map_Symbols, CR_In_Alchemical_Symbols, CR_In_CJK_Unified_Ideographs_Extension_B, CR_In_CJK_Unified_Ideographs_Extension_C, CR_In_CJK_Unified_Ideographs_Extension_D, CR_In_CJK_Compatibility_Ideographs_Supplement, CR_In_Tags, CR_In_Variation_Selectors_Supplement, CR_In_Supplementary_Private_Use_Area_A, CR_In_Supplementary_Private_Use_Area_B, CR_In_No_Block, #endif /* USE_UNICODE_PROPERTIES */ }; static const OnigCodePoint* const CodeScripts[] = { CR_Common, CR_Latin, CR_Greek, CR_Cyrillic, CR_Armenian, CR_Hebrew, CR_Arabic, CR_Syriac, CR_Thaana, CR_Devanagari, CR_Bengali, CR_Gurmukhi, CR_Gujarati, CR_Oriya, CR_Tamil, CR_Telugu, CR_Kannada, CR_Malayalam, CR_Sinhala, CR_Thai, CR_Lao, CR_Tibetan, CR_Myanmar, CR_Georgian, CR_Hangul, CR_Ethiopic, CR_Cherokee, CR_Canadian_Aboriginal, CR_Ogham, CR_Runic, CR_Khmer, CR_Mongolian, CR_Hiragana, CR_Katakana, CR_Bopomofo, CR_Han, CR_Yi, CR_Old_Italic, CR_Gothic, CR_Deseret, CR_Inherited, CR_Tagalog, CR_Hanunoo, CR_Buhid, CR_Tagbanwa, CR_Limbu, CR_Tai_Le, CR_Linear_B, CR_Ugaritic, CR_Shavian, CR_Osmanya, CR_Cypriot, CR_Braille, CR_Buginese, CR_Coptic, CR_New_Tai_Lue, CR_Glagolitic, CR_Tifinagh, CR_Syloti_Nagri, CR_Old_Persian, CR_Kharoshthi, CR_Balinese, CR_Cuneiform, CR_Phoenician, CR_Phags_Pa, CR_Nko, CR_Sundanese, CR_Lepcha, CR_Ol_Chiki, CR_Vai, CR_Saurashtra, CR_Kayah_Li, CR_Rejang, CR_Lycian, CR_Carian, CR_Lydian, CR_Cham, CR_Tai_Tham, CR_Tai_Viet, CR_Avestan, CR_Egyptian_Hieroglyphs, CR_Samaritan, CR_Lisu, CR_Bamum, CR_Javanese, CR_Meetei_Mayek, CR_Imperial_Aramaic, CR_Old_South_Arabian, CR_Inscriptional_Parthian, CR_Inscriptional_Pahlavi, CR_Old_Turkic, CR_Kaithi, CR_Batak, CR_Brahmi, CR_Mandaic, CR_Chakma, CR_Meroitic_Cursive, CR_Meroitic_Hieroglyphs, CR_Miao, CR_Sharada, CR_Sora_Sompeng, CR_Takri }; struct uniname2ctype_struct { int name, ctype; }; static const struct uniname2ctype_struct *uniname2ctype_p(const char *, unsigned int); #ifndef USE_UNICODE_PROPERTIES #define TOTAL_KEYWORDS 14 #define MIN_WORD_LENGTH 4 #define MAX_WORD_LENGTH 6 #define MIN_HASH_VALUE 6 #define MAX_HASH_VALUE 19 /* maximum key range = 14, duplicates = 0 */ #else /* USE_UNICODE_PROPERTIES */ #define TOTAL_KEYWORDS 625 #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 44 #define MIN_HASH_VALUE 3 #define MAX_HASH_VALUE 4167 /* maximum key range = 4165, duplicates = 0 */ #endif /* USE_UNICODE_PROPERTIES */ #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static unsigned int uniname2ctype_hash (str, len) register const char *str; register unsigned int len; { #ifndef USE_UNICODE_PROPERTIES static const unsigned char asso_values[] = #else /* USE_UNICODE_PROPERTIES */ static const unsigned short asso_values[] = #endif /* USE_UNICODE_PROPERTIES */ { #ifndef USE_UNICODE_PROPERTIES 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 3, 11, 5, 4, 20, 20, 9, 20, 1, 20, 20, 10, 20, 2, 20, 1, 20, 1, 7, 4, 6, 20, 1, 4, 20, 20, 20, 20, 20, 20, 20 #else /* USE_UNICODE_PROPERTIES */ 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 1, 4168, 13, 1, 3, 28, 31, 10, 27, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 4168, 13, 854, 14, 443, 19, 7, 570, 335, 4, 66, 1159, 102, 34, 1, 178, 474, 1, 192, 2, 64, 1117, 491, 264, 256, 1305, 3, 4168, 4168, 4168, 4168, 4168 #endif /* USE_UNICODE_PROPERTIES */ }; #ifndef USE_UNICODE_PROPERTIES return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]]; #else /* USE_UNICODE_PROPERTIES */ register int hval = len; switch (hval) { default: hval += asso_values[(unsigned char)str[15]]; /*FALLTHROUGH*/ case 15: case 14: case 13: case 12: hval += asso_values[(unsigned char)str[11]]; /*FALLTHROUGH*/ case 11: case 10: case 9: case 8: case 7: case 6: hval += asso_values[(unsigned char)str[5]]; /*FALLTHROUGH*/ case 5: hval += asso_values[(unsigned char)str[4]]; /*FALLTHROUGH*/ case 4: case 3: hval += asso_values[(unsigned char)str[2]]; /*FALLTHROUGH*/ case 2: hval += asso_values[(unsigned char)str[1]]; /*FALLTHROUGH*/ case 1: hval += asso_values[(unsigned char)str[0]]; break; } return hval + asso_values[(unsigned char)str[len - 1]]; #endif /* USE_UNICODE_PROPERTIES */ } struct uniname2ctype_pool_t { #ifndef USE_UNICODE_PROPERTIES char uniname2ctype_pool_str6[sizeof("word")]; char uniname2ctype_pool_str7[sizeof("print")]; char uniname2ctype_pool_str8[sizeof("punct")]; char uniname2ctype_pool_str9[sizeof("alpha")]; char uniname2ctype_pool_str10[sizeof("alnum")]; char uniname2ctype_pool_str11[sizeof("xdigit")]; char uniname2ctype_pool_str12[sizeof("upper")]; char uniname2ctype_pool_str13[sizeof("ascii")]; char uniname2ctype_pool_str14[sizeof("cntrl")]; char uniname2ctype_pool_str15[sizeof("space")]; char uniname2ctype_pool_str16[sizeof("lower")]; char uniname2ctype_pool_str17[sizeof("graph")]; char uniname2ctype_pool_str18[sizeof("digit")]; char uniname2ctype_pool_str19[sizeof("blank")]; #else /* USE_UNICODE_PROPERTIES */ char uniname2ctype_pool_str3[sizeof("n")]; char uniname2ctype_pool_str5[sizeof("s")]; char uniname2ctype_pool_str7[sizeof("z")]; char uniname2ctype_pool_str9[sizeof("zs")]; char uniname2ctype_pool_str16[sizeof("zzzz")]; char uniname2ctype_pool_str18[sizeof("cn")]; char uniname2ctype_pool_str20[sizeof("cs")]; char uniname2ctype_pool_str24[sizeof("ci")]; char uniname2ctype_pool_str29[sizeof("c")]; char uniname2ctype_pool_str30[sizeof("cf")]; char uniname2ctype_pool_str32[sizeof("sc")]; char uniname2ctype_pool_str34[sizeof("cans")]; char uniname2ctype_pool_str35[sizeof("qaai")]; char uniname2ctype_pool_str38[sizeof("mn")]; char uniname2ctype_pool_str42[sizeof("ascii")]; char uniname2ctype_pool_str44[sizeof("cc")]; char uniname2ctype_pool_str45[sizeof("qaac")]; char uniname2ctype_pool_str49[sizeof("inavestan")]; char uniname2ctype_pool_str52[sizeof("inspecials")]; char uniname2ctype_pool_str62[sizeof("inipaextensions")]; char uniname2ctype_pool_str64[sizeof("mc")]; char uniname2ctype_pool_str66[sizeof("insamaritan")]; char uniname2ctype_pool_str69[sizeof("m")]; char uniname2ctype_pool_str72[sizeof("sm")]; char uniname2ctype_pool_str74[sizeof("me")]; char uniname2ctype_pool_str82[sizeof("inarmenian")]; char uniname2ctype_pool_str84[sizeof("incuneiform")]; char uniname2ctype_pool_str86[sizeof("mandaic")]; char uniname2ctype_pool_str90[sizeof("inancientsymbols")]; char uniname2ctype_pool_str92[sizeof("incuneiformnumbersandpunctuation")]; char uniname2ctype_pool_str96[sizeof("inthai")]; char uniname2ctype_pool_str99[sizeof("inmusicalsymbols")]; char uniname2ctype_pool_str100[sizeof("inmiscellaneoussymbols")]; char uniname2ctype_pool_str106[sizeof("incham")]; char uniname2ctype_pool_str109[sizeof("inmiscellaneoussymbolsandarrows")]; char uniname2ctype_pool_str113[sizeof("initialpunctuation")]; char uniname2ctype_pool_str114[sizeof("inmiscellaneoussymbolsandpictographs")]; char uniname2ctype_pool_str116[sizeof("inthaana")]; char uniname2ctype_pool_str124[sizeof("taile")]; char uniname2ctype_pool_str125[sizeof("mtei")]; char uniname2ctype_pool_str132[sizeof("lc")]; char uniname2ctype_pool_str133[sizeof("lana")]; char uniname2ctype_pool_str134[sizeof("inlycian")]; char uniname2ctype_pool_str135[sizeof("intransportandmapsymbols")]; char uniname2ctype_pool_str136[sizeof("incontrolpictures")]; char uniname2ctype_pool_str142[sizeof("sinhala")]; char uniname2ctype_pool_str151[sizeof("incommonindicnumberforms")]; char uniname2ctype_pool_str156[sizeof("inmiscellaneousmathematicalsymbolsa")]; char uniname2ctype_pool_str158[sizeof("sterm")]; char uniname2ctype_pool_str167[sizeof("inmyanmarextendeda")]; char uniname2ctype_pool_str172[sizeof("lm")]; char uniname2ctype_pool_str175[sizeof("taiviet")]; char uniname2ctype_pool_str179[sizeof("inlinearbideograms")]; char uniname2ctype_pool_str180[sizeof("intaitham")]; char uniname2ctype_pool_str184[sizeof("latn")]; char uniname2ctype_pool_str186[sizeof("latin")]; char uniname2ctype_pool_str187[sizeof("ital")]; char uniname2ctype_pool_str189[sizeof("alnum")]; char uniname2ctype_pool_str199[sizeof("inmalayalam")]; char uniname2ctype_pool_str201[sizeof("intaile")]; char uniname2ctype_pool_str202[sizeof("tale")]; char uniname2ctype_pool_str205[sizeof("l")]; char uniname2ctype_pool_str207[sizeof("nl")]; char uniname2ctype_pool_str209[sizeof("zl")]; char uniname2ctype_pool_str216[sizeof("intamil")]; char uniname2ctype_pool_str217[sizeof("taml")]; char uniname2ctype_pool_str218[sizeof("inlatinextendeda")]; char uniname2ctype_pool_str220[sizeof("inlatinextendedc")]; char uniname2ctype_pool_str223[sizeof("inrunic")]; char uniname2ctype_pool_str224[sizeof("incarian")]; char uniname2ctype_pool_str225[sizeof("insyriac")]; char uniname2ctype_pool_str227[sizeof("cari")]; char uniname2ctype_pool_str230[sizeof("inmeeteimayekextensions")]; char uniname2ctype_pool_str231[sizeof("osma")]; char uniname2ctype_pool_str232[sizeof("lt")]; char uniname2ctype_pool_str233[sizeof("miao")]; char uniname2ctype_pool_str234[sizeof("insharada")]; char uniname2ctype_pool_str239[sizeof("incyrillic")]; char uniname2ctype_pool_str240[sizeof("carian")]; char uniname2ctype_pool_str244[sizeof("armn")]; char uniname2ctype_pool_str245[sizeof("samr")]; char uniname2ctype_pool_str247[sizeof("armi")]; char uniname2ctype_pool_str248[sizeof("inideographicdescriptioncharacters")]; char uniname2ctype_pool_str252[sizeof("inosmanya")]; char uniname2ctype_pool_str253[sizeof("armenian")]; char uniname2ctype_pool_str254[sizeof("inmyanmar")]; char uniname2ctype_pool_str255[sizeof("samaritan")]; char uniname2ctype_pool_str256[sizeof("arabic")]; char uniname2ctype_pool_str259[sizeof("incherokee")]; char uniname2ctype_pool_str261[sizeof("connectorpunctuation")]; char uniname2ctype_pool_str263[sizeof("merc")]; char uniname2ctype_pool_str264[sizeof("inmiscellaneoustechnical")]; char uniname2ctype_pool_str268[sizeof("inenclosedalphanumerics")]; char uniname2ctype_pool_str279[sizeof("inemoticons")]; char uniname2ctype_pool_str281[sizeof("joinc")]; char uniname2ctype_pool_str288[sizeof("cntrl")]; char uniname2ctype_pool_str301[sizeof("inenclosedcjklettersandmonths")]; char uniname2ctype_pool_str303[sizeof("cwcf")]; char uniname2ctype_pool_str304[sizeof("inruminumeralsymbols")]; char uniname2ctype_pool_str308[sizeof("ll")]; char uniname2ctype_pool_str313[sizeof("term")]; char uniname2ctype_pool_str316[sizeof("inlatinextendedadditional")]; char uniname2ctype_pool_str320[sizeof("tamil")]; char uniname2ctype_pool_str321[sizeof("loe")]; char uniname2ctype_pool_str329[sizeof("newtailue")]; char uniname2ctype_pool_str330[sizeof("cwcm")]; char uniname2ctype_pool_str339[sizeof("inenclosedalphanumericsupplement")]; char uniname2ctype_pool_str346[sizeof("sinh")]; char uniname2ctype_pool_str347[sizeof("zinh")]; char uniname2ctype_pool_str349[sizeof("meroiticcursive")]; char uniname2ctype_pool_str353[sizeof("han")]; char uniname2ctype_pool_str357[sizeof("hani")]; char uniname2ctype_pool_str358[sizeof("inopticalcharacterrecognition")]; char uniname2ctype_pool_str359[sizeof("no")]; char uniname2ctype_pool_str360[sizeof("so")]; char uniname2ctype_pool_str364[sizeof("innewtailue")]; char uniname2ctype_pool_str365[sizeof("insinhala")]; char uniname2ctype_pool_str367[sizeof("innko")]; char uniname2ctype_pool_str372[sizeof("co")]; char uniname2ctype_pool_str375[sizeof("shavian")]; char uniname2ctype_pool_str378[sizeof("terminalpunctuation")]; char uniname2ctype_pool_str386[sizeof("intaixuanjingsymbols")]; char uniname2ctype_pool_str387[sizeof("inethiopic")]; char uniname2ctype_pool_str389[sizeof("sora")]; char uniname2ctype_pool_str398[sizeof("inarrows")]; char uniname2ctype_pool_str400[sizeof("cham")]; char uniname2ctype_pool_str403[sizeof("inlowsurrogates")]; char uniname2ctype_pool_str405[sizeof("oriya")]; char uniname2ctype_pool_str406[sizeof("ext")]; char uniname2ctype_pool_str409[sizeof("cwt")]; char uniname2ctype_pool_str412[sizeof("common")]; char uniname2ctype_pool_str414[sizeof("inmiao")]; char uniname2ctype_pool_str420[sizeof("thai")]; char uniname2ctype_pool_str425[sizeof("intifinagh")]; char uniname2ctype_pool_str426[sizeof("ethi")]; char uniname2ctype_pool_str427[sizeof("mero")]; char uniname2ctype_pool_str428[sizeof("chakma")]; char uniname2ctype_pool_str429[sizeof("thaa")]; char uniname2ctype_pool_str430[sizeof("inscriptionalparthian")]; char uniname2ctype_pool_str432[sizeof("tifinagh")]; char uniname2ctype_pool_str436[sizeof("titlecaseletter")]; char uniname2ctype_pool_str445[sizeof("thaana")]; char uniname2ctype_pool_str449[sizeof("asciihexdigit")]; char uniname2ctype_pool_str450[sizeof("math")]; char uniname2ctype_pool_str453[sizeof("di")]; char uniname2ctype_pool_str454[sizeof("ids")]; char uniname2ctype_pool_str460[sizeof("lo")]; char uniname2ctype_pool_str468[sizeof("inlao")]; char uniname2ctype_pool_str470[sizeof("taitham")]; char uniname2ctype_pool_str474[sizeof("lao")]; char uniname2ctype_pool_str475[sizeof("laoo")]; char uniname2ctype_pool_str476[sizeof("dia")]; char uniname2ctype_pool_str478[sizeof("idc")]; char uniname2ctype_pool_str480[sizeof("ps")]; char uniname2ctype_pool_str481[sizeof("insundanese")]; char uniname2ctype_pool_str484[sizeof("pi")]; char uniname2ctype_pool_str485[sizeof("cwl")]; char uniname2ctype_pool_str490[sizeof("pf")]; char uniname2ctype_pool_str495[sizeof("mand")]; char uniname2ctype_pool_str496[sizeof("insylotinagri")]; char uniname2ctype_pool_str497[sizeof("vs")]; char uniname2ctype_pool_str503[sizeof("mongolian")]; char uniname2ctype_pool_str504[sizeof("pc")]; char uniname2ctype_pool_str506[sizeof("inmandaic")]; char uniname2ctype_pool_str509[sizeof("invai")]; char uniname2ctype_pool_str511[sizeof("lineseparator")]; char uniname2ctype_pool_str514[sizeof("pe")]; char uniname2ctype_pool_str515[sizeof("vai")]; char uniname2ctype_pool_str516[sizeof("vaii")]; char uniname2ctype_pool_str517[sizeof("idst")]; char uniname2ctype_pool_str520[sizeof("indominotiles")]; char uniname2ctype_pool_str521[sizeof("inshavian")]; char uniname2ctype_pool_str522[sizeof("inspacingmodifierletters")]; char uniname2ctype_pool_str524[sizeof("format")]; char uniname2ctype_pool_str528[sizeof("inphaistosdisc")]; char uniname2ctype_pool_str531[sizeof("hano")]; char uniname2ctype_pool_str532[sizeof("space")]; char uniname2ctype_pool_str542[sizeof("indeseret")]; char uniname2ctype_pool_str545[sizeof("inolchiki")]; char uniname2ctype_pool_str548[sizeof("hira")]; char uniname2ctype_pool_str553[sizeof("joincontrol")]; char uniname2ctype_pool_str555[sizeof("idcontinue")]; char uniname2ctype_pool_str558[sizeof("inmahjongtiles")]; char uniname2ctype_pool_str560[sizeof("patws")]; char uniname2ctype_pool_str563[sizeof("inlydian")]; char uniname2ctype_pool_str564[sizeof("cher")]; char uniname2ctype_pool_str568[sizeof("inhiragana")]; char uniname2ctype_pool_str572[sizeof("inogham")]; char uniname2ctype_pool_str574[sizeof("avst")]; char uniname2ctype_pool_str575[sizeof("inscriptionalpahlavi")]; char uniname2ctype_pool_str579[sizeof("incoptic")]; char uniname2ctype_pool_str587[sizeof("java")]; char uniname2ctype_pool_str589[sizeof("inmathematicalalphanumericsymbols")]; char uniname2ctype_pool_str594[sizeof("letter")]; char uniname2ctype_pool_str604[sizeof("injavanese")]; char uniname2ctype_pool_str608[sizeof("avestan")]; char uniname2ctype_pool_str612[sizeof("age=1.1")]; char uniname2ctype_pool_str613[sizeof("lepc")]; char uniname2ctype_pool_str614[sizeof("age=2.1")]; char uniname2ctype_pool_str616[sizeof("inlepcha")]; char uniname2ctype_pool_str617[sizeof("javanese")]; char uniname2ctype_pool_str618[sizeof("shaw")]; char uniname2ctype_pool_str619[sizeof("finalpunctuation")]; char uniname2ctype_pool_str620[sizeof("alpha")]; char uniname2ctype_pool_str621[sizeof("age=5.1")]; char uniname2ctype_pool_str622[sizeof("inmongolian")]; char uniname2ctype_pool_str623[sizeof("age=5.2")]; char uniname2ctype_pool_str626[sizeof("age=2.0")]; char uniname2ctype_pool_str627[sizeof("ahex")]; char uniname2ctype_pool_str630[sizeof("ingeneralpunctuation")]; char uniname2ctype_pool_str631[sizeof("oids")]; char uniname2ctype_pool_str632[sizeof("odi")]; char uniname2ctype_pool_str633[sizeof("age=5.0")]; char uniname2ctype_pool_str636[sizeof("tavt")]; char uniname2ctype_pool_str637[sizeof("intaiviet")]; char uniname2ctype_pool_str638[sizeof("age=6.1")]; char uniname2ctype_pool_str639[sizeof("age=3.1")]; char uniname2ctype_pool_str640[sizeof("insundanesesupplement")]; char uniname2ctype_pool_str641[sizeof("age=3.2")]; char uniname2ctype_pool_str642[sizeof("age=4.1")]; char uniname2ctype_pool_str643[sizeof("oidc")]; char uniname2ctype_pool_str646[sizeof("tfng")]; char uniname2ctype_pool_str647[sizeof("insmallformvariants")]; char uniname2ctype_pool_str648[sizeof("ideo")]; char uniname2ctype_pool_str649[sizeof("intags")]; char uniname2ctype_pool_str650[sizeof("age=6.0")]; char uniname2ctype_pool_str651[sizeof("age=3.0")]; char uniname2ctype_pool_str653[sizeof("whitespace")]; char uniname2ctype_pool_str654[sizeof("age=4.0")]; char uniname2ctype_pool_str655[sizeof("inolditalic")]; char uniname2ctype_pool_str660[sizeof("oalpha")]; char uniname2ctype_pool_str668[sizeof("ingujarati")]; char uniname2ctype_pool_str672[sizeof("control")]; char uniname2ctype_pool_str679[sizeof("diacritic")]; char uniname2ctype_pool_str682[sizeof("tagbanwa")]; char uniname2ctype_pool_str690[sizeof("inphoenician")]; char uniname2ctype_pool_str701[sizeof("ininscriptionalparthian")]; char uniname2ctype_pool_str703[sizeof("ininscriptionalpahlavi")]; char uniname2ctype_pool_str704[sizeof("coptic")]; char uniname2ctype_pool_str705[sizeof("dsrt")]; char uniname2ctype_pool_str706[sizeof("inmodifiertoneletters")]; char uniname2ctype_pool_str709[sizeof("xids")]; char uniname2ctype_pool_str713[sizeof("hanunoo")]; char uniname2ctype_pool_str715[sizeof("inoldturkic")]; char uniname2ctype_pool_str721[sizeof("xidc")]; char uniname2ctype_pool_str725[sizeof("idstart")]; char uniname2ctype_pool_str729[sizeof("inimperialaramaic")]; char uniname2ctype_pool_str730[sizeof("invariationselectors")]; char uniname2ctype_pool_str734[sizeof("copt")]; char uniname2ctype_pool_str737[sizeof("caseignorable")]; char uniname2ctype_pool_str738[sizeof("prti")]; char uniname2ctype_pool_str739[sizeof("nchar")]; char uniname2ctype_pool_str746[sizeof("deseret")]; char uniname2ctype_pool_str747[sizeof("decimalnumber")]; char uniname2ctype_pool_str748[sizeof("cprt")]; char uniname2ctype_pool_str750[sizeof("inlatin1supplement")]; char uniname2ctype_pool_str771[sizeof("imperialaramaic")]; char uniname2ctype_pool_str776[sizeof("privateuse")]; char uniname2ctype_pool_str777[sizeof("casedletter")]; char uniname2ctype_pool_str778[sizeof("lowercase")]; char uniname2ctype_pool_str780[sizeof("spaceseparator")]; char uniname2ctype_pool_str784[sizeof("radical")]; char uniname2ctype_pool_str787[sizeof("mong")]; char uniname2ctype_pool_str788[sizeof("canadianaboriginal")]; char uniname2ctype_pool_str792[sizeof("letternumber")]; char uniname2ctype_pool_str796[sizeof("insorasompeng")]; char uniname2ctype_pool_str797[sizeof("dash")]; char uniname2ctype_pool_str798[sizeof("wspace")]; char uniname2ctype_pool_str799[sizeof("ogam")]; char uniname2ctype_pool_str802[sizeof("invariationselectorssupplement")]; char uniname2ctype_pool_str803[sizeof("print")]; char uniname2ctype_pool_str811[sizeof("otheridcontinue")]; char uniname2ctype_pool_str815[sizeof("ingurmukhi")]; char uniname2ctype_pool_str818[sizeof("closepunctuation")]; char uniname2ctype_pool_str823[sizeof("olditalic")]; char uniname2ctype_pool_str824[sizeof("noncharactercodepoint")]; char uniname2ctype_pool_str826[sizeof("sharada")]; char uniname2ctype_pool_str827[sizeof("ingeometricshapes")]; char uniname2ctype_pool_str830[sizeof("otheralphabetic")]; char uniname2ctype_pool_str831[sizeof("patternwhitespace")]; char uniname2ctype_pool_str832[sizeof("po")]; char uniname2ctype_pool_str833[sizeof("rjng")]; char uniname2ctype_pool_str835[sizeof("ingreekandcoptic")]; char uniname2ctype_pool_str841[sizeof("xdigit")]; char uniname2ctype_pool_str850[sizeof("gothic")]; char uniname2ctype_pool_str851[sizeof("inoldsoutharabian")]; char uniname2ctype_pool_str852[sizeof("xidstart")]; char uniname2ctype_pool_str854[sizeof("inrejang")]; char uniname2ctype_pool_str860[sizeof("idsbinaryoperator")]; char uniname2ctype_pool_str867[sizeof("olower")]; char uniname2ctype_pool_str869[sizeof("hex")]; char uniname2ctype_pool_str870[sizeof("inenclosedideographicsupplement")]; char uniname2ctype_pool_str874[sizeof("inalphabeticpresentationforms")]; char uniname2ctype_pool_str879[sizeof("inbasiclatin")]; char uniname2ctype_pool_str884[sizeof("othersymbol")]; char uniname2ctype_pool_str889[sizeof("nd")]; char uniname2ctype_pool_str890[sizeof("sd")]; char uniname2ctype_pool_str900[sizeof("omath")]; char uniname2ctype_pool_str901[sizeof("separator")]; char uniname2ctype_pool_str907[sizeof("inarabic")]; char uniname2ctype_pool_str912[sizeof("xidcontinue")]; char uniname2ctype_pool_str913[sizeof("otheridstart")]; char uniname2ctype_pool_str914[sizeof("grext")]; char uniname2ctype_pool_str917[sizeof("otherlowercase")]; char uniname2ctype_pool_str919[sizeof("phli")]; char uniname2ctype_pool_str920[sizeof("cased")]; char uniname2ctype_pool_str923[sizeof("hang")]; char uniname2ctype_pool_str931[sizeof("xpeo")]; char uniname2ctype_pool_str933[sizeof("lower")]; char uniname2ctype_pool_str936[sizeof("modifierletter")]; char uniname2ctype_pool_str938[sizeof("inphoneticextensions")]; char uniname2ctype_pool_str939[sizeof("inarabicpresentationformsa")]; char uniname2ctype_pool_str943[sizeof("innumberforms")]; char uniname2ctype_pool_str945[sizeof("oldpersian")]; char uniname2ctype_pool_str946[sizeof("incyrillicextendeda")]; char uniname2ctype_pool_str947[sizeof("inverticalforms")]; char uniname2ctype_pool_str949[sizeof("p")]; char uniname2ctype_pool_str950[sizeof("inbyzantinemusicalsymbols")]; char uniname2ctype_pool_str951[sizeof("inmathematicaloperators")]; char uniname2ctype_pool_str952[sizeof("intibetan")]; char uniname2ctype_pool_str953[sizeof("zp")]; char uniname2ctype_pool_str956[sizeof("ingeorgian")]; char uniname2ctype_pool_str960[sizeof("inbraillepatterns")]; char uniname2ctype_pool_str962[sizeof("lepcha")]; char uniname2ctype_pool_str963[sizeof("geor")]; char uniname2ctype_pool_str964[sizeof("invedicextensions")]; char uniname2ctype_pool_str965[sizeof("linb")]; char uniname2ctype_pool_str966[sizeof("other")]; char uniname2ctype_pool_str970[sizeof("deva")]; char uniname2ctype_pool_str972[sizeof("indevanagari")]; char uniname2ctype_pool_str973[sizeof("othernumber")]; char uniname2ctype_pool_str974[sizeof("bamum")]; char uniname2ctype_pool_str976[sizeof("shrd")]; char uniname2ctype_pool_str977[sizeof("bali")]; char uniname2ctype_pool_str981[sizeof("devanagari")]; char uniname2ctype_pool_str983[sizeof("extender")]; char uniname2ctype_pool_str988[sizeof("inherited")]; char uniname2ctype_pool_str989[sizeof("glagolitic")]; char uniname2ctype_pool_str990[sizeof("tibt")]; char uniname2ctype_pool_str994[sizeof("inbalinese")]; char uniname2ctype_pool_str996[sizeof("ingothic")]; char uniname2ctype_pool_str997[sizeof("inmiscellaneousmathematicalsymbolsb")]; char uniname2ctype_pool_str998[sizeof("limb")]; char uniname2ctype_pool_str1000[sizeof("bengali")]; char uniname2ctype_pool_str1003[sizeof("phoenician")]; char uniname2ctype_pool_str1004[sizeof("insuperscriptsandsubscripts")]; char uniname2ctype_pool_str1006[sizeof("inmeroitichieroglyphs")]; char uniname2ctype_pool_str1007[sizeof("tibetan")]; char uniname2ctype_pool_str1010[sizeof("inphoneticextensionssupplement")]; char uniname2ctype_pool_str1016[sizeof("balinese")]; char uniname2ctype_pool_str1021[sizeof("lowercaseletter")]; char uniname2ctype_pool_str1031[sizeof("indingbats")]; char uniname2ctype_pool_str1035[sizeof("inprivateusearea")]; char uniname2ctype_pool_str1039[sizeof("assigned")]; char uniname2ctype_pool_str1044[sizeof("patternsyntax")]; char uniname2ctype_pool_str1051[sizeof("inhangulsyllables")]; char uniname2ctype_pool_str1065[sizeof("sarb")]; char uniname2ctype_pool_str1067[sizeof("brai")]; char uniname2ctype_pool_str1069[sizeof("insupplementalmathematicaloperators")]; char uniname2ctype_pool_str1070[sizeof("phnx")]; char uniname2ctype_pool_str1072[sizeof("ingreekextended")]; char uniname2ctype_pool_str1074[sizeof("otherletter")]; char uniname2ctype_pool_str1076[sizeof("arab")]; char uniname2ctype_pool_str1078[sizeof("inlatinextendedd")]; char uniname2ctype_pool_str1081[sizeof("word")]; char uniname2ctype_pool_str1084[sizeof("inphagspa")]; char uniname2ctype_pool_str1087[sizeof("inblockelements")]; char uniname2ctype_pool_str1092[sizeof("ethiopic")]; char uniname2ctype_pool_str1094[sizeof("inethiopicextendeda")]; char uniname2ctype_pool_str1107[sizeof("brahmi")]; char uniname2ctype_pool_str1110[sizeof("logicalorderexception")]; char uniname2ctype_pool_str1114[sizeof("inoldpersian")]; char uniname2ctype_pool_str1129[sizeof("inletterlikesymbols")]; char uniname2ctype_pool_str1133[sizeof("sorasompeng")]; char uniname2ctype_pool_str1135[sizeof("hiragana")]; char uniname2ctype_pool_str1142[sizeof("inhanguljamoextendeda")]; char uniname2ctype_pool_str1147[sizeof("othermath")]; char uniname2ctype_pool_str1150[sizeof("digit")]; char uniname2ctype_pool_str1151[sizeof("goth")]; char uniname2ctype_pool_str1156[sizeof("ogham")]; char uniname2ctype_pool_str1162[sizeof("sundanese")]; char uniname2ctype_pool_str1170[sizeof("saurashtra")]; char uniname2ctype_pool_str1173[sizeof("linearb")]; char uniname2ctype_pool_str1179[sizeof("graphemebase")]; char uniname2ctype_pool_str1185[sizeof("inunifiedcanadianaboriginalsyllabics")]; char uniname2ctype_pool_str1186[sizeof("cuneiform")]; char uniname2ctype_pool_str1188[sizeof("inkannada")]; char uniname2ctype_pool_str1190[sizeof("kana")]; char uniname2ctype_pool_str1195[sizeof("inancientgreeknumbers")]; char uniname2ctype_pool_str1196[sizeof("incjkstrokes")]; char uniname2ctype_pool_str1198[sizeof("inglagolitic")]; char uniname2ctype_pool_str1202[sizeof("inancientgreekmusicalnotation")]; char uniname2ctype_pool_str1212[sizeof("inchakma")]; char uniname2ctype_pool_str1215[sizeof("plrd")]; char uniname2ctype_pool_str1219[sizeof("inbrahmi")]; char uniname2ctype_pool_str1224[sizeof("cakm")]; char uniname2ctype_pool_str1225[sizeof("incjkcompatibilityforms")]; char uniname2ctype_pool_str1229[sizeof("lisu")]; char uniname2ctype_pool_str1230[sizeof("incjkcompatibilityideographs")]; char uniname2ctype_pool_str1231[sizeof("intagalog")]; char uniname2ctype_pool_str1244[sizeof("inkaithi")]; char uniname2ctype_pool_str1245[sizeof("insupplementalarrowsa")]; char uniname2ctype_pool_str1249[sizeof("takri")]; char uniname2ctype_pool_str1253[sizeof("ideographic")]; char uniname2ctype_pool_str1256[sizeof("hexdigit")]; char uniname2ctype_pool_str1259[sizeof("glag")]; char uniname2ctype_pool_str1261[sizeof("softdotted")]; char uniname2ctype_pool_str1262[sizeof("variationselector")]; char uniname2ctype_pool_str1264[sizeof("inkatakana")]; char uniname2ctype_pool_str1265[sizeof("meeteimayek")]; char uniname2ctype_pool_str1274[sizeof("otherpunctuation")]; char uniname2ctype_pool_str1279[sizeof("inhanguljamo")]; char uniname2ctype_pool_str1282[sizeof("kali")]; char uniname2ctype_pool_str1289[sizeof("braille")]; char uniname2ctype_pool_str1298[sizeof("incombininghalfmarks")]; char uniname2ctype_pool_str1300[sizeof("talu")]; char uniname2ctype_pool_str1302[sizeof("incjkcompatibilityideographssupplement")]; char uniname2ctype_pool_str1306[sizeof("telu")]; char uniname2ctype_pool_str1307[sizeof("idsb")]; char uniname2ctype_pool_str1310[sizeof("tglg")]; char uniname2ctype_pool_str1313[sizeof("inmeeteimayek")]; char uniname2ctype_pool_str1315[sizeof("yi")]; char uniname2ctype_pool_str1318[sizeof("phagspa")]; char uniname2ctype_pool_str1321[sizeof("yiii")]; char uniname2ctype_pool_str1323[sizeof("inarabicmathematicalalphabeticsymbols")]; char uniname2ctype_pool_str1328[sizeof("saur")]; char uniname2ctype_pool_str1330[sizeof("ogrext")]; char uniname2ctype_pool_str1334[sizeof("bidic")]; char uniname2ctype_pool_str1341[sizeof("inkanasupplement")]; char uniname2ctype_pool_str1343[sizeof("runic")]; char uniname2ctype_pool_str1344[sizeof("inalchemicalsymbols")]; char uniname2ctype_pool_str1350[sizeof("georgian")]; char uniname2ctype_pool_str1351[sizeof("inugaritic")]; char uniname2ctype_pool_str1354[sizeof("insaurashtra")]; char uniname2ctype_pool_str1356[sizeof("inhighprivateusesurrogates")]; char uniname2ctype_pool_str1362[sizeof("pd")]; char uniname2ctype_pool_str1372[sizeof("incountingrodnumerals")]; char uniname2ctype_pool_str1377[sizeof("inarabicextendeda")]; char uniname2ctype_pool_str1389[sizeof("inkharoshthi")]; char uniname2ctype_pool_str1393[sizeof("idstrinaryoperator")]; char uniname2ctype_pool_str1396[sizeof("phag")]; char uniname2ctype_pool_str1398[sizeof("brah")]; char uniname2ctype_pool_str1402[sizeof("mark")]; char uniname2ctype_pool_str1404[sizeof("hebr")]; char uniname2ctype_pool_str1411[sizeof("inkhmersymbols")]; char uniname2ctype_pool_str1413[sizeof("dep")]; char uniname2ctype_pool_str1416[sizeof("inkhmer")]; char uniname2ctype_pool_str1422[sizeof("deprecated")]; char uniname2ctype_pool_str1424[sizeof("rejang")]; char uniname2ctype_pool_str1429[sizeof("lyci")]; char uniname2ctype_pool_str1431[sizeof("intakri")]; char uniname2ctype_pool_str1432[sizeof("takr")]; char uniname2ctype_pool_str1435[sizeof("incyrillicsupplement")]; char uniname2ctype_pool_str1436[sizeof("changeswhencasefolded")]; char uniname2ctype_pool_str1438[sizeof("indevanagariextended")]; char uniname2ctype_pool_str1442[sizeof("lycian")]; char uniname2ctype_pool_str1443[sizeof("inbengali")]; char uniname2ctype_pool_str1448[sizeof("beng")]; char uniname2ctype_pool_str1450[sizeof("graph")]; char uniname2ctype_pool_str1452[sizeof("inyijinghexagramsymbols")]; char uniname2ctype_pool_str1457[sizeof("olck")]; char uniname2ctype_pool_str1460[sizeof("inarabicsupplement")]; char uniname2ctype_pool_str1462[sizeof("inbuginese")]; char uniname2ctype_pool_str1463[sizeof("changeswhencasemapped")]; char uniname2ctype_pool_str1468[sizeof("olchiki")]; char uniname2ctype_pool_str1478[sizeof("inaegeannumbers")]; char uniname2ctype_pool_str1479[sizeof("mlym")]; char uniname2ctype_pool_str1480[sizeof("alphabetic")]; char uniname2ctype_pool_str1492[sizeof("sylotinagri")]; char uniname2ctype_pool_str1498[sizeof("changeswhentitlecased")]; char uniname2ctype_pool_str1504[sizeof("tagalog")]; char uniname2ctype_pool_str1505[sizeof("tagb")]; char uniname2ctype_pool_str1506[sizeof("runr")]; char uniname2ctype_pool_str1510[sizeof("malayalam")]; char uniname2ctype_pool_str1512[sizeof("inoriya")]; char uniname2ctype_pool_str1516[sizeof("intagbanwa")]; char uniname2ctype_pool_str1517[sizeof("syrc")]; char uniname2ctype_pool_str1519[sizeof("nko")]; char uniname2ctype_pool_str1520[sizeof("nkoo")]; char uniname2ctype_pool_str1523[sizeof("inethiopicextended")]; char uniname2ctype_pool_str1525[sizeof("kaithi")]; char uniname2ctype_pool_str1530[sizeof("mathsymbol")]; char uniname2ctype_pool_str1531[sizeof("inyiradicals")]; char uniname2ctype_pool_str1536[sizeof("insupplementaryprivateuseareaa")]; char uniname2ctype_pool_str1540[sizeof("osmanya")]; char uniname2ctype_pool_str1546[sizeof("syriac")]; char uniname2ctype_pool_str1548[sizeof("otherdefaultignorablecodepoint")]; char uniname2ctype_pool_str1561[sizeof("number")]; char uniname2ctype_pool_str1565[sizeof("inlinearbsyllabary")]; char uniname2ctype_pool_str1566[sizeof("kthi")]; char uniname2ctype_pool_str1567[sizeof("sund")]; char uniname2ctype_pool_str1569[sizeof("mymr")]; char uniname2ctype_pool_str1571[sizeof("incombiningdiacriticalmarks")]; char uniname2ctype_pool_str1578[sizeof("enclosingmark")]; char uniname2ctype_pool_str1581[sizeof("incombiningdiacriticalmarksforsymbols")]; char uniname2ctype_pool_str1583[sizeof("inethiopicsupplement")]; char uniname2ctype_pool_str1590[sizeof("unassigned")]; char uniname2ctype_pool_str1591[sizeof("sylo")]; char uniname2ctype_pool_str1595[sizeof("combiningmark")]; char uniname2ctype_pool_str1598[sizeof("myanmar")]; char uniname2ctype_pool_str1605[sizeof("graphemeextend")]; char uniname2ctype_pool_str1606[sizeof("bidicontrol")]; char uniname2ctype_pool_str1609[sizeof("inhalfwidthandfullwidthforms")]; char uniname2ctype_pool_str1617[sizeof("cyrl")]; char uniname2ctype_pool_str1620[sizeof("knda")]; char uniname2ctype_pool_str1634[sizeof("inunifiedcanadianaboriginalsyllabicsextended")]; char uniname2ctype_pool_str1635[sizeof("xsux")]; char uniname2ctype_pool_str1636[sizeof("modifiersymbol")]; char uniname2ctype_pool_str1643[sizeof("incombiningdiacriticalmarkssupplement")]; char uniname2ctype_pool_str1645[sizeof("inhanunoo")]; char uniname2ctype_pool_str1648[sizeof("inbuhid")]; char uniname2ctype_pool_str1649[sizeof("kannada")]; char uniname2ctype_pool_str1658[sizeof("inhebrew")]; char uniname2ctype_pool_str1662[sizeof("grbase")]; char uniname2ctype_pool_str1664[sizeof("spacingmark")]; char uniname2ctype_pool_str1670[sizeof("inkatakanaphoneticextensions")]; char uniname2ctype_pool_str1676[sizeof("hangul")]; char uniname2ctype_pool_str1683[sizeof("incjksymbolsandpunctuation")]; char uniname2ctype_pool_str1688[sizeof("bopo")]; char uniname2ctype_pool_str1692[sizeof("orya")]; char uniname2ctype_pool_str1699[sizeof("inbopomofo")]; char uniname2ctype_pool_str1701[sizeof("kharoshthi")]; char uniname2ctype_pool_str1703[sizeof("khar")]; char uniname2ctype_pool_str1709[sizeof("changeswhenlowercased")]; char uniname2ctype_pool_str1724[sizeof("khmr")]; char uniname2ctype_pool_str1725[sizeof("punct")]; char uniname2ctype_pool_str1729[sizeof("symbol")]; char uniname2ctype_pool_str1732[sizeof("cherokee")]; char uniname2ctype_pool_str1737[sizeof("cyrillic")]; char uniname2ctype_pool_str1759[sizeof("inkangxiradicals")]; char uniname2ctype_pool_str1761[sizeof("hebrew")]; char uniname2ctype_pool_str1780[sizeof("inarabicpresentationformsb")]; char uniname2ctype_pool_str1787[sizeof("incyrillicextendedb")]; char uniname2ctype_pool_str1790[sizeof("ugaritic")]; char uniname2ctype_pool_str1829[sizeof("incurrencysymbols")]; char uniname2ctype_pool_str1831[sizeof("meroitichieroglyphs")]; char uniname2ctype_pool_str1835[sizeof("inhighsurrogates")]; char uniname2ctype_pool_str1853[sizeof("nonspacingmark")]; char uniname2ctype_pool_str1858[sizeof("lydi")]; char uniname2ctype_pool_str1864[sizeof("patsyn")]; char uniname2ctype_pool_str1868[sizeof("orkh")]; char uniname2ctype_pool_str1871[sizeof("lydian")]; char uniname2ctype_pool_str1896[sizeof("ugar")]; char uniname2ctype_pool_str1899[sizeof("othergraphemeextend")]; char uniname2ctype_pool_str1900[sizeof("inlatinextendedb")]; char uniname2ctype_pool_str1904[sizeof("bopomofo")]; char uniname2ctype_pool_str1917[sizeof("khmer")]; char uniname2ctype_pool_str1925[sizeof("uideo")]; char uniname2ctype_pool_str1932[sizeof("otheruppercase")]; char uniname2ctype_pool_str1944[sizeof("grek")]; char uniname2ctype_pool_str1949[sizeof("gujr")]; char uniname2ctype_pool_str1970[sizeof("gujarati")]; char uniname2ctype_pool_str1983[sizeof("inhanguljamoextendedb")]; char uniname2ctype_pool_str1988[sizeof("defaultignorablecodepoint")]; char uniname2ctype_pool_str2005[sizeof("inplayingcards")]; char uniname2ctype_pool_str2022[sizeof("bamu")]; char uniname2ctype_pool_str2028[sizeof("inkanbun")]; char uniname2ctype_pool_str2033[sizeof("incjkradicalssupplement")]; char uniname2ctype_pool_str2046[sizeof("cypriot")]; char uniname2ctype_pool_str2051[sizeof("inbamum")]; char uniname2ctype_pool_str2053[sizeof("inmeroiticcursive")]; char uniname2ctype_pool_str2055[sizeof("oldturkic")]; char uniname2ctype_pool_str2086[sizeof("insupplementalarrowsb")]; char uniname2ctype_pool_str2087[sizeof("surrogate")]; char uniname2ctype_pool_str2094[sizeof("batk")]; char uniname2ctype_pool_str2102[sizeof("inbatak")]; char uniname2ctype_pool_str2119[sizeof("inlimbu")]; char uniname2ctype_pool_str2123[sizeof("incypriotsyllabary")]; char uniname2ctype_pool_str2129[sizeof("dashpunctuation")]; char uniname2ctype_pool_str2130[sizeof("innoblock")]; char uniname2ctype_pool_str2141[sizeof("hyphen")]; char uniname2ctype_pool_str2162[sizeof("insupplementalpunctuation")]; char uniname2ctype_pool_str2165[sizeof("ingeorgiansupplement")]; char uniname2ctype_pool_str2178[sizeof("oupper")]; char uniname2ctype_pool_str2189[sizeof("paragraphseparator")]; char uniname2ctype_pool_str2194[sizeof("inbamumsupplement")]; char uniname2ctype_pool_str2299[sizeof("uppercase")]; char uniname2ctype_pool_str2313[sizeof("currencysymbol")]; char uniname2ctype_pool_str2322[sizeof("sk")]; char uniname2ctype_pool_str2338[sizeof("lu")]; char uniname2ctype_pool_str2342[sizeof("openpunctuation")]; char uniname2ctype_pool_str2349[sizeof("inlisu")]; char uniname2ctype_pool_str2371[sizeof("qmark")]; char uniname2ctype_pool_str2372[sizeof("egyp")]; char uniname2ctype_pool_str2377[sizeof("insupplementaryprivateuseareab")]; char uniname2ctype_pool_str2379[sizeof("limbu")]; char uniname2ctype_pool_str2400[sizeof("inegyptianhieroglyphs")]; char uniname2ctype_pool_str2401[sizeof("unifiedideograph")]; char uniname2ctype_pool_str2413[sizeof("intelugu")]; char uniname2ctype_pool_str2429[sizeof("katakana")]; char uniname2ctype_pool_str2442[sizeof("inhangulcompatibilityjamo")]; char uniname2ctype_pool_str2454[sizeof("upper")]; char uniname2ctype_pool_str2495[sizeof("inkayahli")]; char uniname2ctype_pool_str2515[sizeof("cwu")]; char uniname2ctype_pool_str2523[sizeof("incjkcompatibility")]; char uniname2ctype_pool_str2542[sizeof("uppercaseletter")]; char uniname2ctype_pool_str2549[sizeof("bugi")]; char uniname2ctype_pool_str2588[sizeof("buginese")]; char uniname2ctype_pool_str2627[sizeof("any")]; char uniname2ctype_pool_str2651[sizeof("inyisyllables")]; char uniname2ctype_pool_str2671[sizeof("inbopomofoextended")]; char uniname2ctype_pool_str2710[sizeof("inboxdrawing")]; char uniname2ctype_pool_str2724[sizeof("changeswhenuppercased")]; char uniname2ctype_pool_str2727[sizeof("unknown")]; char uniname2ctype_pool_str2737[sizeof("quotationmark")]; char uniname2ctype_pool_str2753[sizeof("buhd")]; char uniname2ctype_pool_str2785[sizeof("punctuation")]; char uniname2ctype_pool_str2888[sizeof("oldsoutharabian")]; char uniname2ctype_pool_str2925[sizeof("kayahli")]; char uniname2ctype_pool_str2940[sizeof("incjkunifiedideographs")]; char uniname2ctype_pool_str2961[sizeof("incjkunifiedideographsextensiona")]; char uniname2ctype_pool_str2962[sizeof("incjkunifiedideographsextensionc")]; char uniname2ctype_pool_str2995[sizeof("telugu")]; char uniname2ctype_pool_str3000[sizeof("guru")]; char uniname2ctype_pool_str3104[sizeof("greek")]; char uniname2ctype_pool_str3189[sizeof("grlink")]; char uniname2ctype_pool_str3197[sizeof("buhid")]; char uniname2ctype_pool_str3254[sizeof("batak")]; char uniname2ctype_pool_str3292[sizeof("blank")]; char uniname2ctype_pool_str3391[sizeof("incjkunifiedideographsextensiond")]; char uniname2ctype_pool_str3459[sizeof("graphemelink")]; char uniname2ctype_pool_str3480[sizeof("egyptianhieroglyphs")]; char uniname2ctype_pool_str3802[sizeof("incjkunifiedideographsextensionb")]; char uniname2ctype_pool_str3922[sizeof("zyyy")]; char uniname2ctype_pool_str4167[sizeof("gurmukhi")]; #endif /* USE_UNICODE_PROPERTIES */ }; static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = { #ifndef USE_UNICODE_PROPERTIES "word", "print", "punct", "alpha", "alnum", "xdigit", "upper", #else /* USE_UNICODE_PROPERTIES */ "n", "s", "z", "zs", "zzzz", "cn", "cs", "ci", "c", "cf", "sc", "cans", "qaai", "mn", #endif /* USE_UNICODE_PROPERTIES */ "ascii", #ifdef USE_UNICODE_PROPERTIES "cc", "qaac", "inavestan", "inspecials", "inipaextensions", "mc", "insamaritan", "m", "sm", "me", "inarmenian", "incuneiform", "mandaic", "inancientsymbols", "incuneiformnumbersandpunctuation", "inthai", "inmusicalsymbols", "inmiscellaneoussymbols", "incham", "inmiscellaneoussymbolsandarrows", "initialpunctuation", "inmiscellaneoussymbolsandpictographs", "inthaana", "taile", "mtei", "lc", "lana", "inlycian", "intransportandmapsymbols", "incontrolpictures", "sinhala", "incommonindicnumberforms", "inmiscellaneousmathematicalsymbolsa", "sterm", "inmyanmarextendeda", "lm", "taiviet", "inlinearbideograms", "intaitham", "latn", "latin", "ital", "alnum", "inmalayalam", "intaile", "tale", "l", "nl", "zl", "intamil", "taml", "inlatinextendeda", "inlatinextendedc", "inrunic", "incarian", "insyriac", "cari", "inmeeteimayekextensions", "osma", "lt", "miao", "insharada", "incyrillic", "carian", "armn", "samr", "armi", "inideographicdescriptioncharacters", "inosmanya", "armenian", "inmyanmar", "samaritan", "arabic", "incherokee", "connectorpunctuation", "merc", "inmiscellaneoustechnical", "inenclosedalphanumerics", "inemoticons", "joinc", #endif /* USE_UNICODE_PROPERTIES */ "cntrl", #ifdef USE_UNICODE_PROPERTIES "inenclosedcjklettersandmonths", "cwcf", "inruminumeralsymbols", "ll", "term", "inlatinextendedadditional", "tamil", "loe", "newtailue", "cwcm", "inenclosedalphanumericsupplement", "sinh", "zinh", "meroiticcursive", "han", "hani", "inopticalcharacterrecognition", "no", "so", "innewtailue", "insinhala", "innko", "co", "shavian", "terminalpunctuation", "intaixuanjingsymbols", "inethiopic", "sora", "inarrows", "cham", "inlowsurrogates", "oriya", "ext", "cwt", "common", "inmiao", "thai", "intifinagh", "ethi", "mero", "chakma", "thaa", "inscriptionalparthian", "tifinagh", "titlecaseletter", "thaana", "asciihexdigit", "math", "di", "ids", "lo", "inlao", "taitham", "lao", "laoo", "dia", "idc", "ps", "insundanese", "pi", "cwl", "pf", "mand", "insylotinagri", "vs", "mongolian", "pc", "inmandaic", "invai", "lineseparator", "pe", "vai", "vaii", "idst", "indominotiles", "inshavian", "inspacingmodifierletters", "format", "inphaistosdisc", "hano", #endif /* USE_UNICODE_PROPERTIES */ "space", #ifdef USE_UNICODE_PROPERTIES "indeseret", "inolchiki", "hira", "joincontrol", "idcontinue", "inmahjongtiles", "patws", "inlydian", "cher", "inhiragana", "inogham", "avst", "inscriptionalpahlavi", "incoptic", "java", "inmathematicalalphanumericsymbols", "letter", "injavanese", "avestan", "age=1.1", "lepc", "age=2.1", "inlepcha", "javanese", "shaw", "finalpunctuation", "alpha", "age=5.1", "inmongolian", "age=5.2", "age=2.0", "ahex", "ingeneralpunctuation", "oids", "odi", "age=5.0", "tavt", "intaiviet", "age=6.1", "age=3.1", "insundanesesupplement", "age=3.2", "age=4.1", "oidc", "tfng", "insmallformvariants", "ideo", "intags", "age=6.0", "age=3.0", "whitespace", "age=4.0", "inolditalic", "oalpha", "ingujarati", "control", "diacritic", "tagbanwa", "inphoenician", "ininscriptionalparthian", "ininscriptionalpahlavi", "coptic", "dsrt", "inmodifiertoneletters", "xids", "hanunoo", "inoldturkic", "xidc", "idstart", "inimperialaramaic", "invariationselectors", "copt", "caseignorable", "prti", "nchar", "deseret", "decimalnumber", "cprt", "inlatin1supplement", "imperialaramaic", "privateuse", "casedletter", "lowercase", "spaceseparator", "radical", "mong", "canadianaboriginal", "letternumber", "insorasompeng", "dash", "wspace", "ogam", "invariationselectorssupplement", "print", "otheridcontinue", "ingurmukhi", "closepunctuation", "olditalic", "noncharactercodepoint", "sharada", "ingeometricshapes", "otheralphabetic", "patternwhitespace", "po", "rjng", "ingreekandcoptic", "xdigit", "gothic", "inoldsoutharabian", "xidstart", "inrejang", "idsbinaryoperator", "olower", "hex", "inenclosedideographicsupplement", "inalphabeticpresentationforms", "inbasiclatin", "othersymbol", "nd", "sd", "omath", "separator", "inarabic", "xidcontinue", "otheridstart", "grext", "otherlowercase", "phli", "cased", "hang", "xpeo", #endif /* USE_UNICODE_PROPERTIES */ "lower", #ifndef USE_UNICODE_PROPERTIES "graph", #else /* USE_UNICODE_PROPERTIES */ "modifierletter", "inphoneticextensions", "inarabicpresentationformsa", "innumberforms", "oldpersian", "incyrillicextendeda", "inverticalforms", "p", "inbyzantinemusicalsymbols", "inmathematicaloperators", "intibetan", "zp", "ingeorgian", "inbraillepatterns", "lepcha", "geor", "invedicextensions", "linb", "other", "deva", "indevanagari", "othernumber", "bamum", "shrd", "bali", "devanagari", "extender", "inherited", "glagolitic", "tibt", "inbalinese", "ingothic", "inmiscellaneousmathematicalsymbolsb", "limb", "bengali", "phoenician", "insuperscriptsandsubscripts", "inmeroitichieroglyphs", "tibetan", "inphoneticextensionssupplement", "balinese", "lowercaseletter", "indingbats", "inprivateusearea", "assigned", "patternsyntax", "inhangulsyllables", "sarb", "brai", "insupplementalmathematicaloperators", "phnx", "ingreekextended", "otherletter", "arab", "inlatinextendedd", "word", "inphagspa", "inblockelements", "ethiopic", "inethiopicextendeda", "brahmi", "logicalorderexception", "inoldpersian", "inletterlikesymbols", "sorasompeng", "hiragana", "inhanguljamoextendeda", "othermath", #endif /* USE_UNICODE_PROPERTIES */ "digit", #ifndef USE_UNICODE_PROPERTIES "blank" #else /* USE_UNICODE_PROPERTIES */ "goth", "ogham", "sundanese", "saurashtra", "linearb", "graphemebase", "inunifiedcanadianaboriginalsyllabics", "cuneiform", "inkannada", "kana", "inancientgreeknumbers", "incjkstrokes", "inglagolitic", "inancientgreekmusicalnotation", "inchakma", "plrd", "inbrahmi", "cakm", "incjkcompatibilityforms", "lisu", "incjkcompatibilityideographs", "intagalog", "inkaithi", "insupplementalarrowsa", "takri", "ideographic", "hexdigit", "glag", "softdotted", "variationselector", "inkatakana", "meeteimayek", "otherpunctuation", "inhanguljamo", "kali", "braille", "incombininghalfmarks", "talu", "incjkcompatibilityideographssupplement", "telu", "idsb", "tglg", "inmeeteimayek", "yi", "phagspa", "yiii", "inarabicmathematicalalphabeticsymbols", "saur", "ogrext", "bidic", "inkanasupplement", "runic", "inalchemicalsymbols", "georgian", "inugaritic", "insaurashtra", "inhighprivateusesurrogates", "pd", "incountingrodnumerals", "inarabicextendeda", "inkharoshthi", "idstrinaryoperator", "phag", "brah", "mark", "hebr", "inkhmersymbols", "dep", "inkhmer", "deprecated", "rejang", "lyci", "intakri", "takr", "incyrillicsupplement", "changeswhencasefolded", "indevanagariextended", "lycian", "inbengali", "beng", "graph", "inyijinghexagramsymbols", "olck", "inarabicsupplement", "inbuginese", "changeswhencasemapped", "olchiki", "inaegeannumbers", "mlym", "alphabetic", "sylotinagri", "changeswhentitlecased", "tagalog", "tagb", "runr", "malayalam", "inoriya", "intagbanwa", "syrc", "nko", "nkoo", "inethiopicextended", "kaithi", "mathsymbol", "inyiradicals", "insupplementaryprivateuseareaa", "osmanya", "syriac", "otherdefaultignorablecodepoint", "number", "inlinearbsyllabary", "kthi", "sund", "mymr", "incombiningdiacriticalmarks", "enclosingmark", "incombiningdiacriticalmarksforsymbols", "inethiopicsupplement", "unassigned", "sylo", "combiningmark", "myanmar", "graphemeextend", "bidicontrol", "inhalfwidthandfullwidthforms", "cyrl", "knda", "inunifiedcanadianaboriginalsyllabicsextended", "xsux", "modifiersymbol", "incombiningdiacriticalmarkssupplement", "inhanunoo", "inbuhid", "kannada", "inhebrew", "grbase", "spacingmark", "inkatakanaphoneticextensions", "hangul", "incjksymbolsandpunctuation", "bopo", "orya", "inbopomofo", "kharoshthi", "khar", "changeswhenlowercased", "khmr", "punct", "symbol", "cherokee", "cyrillic", "inkangxiradicals", "hebrew", "inarabicpresentationformsb", "incyrillicextendedb", "ugaritic", "incurrencysymbols", "meroitichieroglyphs", "inhighsurrogates", "nonspacingmark", "lydi", "patsyn", "orkh", "lydian", "ugar", "othergraphemeextend", "inlatinextendedb", "bopomofo", "khmer", "uideo", "otheruppercase", "grek", "gujr", "gujarati", "inhanguljamoextendedb", "defaultignorablecodepoint", "inplayingcards", "bamu", "inkanbun", "incjkradicalssupplement", "cypriot", "inbamum", "inmeroiticcursive", "oldturkic", "insupplementalarrowsb", "surrogate", "batk", "inbatak", "inlimbu", "incypriotsyllabary", "dashpunctuation", "innoblock", "hyphen", "insupplementalpunctuation", "ingeorgiansupplement", "oupper", "paragraphseparator", "inbamumsupplement", "uppercase", "currencysymbol", "sk", "lu", "openpunctuation", "inlisu", "qmark", "egyp", "insupplementaryprivateuseareab", "limbu", "inegyptianhieroglyphs", "unifiedideograph", "intelugu", "katakana", "inhangulcompatibilityjamo", "upper", "inkayahli", "cwu", "incjkcompatibility", "uppercaseletter", "bugi", "buginese", "any", "inyisyllables", "inbopomofoextended", "inboxdrawing", "changeswhenuppercased", "unknown", "quotationmark", "buhd", "punctuation", "oldsoutharabian", "kayahli", "incjkunifiedideographs", "incjkunifiedideographsextensiona", "incjkunifiedideographsextensionc", "telugu", "guru", "greek", "grlink", "buhid", "batak", "blank", "incjkunifiedideographsextensiond", "graphemelink", "egyptianhieroglyphs", "incjkunifiedideographsextensionb", "zyyy", "gurmukhi" #endif /* USE_UNICODE_PROPERTIES */ }; #define uniname2ctype_pool ((const char *) &uniname2ctype_pool_contents) #ifdef __GNUC__ __inline #ifdef __GNUC_STDC_INLINE__ __attribute__ ((__gnu_inline__)) #endif #endif const struct uniname2ctype_struct * uniname2ctype_p (str, len) register const char *str; register unsigned int len; { static const struct uniname2ctype_struct wordlist[] = { #ifdef USE_UNICODE_PROPERTIES {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3, 34}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str5, 46}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str7, 51}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str9, 54}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str16, 208}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str18, 20}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str20, 22}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str24, 60}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str29, 17}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str30, 19}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str32, 47}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str34, 101}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str35, 114}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str38, 33}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str42, 14}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str44, 18}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str45, 128}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str49, 401}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str52, 377}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str62, 226}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str64, 31}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str66, 239}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str69, 30}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str72, 49}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str74, 32}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str82, 232}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str84, 412}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str86, 168}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str90, 382}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str92, 413}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str96, 252}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str99, 419}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str100, 304}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str106, 355}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str109, 312}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str113, 43}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str114, 430}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str116, 237}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str124, 120}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str125, 159}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str132, 24}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str133, 151}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str134, 384}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str135, 432}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str136, 298}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str142, 92}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str151, 347}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str156, 306}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str158, 204}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str167, 356}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str172, 26}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str175, 152}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str179, 379}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str180, 276}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str184, 75}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str186, 75}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str187, 111}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str189, 13}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str199, 250}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str201, 272}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str202, 120}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str205, 23}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str207, 36}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str209, 52}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str216, 247}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str217, 88}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str218, 224}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str220, 314}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str223, 263}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str224, 385}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str225, 235}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str227, 148}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str230, 358}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str231, 124}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str232, 28}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str233, 172}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str234, 410}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str239, 230}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str240, 148}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str244, 78}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str245, 155}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str247, 160}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str248, 323}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str252, 392}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str253, 78}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str254, 255}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str255, 155}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str256, 80}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str259, 260}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str261, 39}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str263, 170}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str264, 297}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str268, 300}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str279, 431}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str281, 178}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str288, 3}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str301, 333}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str303, 64}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str304, 405}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str308, 25}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str313, 182}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str316, 287}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str320, 88}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str321, 201}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str329, 129}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str330, 65}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str339, 428}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str346, 92}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str347, 114}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str349, 170}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str353, 109}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str357, 109}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str358, 299}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str359, 37}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str360, 50}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str364, 273}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str365, 251}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str367, 238}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str372, 21}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str375, 123}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str378, 182}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str386, 421}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str387, 258}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str389, 174}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str398, 295}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str400, 150}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str403, 365}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str405, 87}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str406, 189}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str409, 63}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str412, 74}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str414, 416}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str420, 93}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str425, 317}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str426, 99}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str427, 171}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str428, 169}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str429, 82}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str430, 162}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str432, 131}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str436, 28}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str445, 82}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str449, 185}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str450, 55}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str453, 70}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str454, 66}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str460, 27}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str468, 253}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str470, 151}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str474, 94}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str475, 94}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str476, 188}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str478, 67}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str480, 45}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str481, 278}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str484, 43}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str485, 61}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str490, 42}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str495, 168}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str496, 346}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str497, 205}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str503, 105}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str504, 39}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str506, 240}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str509, 341}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str511, 52}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str514, 41}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str515, 143}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str516, 143}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str517, 195}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str520, 426}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str521, 391}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str522, 227}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str524, 19}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str528, 383}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str531, 116}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str532, 9}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str542, 390}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str545, 281}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str548, 106}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str553, 178}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str555, 67}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str558, 425}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str560, 206}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str563, 396}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str564, 100}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str568, 325}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str572, 262}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str574, 153}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str575, 163}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str579, 315}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str587, 158}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str589, 423}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str594, 23}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str604, 354}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str608, 153}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str612, 209}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str613, 141}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str614, 211}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str616, 280}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str617, 158}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str618, 123}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str619, 42}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str620, 1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str621, 218}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str622, 269}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str623, 219}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str626, 210}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str627, 185}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str630, 289}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str631, 202}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str632, 198}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str633, 217}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str636, 152}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str637, 357}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str638, 221}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str639, 213}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str640, 282}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str641, 214}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str642, 216}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str643, 203}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str646, 131}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str647, 374}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str648, 187}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str649, 438}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str650, 220}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str651, 212}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str653, 176}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str654, 215}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str655, 386}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str660, 186}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str668, 245}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str672, 18}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str679, 188}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str682, 118}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str690, 395}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str701, 402}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str703, 403}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str704, 128}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str705, 113}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str706, 344}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str709, 68}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str713, 116}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str715, 404}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str721, 69}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str725, 66}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str729, 394}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str730, 370}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str734, 128}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str737, 60}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str738, 162}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str739, 192}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str746, 113}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str747, 35}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str748, 125}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str750, 223}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str771, 160}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str776, 21}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str777, 24}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str778, 57}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str780, 54}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str784, 196}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str787, 105}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str788, 101}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str792, 36}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str796, 408}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str797, 179}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str798, 176}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str799, 102}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str802, 439}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str803, 7}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str811, 203}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str815, 244}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str818, 41}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str823, 111}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str824, 192}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str826, 173}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str827, 303}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str830, 186}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str831, 206}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str832, 44}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str833, 146}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str835, 229}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str841, 11}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str850, 112}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str851, 400}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str852, 68}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str854, 352}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str860, 194}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str867, 190}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str869, 184}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str870, 429}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str874, 368}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str879, 222}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str884, 50}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str889, 35}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str890, 200}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str900, 183}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str901, 51}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str907, 234}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str912, 69}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str913, 202}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str914, 71}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str917, 190}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str919, 163}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str920, 59}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str923, 98}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str931, 133}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str933, 6}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str936, 26}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str938, 284}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str939, 369}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str943, 294}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str945, 133}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str946, 319}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str947, 371}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str949, 38}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str950, 418}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str951, 296}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str952, 254}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str953, 53}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str956, 256}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str960, 308}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str962, 141}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str963, 97}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str964, 283}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str965, 121}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str966, 17}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str970, 83}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str972, 242}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str973, 37}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str974, 157}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str976, 173}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str977, 135}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str981, 83}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str983, 189}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str988, 114}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str989, 130}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str990, 95}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str994, 277}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str996, 387}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str997, 310}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str998, 119}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1000, 84}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1003, 137}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1004, 290}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1006, 397}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1007, 95}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1010, 285}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1016, 135}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1021, 25}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1031, 305}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1035, 366}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1039, 16}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1044, 207}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1051, 361}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1065, 161}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1067, 126}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1069, 311}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1070, 137}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1072, 288}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1074, 27}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1076, 80}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1078, 345}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1081, 12}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1084, 348}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1087, 302}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1092, 99}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1094, 359}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1107, 167}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1110, 201}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1114, 389}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1129, 293}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1133, 174}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1135, 106}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1142, 353}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1147, 183}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1150, 4}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1151, 112}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1156, 102}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1162, 140}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1170, 144}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1173, 121}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1179, 72}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1185, 261}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1186, 136}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1188, 249}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1190, 107}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1195, 381}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1196, 331}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1198, 313}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1202, 420}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1212, 409}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1215, 172}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1219, 406}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1224, 169}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1225, 373}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1229, 156}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1230, 367}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1231, 264}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1244, 407}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1245, 307}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1249, 175}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1253, 187}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1256, 184}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1259, 130}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1261, 200}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1262, 205}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1264, 326}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1265, 159}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1274, 44}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1279, 257}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1282, 145}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1289, 126}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1298, 372}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1300, 129}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1302, 437}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1306, 89}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1307, 194}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1310, 115}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1313, 360}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1315, 110}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1318, 138}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1321, 110}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1323, 424}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1328, 144}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1330, 193}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1334, 177}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1341, 417}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1343, 103}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1344, 433}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1350, 97}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1351, 388}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1354, 349}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1356, 364}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1362, 40}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1372, 422}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1377, 241}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1389, 399}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1393, 195}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1396, 138}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1398, 167}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1402, 30}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1404, 79}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1411, 274}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1413, 199}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1416, 268}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1422, 199}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1424, 146}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1429, 147}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1431, 411}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1432, 175}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1435, 231}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1436, 64}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1438, 350}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1442, 147}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1443, 243}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1448, 84}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1450, 5}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1452, 336}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1457, 142}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1460, 236}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1462, 275}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1463, 65}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1468, 142}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1478, 380}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1479, 91}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1480, 56}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1492, 132}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1498, 63}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1504, 115}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1505, 118}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1506, 103}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1510, 91}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1512, 246}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1516, 267}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1517, 81}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1519, 139}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1520, 139}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1523, 318}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1525, 165}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1530, 49}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1531, 339}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1536, 440}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1540, 124}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1546, 81}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1548, 198}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1561, 34}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1565, 378}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1566, 165}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1567, 140}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1569, 96}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1571, 228}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1578, 32}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1581, 292}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1583, 259}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1590, 20}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1591, 132}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1595, 30}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1598, 96}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1605, 71}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1606, 177}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1609, 376}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1617, 77}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1620, 90}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1634, 270}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1635, 136}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1636, 48}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1643, 286}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1645, 265}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1648, 266}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1649, 90}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1658, 233}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1662, 72}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1664, 31}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1670, 332}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1676, 98}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1683, 324}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1688, 108}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1692, 87}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1699, 327}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1701, 134}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1703, 134}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1709, 61}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1724, 104}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1725, 8}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1729, 46}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1732, 100}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1737, 77}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1759, 322}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1761, 79}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1780, 375}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1787, 342}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1790, 122}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1829, 291}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1831, 171}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1835, 363}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1853, 33}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1858, 149}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1864, 207}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1868, 164}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1871, 149}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1896, 122}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1899, 193}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1900, 225}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1904, 108}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1917, 104}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1925, 197}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1932, 191}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1944, 76}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1949, 86}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1970, 86}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1983, 362}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str1988, 70}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2005, 427}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2022, 157}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2028, 329}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2033, 321}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2046, 125}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2051, 343}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2053, 398}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2055, 164}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2086, 309}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2087, 22}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2094, 166}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2102, 279}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2119, 271}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2123, 393}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2129, 40}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2130, 442}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2141, 180}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2162, 320}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2165, 316}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2178, 191}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2189, 53}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2194, 415}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2299, 58}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2313, 47}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2322, 48}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2338, 29}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2342, 45}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2349, 340}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2371, 181}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2372, 154}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2377, 441}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2379, 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2400, 414}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2401, 197}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2413, 248}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2429, 107}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2442, 328}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2454, 10}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2495, 351}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2515, 62}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2523, 334}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2542, 29}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2549, 127}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2588, 127}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2627, 15}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2651, 338}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2671, 330}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2710, 301}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2724, 62}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2727, 208}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2737, 181}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2753, 117}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2785, 38}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2888, 161}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2925, 145}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2940, 337}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2961, 335}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2962, 435}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str2995, 89}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3000, 85}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3104, 76}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3189, 73}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3197, 117}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3254, 166}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3292, 2}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3391, 436}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3459, 73}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3480, 154}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #endif /* USE_UNICODE_PROPERTIES */ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #ifndef USE_UNICODE_PROPERTIES {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str6, 12}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str7, 7}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str8, 8}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str9, 1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str10, 13}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str11, 11}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str12, 10}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str13, 14}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str14, 3}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str15, 9}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str16, 6}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str17, 5}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str18, 4}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str19, 2} #else /* USE_UNICODE_PROPERTIES */ {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3802, 434}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str3922, 74}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {(int)(long)&((struct uniname2ctype_pool_t *)0)->uniname2ctype_pool_str4167, 85} #endif /* USE_UNICODE_PROPERTIES */ }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = uniname2ctype_hash (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register int o = wordlist[key].name; if (o >= 0) { register const char *s = o + uniname2ctype_pool; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist[key]; } } } return 0; } static int uniname2ctype(const UChar *name, unsigned int len) { const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len); if (p) return p->ctype; return -1; } ================================================ FILE: src/Onigmo/enc/unicode.c ================================================ /********************************************************************** unicode.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regint.h" #define ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code,ctype) \ ((EncUNICODE_ISO_8859_1_CtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) #if 0 #define ONIGENC_IS_UNICODE_ISO_8859_1_BIT_CTYPE(code,cbit) \ ((EncUNICODE_ISO_8859_1_CtypeTable[code] & (cbit)) != 0) #endif static const unsigned short EncUNICODE_ISO_8859_1_CtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0288, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0284, 0x01a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x30e2, 0x01a0, 0x00a0, 0x00a8, 0x00a0, 0x00a0, 0x00a0, 0x00a0, 0x10a0, 0x10a0, 0x00a0, 0x30e2, 0x00a0, 0x01a0, 0x00a0, 0x10a0, 0x30e2, 0x01a0, 0x10a0, 0x10a0, 0x10a0, 0x01a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x00a0, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x34a2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x00a0, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2, 0x30e2 }; #include "enc/unicode/name2ctype.h" typedef struct { int n; OnigCodePoint code[3]; } CodePointList3; typedef struct { OnigCodePoint from; CodePointList3 to; } CaseFold_11_Type; typedef struct { OnigCodePoint from; CodePointList3 to; } CaseUnfold_11_Type; typedef struct { int n; OnigCodePoint code[2]; } CodePointList2; typedef struct { OnigCodePoint from[2]; CodePointList2 to; } CaseUnfold_12_Type; typedef struct { OnigCodePoint from[3]; CodePointList2 to; } CaseUnfold_13_Type; #include "enc/unicode/casefold.h" #define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) #define CODE_RANGES_NUM numberof(CodeRanges) #define CODE_SCRIPTS_NUM numberof(CodeScripts) extern int onigenc_unicode_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if ( #ifdef USE_UNICODE_PROPERTIES ctype <= ONIGENC_MAX_STD_CTYPE && #endif code < 256) { return ONIGENC_IS_UNICODE_ISO_8859_1_CTYPE(code, ctype); } if (ctype >= CODE_RANGES_NUM) { return ONIGERR_TYPE_BUG; } return onig_is_in_code_range((UChar* )CodeRanges[ctype], code); } extern int onigenc_unicode_ctype_code_range(int ctype, const OnigCodePoint* ranges[]) { if (ctype >= CODE_RANGES_NUM) { return ONIGERR_TYPE_BUG; } *ranges = CodeRanges[ctype]; return 0; } extern int onigenc_utf16_32_get_ctype_code_range(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[]) { *sb_out = 0x00; return onigenc_unicode_ctype_code_range(ctype, ranges); } extern const OnigCodePoint* onigenc_unicode_code_script(OnigCodePoint code) { for (int ctype = 0; ctype < CODE_SCRIPTS_NUM; ctype++) { if (onig_is_in_code_range((UChar*) CodeScripts[ctype], code)) { return CodeScripts[ctype]; } } return 0; } #include "st.h" #define PROPERTY_NAME_MAX_SIZE (MAX_WORD_LENGTH + 1) extern int onigenc_unicode_property_name_to_ctype(OnigEncoding enc, UChar* name, UChar* end) { int len; int ctype; UChar buf[PROPERTY_NAME_MAX_SIZE]; UChar *p; OnigCodePoint code; len = 0; for (p = name; p < end; p += enclen(enc, p)) { code = ONIGENC_MBC_TO_CODE(enc, p, end); if (code == ' ' || code == '-' || code == '_') continue; if (code >= 0x80) return ONIGERR_INVALID_CHAR_PROPERTY_NAME; buf[len++] = ONIGENC_ASCII_CODE_TO_LOWER_CASE(code); if (len >= PROPERTY_NAME_MAX_SIZE) return ONIGERR_INVALID_CHAR_PROPERTY_NAME; } buf[len] = 0; if ((ctype = uniname2ctype(buf, len)) < 0) { return ONIGERR_INVALID_CHAR_PROPERTY_NAME; } return ctype; } static int code2_cmp(OnigCodePoint* x, OnigCodePoint* y) { if (x[0] == y[0] && x[1] == y[1]) return 0; return 1; } static int code2_hash(OnigCodePoint* x) { return (int )(x[0] + x[1]); } static struct st_hash_type type_code2_hash = { code2_cmp, code2_hash, }; static int code3_cmp(OnigCodePoint* x, OnigCodePoint* y) { if (x[0] == y[0] && x[1] == y[1] && x[2] == y[2]) return 0; return 1; } static int code3_hash(OnigCodePoint* x) { return (int )(x[0] + x[1] + x[2]); } static struct st_hash_type type_code3_hash = { code3_cmp, code3_hash, }; #ifdef USE_SHARED_UNICODE_TABLE st_table* FoldTable; /* fold-1, fold-2, fold-3 */ st_table* Unfold1Table; st_table* Unfold2Table; st_table* Unfold3Table; int CaseFoldInited = 0; #else static st_table* FoldTable; /* fold-1, fold-2, fold-3 */ static st_table* Unfold1Table; static st_table* Unfold2Table; static st_table* Unfold3Table; static int CaseFoldInited = 0; #endif //USE_SHARED_UNICODE_TABLE static int init_case_fold_table(void) { const CaseFold_11_Type *p; const CaseUnfold_11_Type *p1; const CaseUnfold_12_Type *p2; const CaseUnfold_13_Type *p3; int i; THREAD_ATOMIC_START; FoldTable = st_init_numtable_with_size(FOLD_TABLE_SIZE); if (ONIG_IS_NULL(FoldTable)) return ONIGERR_MEMORY; for (i = 0; i < numberof(CaseFold); i++) { p = &CaseFold[i]; st_add_direct(FoldTable, (st_data_t )p->from, (st_data_t )&(p->to)); } for (i = 0; i < numberof(CaseFold_Locale); i++) { p = &CaseFold_Locale[i]; st_add_direct(FoldTable, (st_data_t )p->from, (st_data_t )&(p->to)); } Unfold1Table = st_init_numtable_with_size(UNFOLD1_TABLE_SIZE); if (ONIG_IS_NULL(Unfold1Table)) return ONIGERR_MEMORY; for (i = 0; i < numberof(CaseUnfold_11); i++) { p1 = &CaseUnfold_11[i]; st_add_direct(Unfold1Table, (st_data_t )p1->from, (st_data_t )&(p1->to)); } for (i = 0; i < numberof(CaseUnfold_11_Locale); i++) { p1 = &CaseUnfold_11_Locale[i]; st_add_direct(Unfold1Table, (st_data_t )p1->from, (st_data_t )&(p1->to)); } Unfold2Table = st_init_table_with_size(&type_code2_hash, UNFOLD2_TABLE_SIZE); if (ONIG_IS_NULL(Unfold2Table)) return ONIGERR_MEMORY; for (i = 0; i < numberof(CaseUnfold_12); i++) { p2 = &CaseUnfold_12[i]; st_add_direct(Unfold2Table, (st_data_t )p2->from, (st_data_t )(&p2->to)); } for (i = 0; i < numberof(CaseUnfold_12_Locale); i++) { p2 = &CaseUnfold_12_Locale[i]; st_add_direct(Unfold2Table, (st_data_t )p2->from, (st_data_t )(&p2->to)); } Unfold3Table = st_init_table_with_size(&type_code3_hash, UNFOLD3_TABLE_SIZE); if (ONIG_IS_NULL(Unfold3Table)) return ONIGERR_MEMORY; for (i = 0; i < numberof(CaseUnfold_13); i++) { p3 = &CaseUnfold_13[i]; st_add_direct(Unfold3Table, (st_data_t )p3->from, (st_data_t )(&p3->to)); } CaseFoldInited = 1; THREAD_ATOMIC_END; return 0; } extern int onigenc_unicode_mbc_case_fold(OnigEncoding enc, OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end, UChar* fold) { CodePointList3 *to; OnigCodePoint code; int i, len, rlen; const UChar *p = *pp; if (CaseFoldInited == 0) init_case_fold_table(); code = ONIGENC_MBC_TO_CODE(enc, p, end); len = enclen(enc, p); *pp += len; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (code == 0x0049) { return ONIGENC_CODE_TO_MBC(enc, 0x0131, fold); } else if (code == 0x0130) { return ONIGENC_CODE_TO_MBC(enc, 0x0069, fold); } } #endif if (onig_st_lookup(FoldTable, (st_data_t )code, (void* )&to) != 0) { if (to->n == 1) { return ONIGENC_CODE_TO_MBC(enc, to->code[0], fold); } #if 0 /* NO NEEDS TO CHECK */ else if ((flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { #else else { #endif rlen = 0; for (i = 0; i < to->n; i++) { len = ONIGENC_CODE_TO_MBC(enc, to->code[i], fold); fold += len; rlen += len; } return rlen; } } for (i = 0; i < len; i++) { *fold++ = *p++; } return len; } extern int onigenc_unicode_mbc_case_fold_se(OnigIterator* it, OnigEncoding enc, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end, UChar* fold) { CodePointList3 *to; OnigCodePoint code; int i, len, rlen; OnigPosition p = *pp; if (CaseFoldInited == 0) init_case_fold_table(); code = ONIGENC_MBC_TO_CODE_SE(it, enc, p, end); len = enclen_se(it, enc, p); *pp += len; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (code == 0x0049) { return ONIGENC_CODE_TO_MBC(enc, 0x0131, fold); } else if (code == 0x0130) { return ONIGENC_CODE_TO_MBC(enc, 0x0069, fold); } } #endif if (onig_st_lookup(FoldTable, (st_data_t )code, (void* )&to) != 0) { if (to->n == 1) { return ONIGENC_CODE_TO_MBC(enc, to->code[0], fold); } #if 0 /* NO NEEDS TO CHECK */ else if ((flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { #else else { #endif rlen = 0; for (i = 0; i < to->n; i++) { len = ONIGENC_CODE_TO_MBC(enc, to->code[i], fold); fold += len; rlen += len; } return rlen; } } for (i = 0; i < len; i++) { *fold++ = ONIG_CHARAT(p++); } return len; } extern int onigenc_unicode_apply_all_case_fold(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { const CaseUnfold_11_Type* p11; OnigCodePoint code; int i, j, k, r; /* if (CaseFoldInited == 0) init_case_fold_table(); */ for (i = 0; i < numberof(CaseUnfold_11); i++) { p11 = &CaseUnfold_11[i]; for (j = 0; j < p11->to.n; j++) { code = p11->from; r = (*f)(p11->to.code[j], &code, 1, arg); if (r != 0) return r; code = p11->to.code[j]; r = (*f)(p11->from, &code, 1, arg); if (r != 0) return r; for (k = 0; k < j; k++) { r = (*f)(p11->to.code[j], (OnigCodePoint* )(&p11->to.code[k]), 1, arg); if (r != 0) return r; r = (*f)(p11->to.code[k], (OnigCodePoint* )(&p11->to.code[j]), 1, arg); if (r != 0) return r; } } } #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { code = 0x0131; r = (*f)(0x0049, &code, 1, arg); if (r != 0) return r; code = 0x0049; r = (*f)(0x0131, &code, 1, arg); if (r != 0) return r; code = 0x0130; r = (*f)(0x0069, &code, 1, arg); if (r != 0) return r; code = 0x0069; r = (*f)(0x0130, &code, 1, arg); if (r != 0) return r; } else { #endif for (i = 0; i < numberof(CaseUnfold_11_Locale); i++) { p11 = &CaseUnfold_11_Locale[i]; for (j = 0; j < p11->to.n; j++) { code = p11->from; r = (*f)(p11->to.code[j], &code, 1, arg); if (r != 0) return r; code = p11->to.code[j]; r = (*f)(p11->from, &code, 1, arg); if (r != 0) return r; for (k = 0; k < j; k++) { r = (*f)(p11->to.code[j], (OnigCodePoint* )(&p11->to.code[k]), 1, arg); if (r != 0) return r; r = (*f)(p11->to.code[k], (OnigCodePoint* )(&p11->to.code[j]), 1, arg); if (r != 0) return r; } } } #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI } #endif if ((flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { for (i = 0; i < numberof(CaseUnfold_12); i++) { for (j = 0; j < CaseUnfold_12[i].to.n; j++) { r = (*f)(CaseUnfold_12[i].to.code[j], (OnigCodePoint* )CaseUnfold_12[i].from, 2, arg); if (r != 0) return r; for (k = 0; k < CaseUnfold_12[i].to.n; k++) { if (k == j) continue; r = (*f)(CaseUnfold_12[i].to.code[j], (OnigCodePoint* )(&CaseUnfold_12[i].to.code[k]), 1, arg); if (r != 0) return r; } } } #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) == 0) { #endif for (i = 0; i < numberof(CaseUnfold_12_Locale); i++) { for (j = 0; j < CaseUnfold_12_Locale[i].to.n; j++) { r = (*f)(CaseUnfold_12_Locale[i].to.code[j], (OnigCodePoint* )CaseUnfold_12_Locale[i].from, 2, arg); if (r != 0) return r; for (k = 0; k < CaseUnfold_12_Locale[i].to.n; k++) { if (k == j) continue; r = (*f)(CaseUnfold_12_Locale[i].to.code[j], (OnigCodePoint* )(&CaseUnfold_12_Locale[i].to.code[k]), 1, arg); if (r != 0) return r; } } } #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI } #endif for (i = 0; i < numberof(CaseUnfold_13); i++) { for (j = 0; j < CaseUnfold_13[i].to.n; j++) { r = (*f)(CaseUnfold_13[i].to.code[j], (OnigCodePoint* )CaseUnfold_13[i].from, 3, arg); if (r != 0) return r; for (k = 0; k < CaseUnfold_13[i].to.n; k++) { if (k == j) continue; r = (*f)(CaseUnfold_13[i].to.code[j], (OnigCodePoint* )(&CaseUnfold_13[i].to.code[k]), 1, arg); if (r != 0) return r; } } } } return 0; } extern int onigenc_unicode_get_case_fold_codes_by_str(OnigEncoding enc, OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { int n, i, j, k, len; OnigCodePoint code, codes[3]; CodePointList3 *to, *z3; CodePointList2 *z2; if (CaseFoldInited == 0) init_case_fold_table(); n = 0; code = ONIGENC_MBC_TO_CODE(enc, p, end); len = enclen(enc, p); #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (code == 0x0049) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = 0x0131; return 1; } else if (code == 0x0130) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = 0x0069; return 1; } else if (code == 0x0131) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = 0x0049; return 1; } else if (code == 0x0069) { items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = 0x0130; return 1; } } #endif if (onig_st_lookup(FoldTable, (st_data_t )code, (void* )&to) != 0) { if (to->n == 1) { OnigCodePoint orig_code = code; items[0].byte_len = len; items[0].code_len = 1; items[0].code[0] = to->code[0]; n++; code = to->code[0]; if (onig_st_lookup(Unfold1Table, (st_data_t )code, (void* )&to) != 0) { for (i = 0; i < to->n; i++) { if (to->code[i] != orig_code) { items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = to->code[i]; n++; } } } } else if ((flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { OnigCodePoint cs[3][4]; int fn, ncs[3]; for (fn = 0; fn < to->n; fn++) { cs[fn][0] = to->code[fn]; if (onig_st_lookup(Unfold1Table, (st_data_t )cs[fn][0], (void* )&z3) != 0) { for (i = 0; i < z3->n; i++) { cs[fn][i+1] = z3->code[i]; } ncs[fn] = z3->n + 1; } else ncs[fn] = 1; } if (fn == 2) { for (i = 0; i < ncs[0]; i++) { for (j = 0; j < ncs[1]; j++) { items[n].byte_len = len; items[n].code_len = 2; items[n].code[0] = cs[0][i]; items[n].code[1] = cs[1][j]; n++; } } if (onig_st_lookup(Unfold2Table, (st_data_t )to->code, (void* )&z2) != 0) { for (i = 0; i < z2->n; i++) { if (z2->code[i] == code) continue; items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = z2->code[i]; n++; } } } else { for (i = 0; i < ncs[0]; i++) { for (j = 0; j < ncs[1]; j++) { for (k = 0; k < ncs[2]; k++) { items[n].byte_len = len; items[n].code_len = 3; items[n].code[0] = cs[0][i]; items[n].code[1] = cs[1][j]; items[n].code[2] = cs[2][k]; n++; } } } if (onig_st_lookup(Unfold3Table, (st_data_t )to->code, (void* )&z2) != 0) { for (i = 0; i < z2->n; i++) { if (z2->code[i] == code) continue; items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = z2->code[i]; n++; } } } /* multi char folded code is not head of another folded multi char */ flag = 0; /* DISABLE_CASE_FOLD_MULTI_CHAR(flag); */ } } else { if (onig_st_lookup(Unfold1Table, (st_data_t )code, (void* )&to) != 0) { for (i = 0; i < to->n; i++) { items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = to->code[i]; n++; } } } if ((flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { p += len; if (p < end) { int clen; codes[0] = code; code = ONIGENC_MBC_TO_CODE(enc, p, end); if (onig_st_lookup(FoldTable, (st_data_t )code, (void* )&to) != 0 && to->n == 1) { codes[1] = to->code[0]; } else codes[1] = code; clen = enclen(enc, p); len += clen; if (onig_st_lookup(Unfold2Table, (st_data_t )codes, (void* )&z2) != 0) { for (i = 0; i < z2->n; i++) { items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = z2->code[i]; n++; } } p += clen; if (p < end) { code = ONIGENC_MBC_TO_CODE(enc, p, end); if (onig_st_lookup(FoldTable, (st_data_t )code, (void* )&to) != 0 && to->n == 1) { codes[2] = to->code[0]; } else codes[2] = code; clen = enclen(enc, p); len += clen; if (onig_st_lookup(Unfold3Table, (st_data_t )codes, (void* )&z2) != 0) { for (i = 0; i < z2->n; i++) { items[n].byte_len = len; items[n].code_len = 1; items[n].code[0] = z2->code[i]; n++; } } } } } return n; } ================================================ FILE: src/Onigmo/enc/utf16_be.c ================================================ /********************************************************************** utf16_be.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regenc.h" static const int EncLen_UTF16[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static int utf16be_mbc_enc_len(const UChar* p) { return EncLen_UTF16[*p]; } static int utf16be_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_UTF16[ONIG_CHARAT(p)]; } static int utf16be_is_mbc_newline(const UChar* p, const UChar* end) { if (p + 1 < end) { if (*(p+1) == 0x0a && *p == 0x00) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((*(p+1) == 0x0b || *(p+1) == 0x0c || *(p+1) == 0x0d || *(p+1) == 0x85) && *p == 0x00) return 1; if (*p == 0x20 && (*(p+1) == 0x29 || *(p+1) == 0x28)) return 1; #endif } return 0; } static int utf16be_is_mbc_newline_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p + 1 < end) { const UChar c0 = ONIG_CHARAT(p); const UChar c1 = ONIG_CHARAT(p+1); if (c1 == 0x0a && c0 == 0x00) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((c1 == 0x0b || c1 == 0x0c || c1 == 0x0d || c1 == 0x85) && c0 == 0x00) return 1; if (c0 == 0x20 && (c1 == 0x29 || c1 == 0x28)) return 1; #endif } return 0; } static OnigCodePoint utf16be_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { OnigCodePoint code; if (UTF16_IS_SURROGATE_FIRST(*p)) { code = ((((p[0] - 0xd8) << 2) + ((p[1] & 0xc0) >> 6) + 1) << 16) + ((((p[1] & 0x3f) << 2) + (p[2] - 0xdc)) << 8) + p[3]; } else { code = p[0] * 256 + p[1]; } return code; } static OnigCodePoint utf16be_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { OnigCodePoint code; const UChar c0 = ONIG_CHARAT(p); const UChar c1 = ONIG_CHARAT(p+1); if (UTF16_IS_SURROGATE_FIRST(c0)) { code = ((((c0 - 0xd8) << 2) + ((c1 & 0xc0) >> 6) + 1) << 16) + ((((c1 & 0x3f) << 2) + (ONIG_CHARAT(p+2) - 0xdc)) << 8) + ONIG_CHARAT(p+3); } else { code = c0 * 256 + c1; } return code; } static int utf16be_code_to_mbclen(OnigCodePoint code) { return (code > 0xffff ? 4 : 2); } static int utf16be_code_to_mbc(OnigCodePoint code, UChar *buf) { UChar* p = buf; if (code > 0xffff) { unsigned int plane, high; plane = (code >> 16) - 1; *p++ = (plane >> 2) + 0xd8; high = (code & 0xff00) >> 8; *p++ = ((plane & 0x03) << 6) + (high >> 2); *p++ = (high & 0x03) + 0xdc; *p = (UChar )(code & 0xff); return 4; } else { *p++ = (UChar )((code & 0xff00) >> 8); *p++ = (UChar )(code & 0xff); return 2; } } static int utf16be_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold) { const UChar* p = *pp; if (ONIGENC_IS_ASCII_CODE(*(p+1)) && *p == 0) { p++; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (*p == 0x49) { *fold++ = 0x01; *fold = 0x31; (*pp) += 2; return 2; } } #endif *fold++ = 0; *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); *pp += 2; return 2; } else return onigenc_unicode_mbc_case_fold(ONIG_ENCODING_UTF16_BE, flag, pp, end, fold); } static int utf16be_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold) { const UChar c0 = ONIG_CHARAT(*pp); const UChar c1 = ONIG_CHARAT(*pp+1); if (ONIGENC_IS_ASCII_CODE(c1) && c0 == 0) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (c1 == 0x49) { *fold++ = 0x01; *fold = 0x31; (*pp) += 2; return 2; } } #endif *fold++ = 0; *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c1); *pp += 2; return 2; } else return onigenc_unicode_mbc_case_fold_se(it, ONIG_ENCODING_UTF16_BE, flag, pp, end, fold); } #if 0 static int utf16be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; (*pp) += EncLen_UTF16[*p]; if (*p == 0) { int c, v; p++; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { return TRUE; } c = *p; v = ONIGENC_IS_UNICODE_ISO_8859_1_BIT_CTYPE(c, (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (c >= 0xaa && c <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } return FALSE; } #endif static UChar* utf16be_left_adjust_char_head(const UChar* start, const UChar* s) { if (s <= start) return (UChar* )s; if ((s - start) % 2 == 1) { s--; } if (UTF16_IS_SURROGATE_SECOND(*s) && s > start + 1) s -= 2; return (UChar* )s; } static OnigPosition utf16be_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { if (s <= start) return s; if ((s - start) % 2 == 1) { s--; } if (UTF16_IS_SURROGATE_SECOND(ONIG_CHARAT(s)) && s > start + 1) s -= 2; return s; } static int utf16be_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_unicode_get_case_fold_codes_by_str(ONIG_ENCODING_UTF16_BE, flag, p, end, items); } OnigEncodingType OnigEncodingUTF16_BE = { utf16be_mbc_enc_len, utf16be_mbc_enc_len_se, "UTF-16BE", /* name */ 4, /* max byte length */ 2, /* min byte length */ utf16be_is_mbc_newline, utf16be_is_mbc_newline_se, utf16be_mbc_to_code, utf16be_mbc_to_code_se, utf16be_code_to_mbclen, utf16be_code_to_mbc, utf16be_mbc_case_fold, utf16be_mbc_case_fold_se, onigenc_unicode_apply_all_case_fold, utf16be_get_case_fold_codes_by_str, onigenc_unicode_property_name_to_ctype, onigenc_unicode_is_code_ctype, onigenc_utf16_32_get_ctype_code_range, utf16be_left_adjust_char_head, utf16be_left_adjust_char_head_se, onigenc_always_false_is_allowed_reverse_match, ONIGENC_FLAG_UNICODE, }; ================================================ FILE: src/Onigmo/enc/utf16_le.c ================================================ /********************************************************************** utf16_le.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * 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. */ #include "regenc.h" static const int EncLen_UTF16[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static int utf16le_code_to_mbclen(OnigCodePoint code) { return (code > 0xffff ? 4 : 2); } static int utf16le_mbc_enc_len(const UChar* p) { return EncLen_UTF16[*(p+1)]; } static int utf16le_mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_UTF16[ONIG_CHARAT(p+1)]; } static int utf16le_is_mbc_newline(const UChar* p, const UChar* end) { if (p + 1 < end) { if (*p == 0x0a && *(p+1) == 0x00) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((*p == 0x0b || *p == 0x0c || *p == 0x0d || *p == 0x85) && *(p+1) == 0x00) return 1; if (*(p+1) == 0x20 && (*p == 0x29 || *p == 0x28)) return 1; #endif } return 0; } static int utf16le_is_mbc_newline_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p + 1 < end) { const UChar c0 = ONIG_CHARAT(p); const UChar c1 = ONIG_CHARAT(p+1); if (c0 == 0x0a && c1 == 0x00) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((c0 == 0x0b || c0 == 0x0c || c0 == 0x0d || c0 == 0x85) && c1 == 0x00) return 1; if (c1 == 0x20 && (c0 == 0x29 || c0 == 0x28)) return 1; #endif } return 0; } static OnigCodePoint utf16le_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { OnigCodePoint code; UChar c0 = *p; UChar c1 = *(p+1); if (UTF16_IS_SURROGATE_FIRST(c1)) { code = ((((c1 - 0xd8) << 2) + ((c0 & 0xc0) >> 6) + 1) << 16) + ((((c0 & 0x3f) << 2) + (p[3] - 0xdc)) << 8) + p[2]; } else { code = c1 * 256 + p[0]; } return code; } static OnigCodePoint utf16le_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { OnigCodePoint code; const UChar c0 = ONIG_CHARAT(p); const UChar c1 = ONIG_CHARAT(p+1); if (UTF16_IS_SURROGATE_FIRST(c1)) { code = ((((c1 - 0xd8) << 2) + ((c0 & 0xc0) >> 6) + 1) << 16) + ((((c0 & 0x3f) << 2) + (ONIG_CHARAT(p+3) - 0xdc)) << 8) + ONIG_CHARAT(p+2); } else { code = c1 * 256 + c0; } return code; } static int utf16le_code_to_mbc(OnigCodePoint code, UChar *buf) { UChar* p = buf; if (code > 0xffff) { unsigned int plane, high; plane = (code >> 16) - 1; high = (code & 0xff00) >> 8; *p++ = ((plane & 0x03) << 6) + (high >> 2); *p++ = (plane >> 2) + 0xd8; *p++ = (UChar )(code & 0xff); *p = (high & 0x03) + 0xdc; return 4; } else { *p++ = (UChar )(code & 0xff); *p++ = (UChar )((code & 0xff00) >> 8); return 2; } } static int utf16le_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold) { const UChar* p = *pp; if (ONIGENC_IS_ASCII_CODE(*p) && *(p+1) == 0) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (*p == 0x49) { *fold++ = 0x31; *fold = 0x01; (*pp) += 2; return 2; } } #endif *fold++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); *fold = 0; *pp += 2; return 2; } else return onigenc_unicode_mbc_case_fold(ONIG_ENCODING_UTF16_LE, flag, pp, end, fold); } static int utf16le_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold) { const UChar c = ONIG_CHARAT(*pp); if (ONIGENC_IS_ASCII_CODE(c) && ONIG_CHARAT(*pp+1) == 0) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (c == 0x49) { *fold++ = 0x31; *fold = 0x01; (*pp) += 2; return 2; } } #endif *fold++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); *fold = 0; *pp += 2; return 2; } else return onigenc_unicode_mbc_case_fold_se(it, ONIG_ENCODING_UTF16_LE, flag, pp, end, fold); } #if 0 static int utf16le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; (*pp) += EncLen_UTF16[*(p+1)]; if (*(p+1) == 0) { int c, v; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { return TRUE; } c = *p; v = ONIGENC_IS_UNICODE_ISO_8859_1_BIT_CTYPE(c, (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (c >= 0xaa && c <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } return FALSE; } #endif static UChar* utf16le_left_adjust_char_head(const UChar* start, const UChar* s) { if (s <= start) return (UChar* )s; if ((s - start) % 2 == 1) { s--; } if (UTF16_IS_SURROGATE_SECOND(*(s+1)) && s > start + 1) s -= 2; return (UChar* )s; } static OnigPosition utf16le_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { if (s <= start) return s; if ((s - start) % 2 == 1) { s--; } if (UTF16_IS_SURROGATE_SECOND(ONIG_CHARAT(s+1)) && s > start + 1) s -= 2; return s; } static int utf16le_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_unicode_get_case_fold_codes_by_str(ONIG_ENCODING_UTF16_LE, flag, p, end, items); } OnigEncodingType OnigEncodingUTF16_LE = { utf16le_mbc_enc_len, utf16le_mbc_enc_len_se, "UTF-16LE", /* name */ 4, /* max byte length */ 2, /* min byte length */ utf16le_is_mbc_newline, utf16le_is_mbc_newline_se, utf16le_mbc_to_code, utf16le_mbc_to_code_se, utf16le_code_to_mbclen, utf16le_code_to_mbc, utf16le_mbc_case_fold, utf16le_mbc_case_fold_se, onigenc_unicode_apply_all_case_fold, utf16le_get_case_fold_codes_by_str, onigenc_unicode_property_name_to_ctype, onigenc_unicode_is_code_ctype, onigenc_utf16_32_get_ctype_code_range, utf16le_left_adjust_char_head, utf16le_left_adjust_char_head_se, onigenc_always_false_is_allowed_reverse_match, ONIGENC_FLAG_UNICODE, }; ================================================ FILE: src/Onigmo/enc/utf32_be.c ================================================ /********************************************************************** utf32_be.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" static int utf32be_mbc_enc_len(const UChar* p ARG_UNUSED) { return 4; } static int utf32be_mbc_enc_len_se(OnigIterator* it ARG_UNUSED, OnigPosition p ARG_UNUSED) { return 4; } static int utf32be_is_mbc_newline(const UChar* p, const UChar* end) { if (p + 3 < end) { if (*(p+3) == 0x0a && *(p+2) == 0 && *(p+1) == 0 && *p == 0) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((*(p+3) == 0x0b || *(p+3) == 0x0c || *(p+3) == 0x0d || *(p+3) == 0x85) && *(p+2) == 0 && *(p+1) == 0 && *p == 0x00) return 1; if (*(p+2) == 0x20 && (*(p+3) == 0x29 || *(p+3) == 0x28) && *(p+1) == 0 && *p == 0) return 1; #endif } return 0; } static int utf32be_is_mbc_newline_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p + 3 < end) { const UChar c2 = ONIG_CHARAT(p+2); const UChar c3 = ONIG_CHARAT(p+3); if (c3 == 0x0a && c2 == 0 && ONIG_CHARAT(p+1) == 0 && ONIG_CHARAT(p) == 0) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((c3 == 0x0b || c3 == 0x0c || c3 == 0x0d || c3 == 0x85) && c2 == 0 && ONIG_CHARAT(p+1) == 0 && ONIG_CHARAT(p) == 0x00) return 1; if (c2 == 0x20 && (c3 == 0x29 || c3 == 0x28) && ONIG_CHARAT(p+1) == 0 && ONIG_CHARAT(p) == 0) return 1; #endif } return 0; } static OnigCodePoint utf32be_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { return (OnigCodePoint )(((p[0] * 256 + p[1]) * 256 + p[2]) * 256 + p[3]); } static OnigCodePoint utf32be_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { return (OnigCodePoint )(((ONIG_CHARAT(p) * 256 + ONIG_CHARAT(p+1)) * 256 + ONIG_CHARAT(p+2)) * 256 + ONIG_CHARAT(p+3)); } static int utf32be_code_to_mbclen(OnigCodePoint code ARG_UNUSED) { return 4; } static int utf32be_code_to_mbc(OnigCodePoint code, UChar *buf) { UChar* p = buf; *p++ = (UChar )((code & 0xff000000) >>24); *p++ = (UChar )((code & 0xff0000) >>16); *p++ = (UChar )((code & 0xff00) >> 8); *p++ = (UChar ) (code & 0xff); return 4; } static int utf32be_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold) { const UChar* p = *pp; if (ONIGENC_IS_ASCII_CODE(*(p+3)) && *(p+2) == 0 && *(p+1) == 0 && *p == 0) { *fold++ = 0; *fold++ = 0; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (*(p+3) == 0x49) { *fold++ = 0x01; *fold = 0x31; (*pp) += 4; return 4; } } #endif *fold++ = 0; *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*(p+3)); *pp += 4; return 4; } else return onigenc_unicode_mbc_case_fold(ONIG_ENCODING_UTF32_BE, flag, pp, end, fold); } static int utf32be_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold) { OnigPosition p = *pp; const UChar c3 = ONIG_CHARAT(p+3); if (ONIGENC_IS_ASCII_CODE(c3) && ONIG_CHARAT(p+2) == 0 && ONIG_CHARAT(p+1) == 0 && ONIG_CHARAT(p) == 0) { *fold++ = 0; *fold++ = 0; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (c3 == 0x49) { *fold++ = 0x01; *fold = 0x31; (*pp) += 4; return 4; } } #endif *fold++ = 0; *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c3); *pp += 4; return 4; } else return onigenc_unicode_mbc_case_fold_se(it, ONIG_ENCODING_UTF32_BE, flag, pp, end, fold); } #if 0 static int utf32be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; (*pp) += 4; if (*(p+2) == 0 && *(p+1) == 0 && *p == 0) { int c, v; p += 3; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { return TRUE; } c = *p; v = ONIGENC_IS_UNICODE_ISO_8859_1_BIT_CTYPE(c, (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (c >= 0xaa && c <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } return FALSE; } #endif static UChar* utf32be_left_adjust_char_head(const UChar* start, const UChar* s) { int rem; if (s <= start) return (UChar* )s; rem = (int )((s - start) % 4); return (UChar* )(s - rem); } static OnigPosition utf32be_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { int rem; if (s <= start) return s; rem = (int )((s - start) % 4); return (s - rem); } static int utf32be_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_unicode_get_case_fold_codes_by_str(ONIG_ENCODING_UTF32_BE, flag, p, end, items); } OnigEncodingType OnigEncodingUTF32_BE = { utf32be_mbc_enc_len, utf32be_mbc_enc_len_se, "UTF-32BE", /* name */ 4, /* max byte length */ 4, /* min byte length */ utf32be_is_mbc_newline, utf32be_is_mbc_newline_se, utf32be_mbc_to_code, utf32be_mbc_to_code_se, utf32be_code_to_mbclen, utf32be_code_to_mbc, utf32be_mbc_case_fold, utf32be_mbc_case_fold_se, onigenc_unicode_apply_all_case_fold, utf32be_get_case_fold_codes_by_str, onigenc_unicode_property_name_to_ctype, onigenc_unicode_is_code_ctype, onigenc_utf16_32_get_ctype_code_range, utf32be_left_adjust_char_head, utf32be_left_adjust_char_head_se, onigenc_always_false_is_allowed_reverse_match, ONIGENC_FLAG_UNICODE, }; ================================================ FILE: src/Onigmo/enc/utf32_le.c ================================================ /********************************************************************** utf32_le.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" static int utf32le_mbc_enc_len(const UChar* p ARG_UNUSED) { return 4; } static int utf32le_mbc_enc_len_se(OnigIterator* it ARG_UNUSED, OnigPosition p ARG_UNUSED) { return 4; } static int utf32le_is_mbc_newline(const UChar* p, const UChar* end) { if (p + 3 < end) { if (*p == 0x0a && *(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((*p == 0x0b ||*p == 0x0c ||*p == 0x0d || *p == 0x85) && *(p+1) == 0x00 && *(p+2) == 0x00 && *(p+3) == 0x00) return 1; if (*(p+1) == 0x20 && (*p == 0x29 || *p == 0x28) && *(p+2) == 0x00 && *(p+3) == 0x00) return 1; #endif } return 0; } static int utf32le_is_mbc_newline_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p + 3 < end) { const UChar c0 = ONIG_CHARAT(p); const UChar c1 = ONIG_CHARAT(p+1); if (c0 == 0x0a && c1 == 0 && ONIG_CHARAT(p+2) == 0 && ONIG_CHARAT(p+3) == 0) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if ((c0 == 0x0b || c0 == 0x0c || c0 == 0x0d || c0 == 0x85) && c1 == 0x00 && ONIG_CHARAT(p+2) == 0x00 && ONIG_CHARAT(p+3) == 0x00) return 1; if (c1 == 0x20 && (c0 == 0x29 || c0 == 0x28) && ONIG_CHARAT(p+2) == 0x00 && ONIG_CHARAT(p+3) == 0x00) return 1; #endif } return 0; } static OnigCodePoint utf32le_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { return (OnigCodePoint )(((p[3] * 256 + p[2]) * 256 + p[1]) * 256 + p[0]); } static OnigCodePoint utf32le_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { return (OnigCodePoint )(((ONIG_CHARAT(p+3) * 256 + ONIG_CHARAT(p+2)) * 256 + ONIG_CHARAT(p+1)) * 256 + ONIG_CHARAT(p)); } static int utf32le_code_to_mbclen(OnigCodePoint code ARG_UNUSED) { return 4; } static int utf32le_code_to_mbc(OnigCodePoint code, UChar *buf) { UChar* p = buf; *p++ = (UChar ) (code & 0xff); *p++ = (UChar )((code & 0xff00) >> 8); *p++ = (UChar )((code & 0xff0000) >>16); *p++ = (UChar )((code & 0xff000000) >>24); return 4; } static int utf32le_mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold) { const UChar* p = *pp; if (ONIGENC_IS_ASCII_CODE(*p) && *(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (*p == 0x49) { *fold++ = 0x31; *fold++ = 0x01; } } else { #endif *fold++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); *fold++ = 0; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI } #endif *fold++ = 0; *fold = 0; *pp += 4; return 4; } else return onigenc_unicode_mbc_case_fold(ONIG_ENCODING_UTF32_LE, flag, pp, end, fold); } static int utf32le_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold) { const OnigPosition p = *pp; const UChar c = ONIG_CHARAT(p); if (ONIGENC_IS_ASCII_CODE(c) && ONIG_CHARAT(p+1) == 0 && ONIG_CHARAT(p+2) == 0 && ONIG_CHARAT(p+3) == 0) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (c == 0x49) { *fold++ = 0x31; *fold++ = 0x01; } } else { #endif *fold++ = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); *fold++ = 0; #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI } #endif *fold++ = 0; *fold = 0; *pp += 4; return 4; } else return onigenc_unicode_mbc_case_fold_se(it, ONIG_ENCODING_UTF32_LE, flag, pp, end, fold); } #if 0 static int utf32le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; (*pp) += 4; if (*(p+1) == 0 && *(p+2) == 0 && *(p+3) == 0) { int c, v; if (*p == 0xdf && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { return TRUE; } c = *p; v = ONIGENC_IS_UNICODE_ISO_8859_1_BIT_CTYPE(c, (BIT_CTYPE_UPPER | BIT_CTYPE_LOWER)); if ((v | BIT_CTYPE_LOWER) != 0) { /* 0xaa, 0xb5, 0xba are lower case letter, but can't convert. */ if (c >= 0xaa && c <= 0xba) return FALSE; else return TRUE; } return (v != 0 ? TRUE : FALSE); } return FALSE; } #endif static UChar* utf32le_left_adjust_char_head(const UChar* start, const UChar* s) { int rem; if (s <= start) return (UChar* )s; rem = (int )((s - start) % 4); return (UChar* )(s - rem); } static OnigPosition utf32le_left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { int rem; if (s <= start) return s; rem = (int )((s - start) % 4); return (s - rem); } static int utf32le_get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_unicode_get_case_fold_codes_by_str(ONIG_ENCODING_UTF32_LE, flag, p, end, items); } OnigEncodingType OnigEncodingUTF32_LE = { utf32le_mbc_enc_len, utf32le_mbc_enc_len_se, "UTF-32LE", /* name */ 4, /* max byte length */ 4, /* min byte length */ utf32le_is_mbc_newline, utf32le_is_mbc_newline_se, utf32le_mbc_to_code, utf32le_mbc_to_code_se, utf32le_code_to_mbclen, utf32le_code_to_mbc, utf32le_mbc_case_fold, utf32le_mbc_case_fold_se, onigenc_unicode_apply_all_case_fold, utf32le_get_case_fold_codes_by_str, onigenc_unicode_property_name_to_ctype, onigenc_unicode_is_code_ctype, onigenc_utf16_32_get_ctype_code_range, utf32le_left_adjust_char_head, utf32le_left_adjust_char_head_se, onigenc_always_false_is_allowed_reverse_match, ONIGENC_FLAG_UNICODE, }; ================================================ FILE: src/Onigmo/enc/utf8.c ================================================ /********************************************************************** utf8.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #include "regenc.h" #define USE_INVALID_CODE_SCHEME #ifdef USE_INVALID_CODE_SCHEME /* virtual codepoint values for invalid encoding byte 0xfe and 0xff */ #define INVALID_CODE_FE 0xfffffffe #define INVALID_CODE_FF 0xffffffff #define VALID_CODE_LIMIT 0x7fffffff #endif #define utf8_islead(c) ((UChar )((c) & 0xc0) != 0x80) static const int EncLen_UTF8[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 1, 1 }; static int mbc_enc_len(const UChar* p) { return EncLen_UTF8[*p]; } static int mbc_enc_len_se(OnigIterator* it, OnigPosition p) { return EncLen_UTF8[ONIG_CHARAT(p)]; } static int is_mbc_newline(const UChar* p, const UChar* end) { if (p < end) { if (*p == 0x0a) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if (*p == 0x0b || *p == 0x0c || *p == 0x0d) return 1; if (p + 1 < end) { if (*(p+1) == 0x85 && *p == 0xc2) /* U+0085 */ return 1; if (p + 2 < end) { if ((*(p+2) == 0xa8 || *(p+2) == 0xa9) && *(p+1) == 0x80 && *p == 0xe2) /* U+2028, U+2029 */ return 1; } } #endif } return 0; } static int is_mbc_newline_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p < end) { const UChar c0 = ONIG_CHARAT(p); if (c0 == 0x0a) return 1; #ifdef USE_UNICODE_ALL_LINE_TERMINATORS if (c0 == 0x0b || c0 == 0x0c || c0 == 0x0d) return 1; if (p + 1 < end) { const UChar c1 = ONIG_CHARAT(p+1); if (c1 == 0x85 && c0 == 0xc2) /* U+0085 */ return 1; if (p + 2 < end) { const UChar c2 = ONIG_CHARAT(p+2); if ((c2 == 0xa8 || c2 == 0xa9) && c1 == 0x80 && c0 == 0xe2) /* U+2028, U+2029 */ return 1; } } #endif } return 0; } static OnigCodePoint mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { int c, len; OnigCodePoint n; len = mbc_enc_len(p); c = *p++; if (len > 1) { len--; n = c & ((1 << (6 - len)) - 1); while (len--) { c = *p++; n = (n << 6) | (c & ((1 << 6) - 1)); } return n; } else { #ifdef USE_INVALID_CODE_SCHEME if (c > 0xfd) { return ((c == 0xfe) ? INVALID_CODE_FE : INVALID_CODE_FF); } #endif return (OnigCodePoint )c; } } static OnigCodePoint mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { int c, len; OnigCodePoint n; len = mbc_enc_len_se(it, p); c = ONIG_CHARAT(p++); if (len > 1) { len--; n = c & ((1 << (6 - len)) - 1); while (len--) { c = ONIG_CHARAT(p++); n = (n << 6) | (c & ((1 << 6) - 1)); } return n; } else { #ifdef USE_INVALID_CODE_SCHEME if (c > 0xfd) { return ((c == 0xfe) ? INVALID_CODE_FE : INVALID_CODE_FF); } #endif return (OnigCodePoint )c; } } static int code_to_mbclen(OnigCodePoint code) { if ((code & 0xffffff80) == 0) return 1; else if ((code & 0xfffff800) == 0) return 2; else if ((code & 0xffff0000) == 0) return 3; else if ((code & 0xffe00000) == 0) return 4; else if ((code & 0xfc000000) == 0) return 5; else if ((code & 0x80000000) == 0) return 6; #ifdef USE_INVALID_CODE_SCHEME else if (code == INVALID_CODE_FE) return 1; else if (code == INVALID_CODE_FF) return 1; #endif else return ONIGERR_INVALID_CODE_POINT_VALUE; } static int code_to_mbc(OnigCodePoint code, UChar *buf) { #define UTF8_TRAILS(code, shift) (UChar )((((code) >> (shift)) & 0x3f) | 0x80) #define UTF8_TRAIL0(code) (UChar )(((code) & 0x3f) | 0x80) if ((code & 0xffffff80) == 0) { *buf = (UChar )code; return 1; } else { UChar *p = buf; if ((code & 0xfffff800) == 0) { *p++ = (UChar )(((code>>6)& 0x1f) | 0xc0); } else if ((code & 0xffff0000) == 0) { *p++ = (UChar )(((code>>12) & 0x0f) | 0xe0); *p++ = UTF8_TRAILS(code, 6); } else if ((code & 0xffe00000) == 0) { *p++ = (UChar )(((code>>18) & 0x07) | 0xf0); *p++ = UTF8_TRAILS(code, 12); *p++ = UTF8_TRAILS(code, 6); } else if ((code & 0xfc000000) == 0) { *p++ = (UChar )(((code>>24) & 0x03) | 0xf8); *p++ = UTF8_TRAILS(code, 18); *p++ = UTF8_TRAILS(code, 12); *p++ = UTF8_TRAILS(code, 6); } else if ((code & 0x80000000) == 0) { *p++ = (UChar )(((code>>30) & 0x01) | 0xfc); *p++ = UTF8_TRAILS(code, 24); *p++ = UTF8_TRAILS(code, 18); *p++ = UTF8_TRAILS(code, 12); *p++ = UTF8_TRAILS(code, 6); } #ifdef USE_INVALID_CODE_SCHEME else if (code == INVALID_CODE_FE) { *p = 0xfe; return 1; } else if (code == INVALID_CODE_FF) { *p = 0xff; return 1; } #endif else { return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; } *p++ = UTF8_TRAIL0(code); return (int )(p - buf); } } static int mbc_case_fold(OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold) { const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (*p == 0x49) { *fold++ = 0xc4; *fold = 0xb1; (*pp)++; return 2; } } #endif *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); (*pp)++; return 1; /* return byte length of converted char to lower */ } else { return onigenc_unicode_mbc_case_fold(ONIG_ENCODING_UTF8, flag, pp, end, fold); } } static int mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold) { const UChar c = ONIG_CHARAT(*pp); if (ONIGENC_IS_MBC_ASCII_SE(c)) { #ifdef USE_UNICODE_CASE_FOLD_TURKISH_AZERI if ((flag & ONIGENC_CASE_FOLD_TURKISH_AZERI) != 0) { if (c == 0x49) { *fold++ = 0xc4; *fold = 0xb1; (*pp)++; return 2; } } #endif *fold = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); (*pp)++; return 1; /* return byte length of converted char to lower */ } else { return onigenc_unicode_mbc_case_fold_se(it, ONIG_ENCODING_UTF8, flag, pp, end, fold); } } #if 0 static int is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { (*pp)++; return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); } else { (*pp) += mbc_enc_len(p); if (*p == 0xc3) { int c = *(p + 1); if (c >= 0x80) { if (c <= (UChar )0x9e) { /* upper */ if (c == (UChar )0x97) return FALSE; return TRUE; } else if (c >= (UChar )0xa0 && c <= (UChar )0xbe) { /* lower */ if (c == (UChar )'\267') return FALSE; return TRUE; } else if (c == (UChar )0x9f && (flag & INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) != 0) { return TRUE; } } } } return FALSE; } #endif static int get_ctype_code_range(OnigCtype ctype, OnigCodePoint *sb_out, const OnigCodePoint* ranges[]) { *sb_out = 0x80; return onigenc_unicode_ctype_code_range(ctype, ranges); } static UChar* left_adjust_char_head(const UChar* start, const UChar* s) { const UChar *p; if (s <= start) return (UChar* )s; p = s; while (!utf8_islead(*p) && p > start) p--; return (UChar* )p; } static OnigPosition left_adjust_char_head_se(OnigIterator* it, OnigPosition start, OnigPosition s) { OnigPosition p; if (s <= start) return s; p = s; while (!utf8_islead(ONIG_CHARAT(p)) && p > start) p--; return p; } static int get_case_fold_codes_by_str(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { return onigenc_unicode_get_case_fold_codes_by_str(ONIG_ENCODING_UTF8, flag, p, end, items); } OnigEncodingType OnigEncodingUTF8 = { mbc_enc_len, mbc_enc_len_se, "UTF-8", /* name */ 6, /* max byte length */ 1, /* min byte length */ is_mbc_newline, is_mbc_newline_se, mbc_to_code, mbc_to_code_se, code_to_mbclen, code_to_mbc, mbc_case_fold, mbc_case_fold_se, onigenc_unicode_apply_all_case_fold, get_case_fold_codes_by_str, onigenc_unicode_property_name_to_ctype, onigenc_unicode_is_code_ctype, get_ctype_code_range, left_adjust_char_head, left_adjust_char_head_se, onigenc_always_true_is_allowed_reverse_match, ONIGENC_FLAG_UNICODE, }; ================================================ FILE: src/Onigmo/index.html ================================================ Oniguruma

Oniguruma

(Japanese)

(c) K.Kosako, updated at: 2013/04/04

What's new
  • 2013/04/04: Version 5.9.4 released.
  • 2007/08/16: Version 4.7.1 released.
  • 2007/06/20: Version 2.5.9 released.
  • 2007/06/20: Maintainer of 2.x was changed.

Oniguruma is a regular expressions library.
The characteristics of this library is that different character encoding
for every regular expression object can be specified.
(supported APIs: GNU regex, POSIX and Oniguruma native)

Supported character encodings:
ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE,
EUC-JP, EUC-TW, EUC-KR, EUC-CN,
Shift_JIS, Big5, GB18030, KOI8-R, CP1251,
ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5,
ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10,
ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16
(GB18030 encoding was contributed by KUBO Takehiro)
(CP1251 encoding was contributed by Byte)


License: BSD license.
Platform:
  • Unix (include Mac OS X)
  • Cygwin
  • Win32

Download:
Maintainer of 2.x was changed to Hannes Wyss <hwyss AT ywesee.com>.
About 2.x, please contact him.
* 5.x supports Unicode Property/Script.
* 2.x supports Ruby1.6/1.8.

Documents: (version 5.9.4)
Sample Programs:
Site Links:
Links:
References:

and I'm thankful to Akinori MUSHA.


Other Libraries:
================================================ FILE: src/Onigmo/index_ja.html ================================================ 鬼車

鬼車

(c) K.Kosako, 最終更新: 2013/04/04

更新情報
  • 2013/04/04: Version 5.9.4 リリース
  • 2007/08/16: Version 4.7.1 リリース
  • 2007/06/20: Version 2.5.9 リリース
  • 2007/06/20: 2.xの保守担当者を変更

鬼車は正規表現ライブラリである。
このライブラリの特徴は、それぞれの正規表現オブジェクトごとに異なる文字エンコーディングを 指定できること。
(API: GNU regex, POSIX and Oniguruma native)

対応している文字エンコーディング:
ASCII, UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE,
EUC-JP, EUC-TW, EUC-KR, EUC-CN,
Shift_JIS, Big5, GB18030, KOI8-R, CP1251,
ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5,
ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10,
ISO-8859-11, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16
(GB18030は、KUBO Takehiro氏提供)
(CP1251は、Byte氏提供)


ライセンス:BSDライセンス
プラットフォーム:
  • Unix (Mac OS Xを含む)
  • Cygwin
  • Win32

ダウンロード:
2.xの保守担当は、Hannes Wyss <hwyss AT ywesee.com>に交替しました。
2.xについては、彼に連絡してください。
* 5.xはUnicode Property/Scriptを提供
* 2.xはRuby1.6/1.8組込みライブラリとして動作する。 (2006年末で保守を終了)

ドキュメント: (version 5.9.4)
サンプルプログラム:
サイト:
リンク:
参考資料:

and I'm thankful to Akinori MUSHA.


他のライブラリ:

ホームにもどる ================================================ FILE: src/Onigmo/install-sh ================================================ #!/bin/sh # install - install a program, script, or datafile scriptversion=2009-04-28.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # 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 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/Onigmo/ltmain.sh ================================================ # Generated from ltmain.m4sh. # ltmain.sh (GNU libtool) 2.2.6b # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print informational messages (default) # --version print version information # -h, --help print short or long help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=ltmain.sh PACKAGE=libtool VERSION="2.2.6b Debian-2.2.6b-2ubuntu1" TIMESTAMP="" package_revision=1.3017 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # NLS nuisances: We save the old values to restore during execute mode. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done $lt_unset CDPATH : ${CP="cp -f"} : ${ECHO="echo"} : ${EGREP="/bin/grep -E"} : ${FGREP="/bin/grep -F"} : ${GREP="/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/bin/sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # Generated shell functions inserted here. # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: # In the unlikely event $progname began with a '-', it would play havoc with # func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result case $progname in -*) progname=./$progname ;; esac # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname${mode+: }$mode: $*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` done my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "X$my_tmpdir" | $Xsed } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "X$1" | $Xsed \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_version # Echo version message to standard output and exit. func_version () { $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $SED -n '/^# Usage:/,/# -h/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" $ECHO $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help # Echo long help message to standard output and exit. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" exit $? } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { func_error "missing argument for $1" exit_cmd=exit } exit_cmd=: # Check that we have a working $ECHO. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then # Yippee, $ECHO works! : else # Restart under the correct shell, and then maybe $ECHO will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # Parse options once, thoroughly. This comes as soon as possible in # the script to make things like `libtool --version' happen quickly. { # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Parse non-mode specific arguments: while test "$#" -gt 0; do opt="$1" shift case $opt in --config) func_config ;; --debug) preserve_args="$preserve_args $opt" func_echo "enabling shell trace mode" opt_debug='set -x' $opt_debug ;; -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break execute_dlfiles="$execute_dlfiles $1" shift ;; --dry-run | -n) opt_dry_run=: ;; --features) func_features ;; --finish) mode="finish" ;; --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break case $1 in # Valid mode arguments: clean) ;; compile) ;; execute) ;; finish) ;; install) ;; link) ;; relink) ;; uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac mode="$1" shift ;; --preserve-dup-deps) opt_duplicate_deps=: ;; --quiet|--silent) preserve_args="$preserve_args $opt" opt_silent=: ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false ;; --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break preserve_args="$preserve_args $opt $1" func_enable_tag "$1" # tagname is set here shift ;; # Separate optargs to long options: -dlopen=*|--mode=*|--tag=*) func_opt_split "$opt" set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} shift ;; -\?|-h) func_usage ;; --help) opt_help=: ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_duplicate_deps ;; esac # Having warned about all mis-specified options, bail out if # anything was wrong. $exit_cmd $EXIT_FAILURE } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } ## ----------- ## ## Main. ## ## ----------- ## $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi test -z "$mode" && func_fatal_error "error: you must specify a MODE." # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$mode' for more information." } # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_ltwrapper_scriptname_result="" if func_ltwrapper_executable_p "$1"; then func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" fi } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case "$@ " in " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi removelist="$removelist $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist removelist="$removelist $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir command="$command -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$mode'" ;; esac $ECHO $ECHO "Try \`$progname --help' for more information about other modes." exit $? } # Now that we've collected a possible --mode arg, show help if necessary $opt_help && func_mode_help # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $execute_dlfiles; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_quote_for_eval "$file" args="$args $func_quote_for_eval_result" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" $ECHO "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS $ECHO "X----------------------------------------------------------------------" | $Xsed $ECHO "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done $ECHO $ECHO "If you ever happen to want to link against installed libraries" $ECHO "in a given directory, LIBDIR, you must either use libtool, and" $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" $ECHO "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" $ECHO " during execution" fi if test -n "$runpath_var"; then $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" $ECHO " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $ECHO $ECHO "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" $ECHO "pages." ;; *) $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac $ECHO "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS } test "$mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $ECHO "X$nonopt" | $GREP shtool >/dev/null; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" } done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" fi $ECHO >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; " case $host in *cygwin* | *mingw* | *cegcc* ) $ECHO >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" lt_dlsym_const= ;; *osf5*) echo >> "$output_objdir/$my_dlsyms" "\ /* This system does not cope well with relocations in const data */" lt_dlsym_const= ;; *) lt_dlsym_const=const ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) symtab_cflags="$symtab_cflags $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper_part1 [arg=no] # # Emit the first part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part1 () { func_emit_wrapper_part1_arg1=no if test -n "$1" ; then func_emit_wrapper_part1_arg1=$1 fi $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then ECHO=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then # Yippee, \$ECHO works! : else # Restart under the correct shell, and then maybe \$ECHO will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $ECHO "\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done " } # end: func_emit_wrapper_part1 # func_emit_wrapper_part2 [arg=no] # # Emit the second part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part2 () { func_emit_wrapper_part2_arg1=no if test -n "$1" ; then func_emit_wrapper_part2_arg1=$1 fi $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # end: func_emit_wrapper_part2 # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=no if test -n "$1" ; then func_emit_wrapper_arg1=$1 fi # split this up so that func_emit_cwrapperexe_src # can call each part independently. func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_path_tmp1=`( cmd //c echo "$1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_tmp1=`cygpath -w "$1"` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result="" fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_to_host_pathlist_tmp2="$1" # Once set for this call, this variable should not be # reassigned. It is used in tha fallback case. func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e 's|^:*||' -e 's|:*$||'` case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" fi fi fi IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result" ; then func_error "Could not determine the host path(s) corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" ;; esac ;; esac fi } # end: func_to_host_pathlist # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include # define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include # define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif # endif #endif #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif #ifdef _MSC_VER # define S_IXUSR _S_IEXEC # define stat _stat # ifndef _INTPTR_T_DEFINED # define intptr_t int # endif #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifdef __CYGWIN__ # define FOPEN_WB "wb" #endif #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #undef LTWRAPPER_DEBUGPRINTF #if defined DEBUGWRAPPER # define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args static void ltwrapper_debugprintf (const char *fmt, ...) { va_list args; va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } #else # define LTWRAPPER_DEBUGPRINTF(args) #endif const char *program_name = NULL; void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_fatal (const char *message, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_opt_process_env_set (const char *arg); void lt_opt_process_env_prepend (const char *arg); void lt_opt_process_env_append (const char *arg); int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); static const char *script_text_part1 = EOF func_emit_wrapper_part1 yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ "/' -e 's/$/\\n"/' echo ";" cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", tmp_pathspec)); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { char *errstr = strerror (errno); lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal ("Could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } int lt_split_name_value (const char *arg, char** name, char** value) { const char *p; int len; if (!arg || !*arg) return 1; p = strchr (arg, (int)'='); if (!p) return 1; *value = xstrdup (++p); len = strlen (arg) - strlen (*value); *name = XMALLOC (char, len); strncpy (*name, arg, len-1); (*name)[len - 1] = '\0'; return 0; } void lt_opt_process_env_set (const char *arg) { char *name = NULL; char *value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); } lt_setenv (name, value); XFREE (name); XFREE (value); } void lt_opt_process_env_prepend (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); } new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_opt_process_env_append (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); } new_value = lt_extend_str (getenv (name), value, 1); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF } # end: func_emit_cwrapperexe_src # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) deplibs="$deplibs $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) weak_libs="$weak_libs $arg" prev= continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname '-L' '' "$arg" dir=$func_stripname_result if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" linker_flags="$linker_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" compiler_flags="$compiler_flags $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_duplicate_deps ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= case $lib in *.la) func_source "$lib" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" dir=$func_stripname_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $ECHO $ECHO "*** Warning: Trying to link with static lib archive $deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because the file extensions .$libext of this argument makes me believe" $ECHO "*** that it is just a static archive that I should not use here." else $ECHO $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) temp_rpath="$temp_rpath$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded notinst_deplibs="$notinst_deplibs $lib" need_relink=no ;; *) if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $ECHO if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $ECHO $ECHO "*** And there doesn't seem to be a static archive available" $ECHO "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $ECHO $ECHO "*** Warning: This system can not link to static lib archive $lib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $ECHO "*** But as you try to build a module library, libtool will still create " $ECHO "*** a static module, that should work as long as the dlopening application" $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_dirname "$deplib" "" "." dir="$func_dirname_result" # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else $ECHO $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type \`$version_type'" ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" libobjs="$libobjs $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` done fi if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | $GREP . >/dev/null; then $ECHO if test "X$deplibs_check_method" = "Xnone"; then $ECHO "*** Warning: inter-library dependencies are not supported in this platform." else $ECHO "*** Warning: inter-library dependencies are not known to be supported." fi $ECHO "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $ECHO $ECHO "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" $ECHO "*** a static module, that should work as long as the dlopening" $ECHO "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $ECHO "*** The inter-library dependencies that have been dropped here will be" $ECHO "*** automatically added whenever a program is linked with this library" $ECHO "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $ECHO $ECHO "*** Since this library must not contain undefined symbols," $ECHO "*** because either the platform does not support them or" $ECHO "*** it was explicitly requested with -no-undefined," $ECHO "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" delfiles="$delfiles $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" func_len " $cmd" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then func_show_eval "$cmd" 'exit $?' skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" $ECHO 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done $ECHO ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do $ECHO "$obj" >> $output done delfiles="$delfiles $output" output=$firstobj\"$file_list_spec$output\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=$obj func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi delfiles="$delfiles $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *cegcc) # Disable wrappers for cegcc, we are cross compiling anyway. wrappers_required=no ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $ECHO for shipping. if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then oldobjs="$oldobjs $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles oldobjs="$oldobjs $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else $ECHO "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlfiles="$newdlfiles $libdir/$name" ;; *) newdlfiles="$newdlfiles $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlprefiles="$newdlprefiles $libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$mode" = link || test "$mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) RM="$RM $arg"; rmforce=yes ;; -*) RM="$RM $arg" ;; *) files="$files $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then objdir="$origobjdir" else objdir="$dir/$origobjdir" fi func_basename "$file" name="$func_basename_result" test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result rmfiles="$rmfiles $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$mode" = uninstall || test "$mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 ================================================ FILE: src/Onigmo/m4/libtool.m4 ================================================ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 56 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl _LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\[$]0 --fallback-echo"')dnl " lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` ;; esac _LT_OUTPUT_LIBTOOL_INIT ]) # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) cat >"$CONFIG_LT" <<_LTEOF #! $SHELL # Generated by $as_me. # Run this file to recreate a libtool stub with the current configuration. lt_cl_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2008 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. if test "$no_create" != yes; then lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) fi ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_XSI_SHELLFNS sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(whole_archive_flag_spec, $1)='' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX # ----------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl AC_LINK_IFELSE(AC_LANG_PROGRAM,[ lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. m4_defun([_LT_PROG_ECHO_BACKSLASH], [_LT_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac ECHO=${lt_ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF [$]* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(lt_ECHO) ]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that does not interpret backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [AC_CHECK_TOOL(AR, ar, false) test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1]) AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line __oline__ "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method == "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC*) # IBM XL 8.0 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' ;; linux* | k*bsd*-gnu) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; linux* | k*bsd*-gnu) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi _LT_TAGVAR(link_all_deplibs, $1)=no else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE(int foo(void) {}, _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' ) LDFLAGS="$save_LDFLAGS" else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then _LT_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [fix_srcfile_path], [1], [Fix the shell variable $srcfile for the compiler]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_PROG_CXX # ------------ # Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ # compiler, we have our own version here. m4_defun([_LT_PROG_CXX], [ pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) AC_PROG_CXX if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_CXX dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_CXX], []) # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [AC_REQUIRE([_LT_PROG_CXX])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 will use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; xl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=echo else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_PROG_F77 # ------------ # Since AC_PROG_F77 is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_F77], [ pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) AC_PROG_F77 if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_F77 dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_F77], []) # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_REQUIRE([_LT_PROG_F77])dnl AC_LANG_PUSH(Fortran 77) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${F77-"f77"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_PROG_FC # ----------- # Since AC_PROG_FC is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_FC], [ pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) AC_PROG_FC if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_FC dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_FC], []) # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_REQUIRE([_LT_PROG_FC])dnl AC_LANG_PUSH(Fortran) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${FC-"f95"} compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC="$lt_save_CC" ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC= CC=${RC-"windres"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC="$lt_save_CC" ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_XSI_SHELLFNS # --------------------- # Bourne and XSI compatible variants of some useful shell functions. m4_defun([_LT_PROG_XSI_SHELLFNS], [case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $[*] )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } dnl func_dirname_and_basename dnl A portable version of this function is already defined in general.m4sh dnl so there is no need for it here. # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[[^=]]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$[@]"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]+=\$[2]" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]=\$$[1]\$[2]" } _LT_EOF ;; esac ]) ================================================ FILE: src/Onigmo/m4/ltoptions.m4 ================================================ # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [0], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) ================================================ FILE: src/Onigmo/m4/ltsugar.m4 ================================================ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) ================================================ FILE: src/Onigmo/m4/ltversion.m4 ================================================ # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # Generated from ltversion.in. # serial 3017 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.2.6b]) m4_define([LT_PACKAGE_REVISION], [1.3017]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.2.6b' macro_revision='1.3017' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) ================================================ FILE: src/Onigmo/m4/lt~obsolete.m4 ================================================ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 4 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) ================================================ FILE: src/Onigmo/missing ================================================ #! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; tar*) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar*) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ================================================ FILE: src/Onigmo/onig-config.in ================================================ #!/bin/sh # Copyright (C) 2006 K.Kosako (sndgk393 AT ybb DOT ne DOT jp) ONIG_VERSION=@PACKAGE_VERSION@ show_usage() { cat < -1000) # normal return ONIG_NORMAL = 0 ONIG_MISMATCH = -1 ONIG_NO_SUPPORT_CONFIG = -2 # internal error # general error ONIGERR_INVALID_ARGUMENT = -30 # syntax error # values error (syntax error) # errors related to thread ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT = -1001 # # Onigmo APIs # # onig_init onig_init = libonig.onig_init # onig_error_code_to_str libonig.onig_error_code_to_str.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(OnigErrorInfo)] def onig_error_code_to_str(err_buf, err_code, err_info=None): return libonig.onig_error_code_to_str(err_buf, err_code, err_info) # onig_set_warn_func # onig_set_verb_warn_func # onig_new libonig.onig_new.argtypes = [ctypes.POINTER(OnigRegex), ctypes.c_void_p, ctypes.c_void_p, OnigOptionType, OnigEncoding, ctypes.POINTER(OnigSyntaxType), ctypes.POINTER(OnigErrorInfo)] onig_new = libonig.onig_new # onig_reg_init # onig_new_without_alloc # onig_new_deluxe # onig_free libonig.onig_free.argtypes = [OnigRegex] onig_free = libonig.onig_free # onig_free_body # onig_recompile # onig_recompile_deluxe # onig_search libonig.onig_search.argtypes = [OnigRegex, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(OnigRegion), OnigOptionType] libonig.onig_search.restype = _c_ssize_t onig_search = libonig.onig_search # onig_search_gpos # onig_match libonig.onig_match.argtypes = [OnigRegex, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.POINTER(OnigRegion), OnigOptionType] libonig.onig_match.restype = _c_ssize_t onig_match = libonig.onig_match # onig_region_new libonig.onig_region_new.argtypes = [] libonig.onig_region_new.restype = ctypes.POINTER(OnigRegion) onig_region_new = libonig.onig_region_new # onig_region_init # onig_region_free libonig.onig_region_free.argtypes = [ctypes.POINTER(OnigRegion), ctypes.c_int] onig_region_free = libonig.onig_region_free # onig_region_copy # onig_region_clear # onig_region_resize # onig_region_set # onig_name_to_group_numbers # onig_name_to_backref_number # onig_foreach_name # onig_number_of_names # onig_number_of_captures # onig_number_of_capture_histories # onig_get_capture_tree # onig_capture_tree_traverse # onig_noname_group_capture_is_active # onig_get_encoding # onig_get_options # onig_get_case_fold_flag # onig_get_syntax # onig_set_default_syntax # onig_copy_syntax libonig.onig_copy_syntax.argtypes = [ctypes.POINTER(OnigSyntaxType), ctypes.POINTER(OnigSyntaxType)] onig_copy_syntax = libonig.onig_copy_syntax # onig_get_syntax_op # onig_get_syntax_op2 # onig_get_syntax_behavior # onig_get_syntax_options # onig_set_syntax_op # onig_set_syntax_op2 # onig_set_syntax_behavior # onig_set_syntax_options # onig_set_meta_char # onig_copy_encoding # onig_get_default_case_fold_flag # onig_set_default_case_fold_flag # onig_get_match_stack_limit_size # onig_set_match_stack_limit_size # onig_end libonig.onig_end.argtypes = [] onig_end = libonig.onig_end # onig_version libonig.onig_version.argtypes = [] libonig.onig_version.restype = ctypes.c_char_p def onig_version(): return libonig.onig_version().decode() # onig_copyright libonig.onig_copyright.argtypes = [] libonig.onig_copyright.restype = ctypes.c_char_p def onig_copyright(): return libonig.onig_copyright().decode() ================================================ FILE: src/Onigmo/oniggnu.h ================================================ #ifndef ONIGGNU_H #define ONIGGNU_H /********************************************************************** oniggnu.h - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2005 K.Kosako * 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. */ #include "oniguruma.h" #ifdef __cplusplus extern "C" { #endif #define RE_MBCTYPE_ASCII 0 #define RE_MBCTYPE_EUC 1 #define RE_MBCTYPE_SJIS 2 #define RE_MBCTYPE_UTF8 3 /* GNU regex options */ #ifndef RE_NREGS #define RE_NREGS ONIG_NREGION #endif #define RE_OPTION_IGNORECASE ONIG_OPTION_IGNORECASE #define RE_OPTION_EXTENDED ONIG_OPTION_EXTEND #define RE_OPTION_MULTILINE ONIG_OPTION_MULTILINE #define RE_OPTION_SINGLELINE ONIG_OPTION_SINGLELINE #define RE_OPTION_LONGEST ONIG_OPTION_FIND_LONGEST #define RE_OPTION_POSIXLINE (RE_OPTION_MULTILINE|RE_OPTION_SINGLELINE) #define RE_OPTION_FIND_NOT_EMPTY ONIG_OPTION_FIND_NOT_EMPTY #define RE_OPTION_NEGATE_SINGLELINE ONIG_OPTION_NEGATE_SINGLELINE #define RE_OPTION_DONT_CAPTURE_GROUP ONIG_OPTION_DONT_CAPTURE_GROUP #define RE_OPTION_CAPTURE_GROUP ONIG_OPTION_CAPTURE_GROUP ONIG_EXTERN void re_mbcinit P_((int)); ONIG_EXTERN int re_compile_pattern P_((const char*, int, struct re_pattern_buffer*, char* err_buf)); ONIG_EXTERN int re_recompile_pattern P_((const char*, int, struct re_pattern_buffer*, char* err_buf)); ONIG_EXTERN void re_free_pattern P_((struct re_pattern_buffer*)); ONIG_EXTERN int re_adjust_startpos P_((struct re_pattern_buffer*, const char*, int, int, int)); ONIG_EXTERN int re_search P_((OnigIterator* it, struct re_pattern_buffer*, OnigPosition, OnigPosition, OnigPosition, OnigPosition, struct re_registers*)); ONIG_EXTERN int re_match P_((OnigIterator* it, struct re_pattern_buffer*, OnigPosition, OnigPosition, OnigPosition, struct re_registers*)); ONIG_EXTERN void re_set_casetable P_((const char*)); ONIG_EXTERN void re_free_registers P_((struct re_registers*)); ONIG_EXTERN int re_alloc_pattern P_((struct re_pattern_buffer**)); /* added */ #ifdef __cplusplus } #endif #endif /* ONIGGNU_H */ ================================================ FILE: src/Onigmo/onigposix.h ================================================ #ifndef ONIGPOSIX_H #define ONIGPOSIX_H /********************************************************************** onigposix.h - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2005 K.Kosako * 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. */ #include #ifdef __cplusplus extern "C" { #endif /* options */ #define REG_ICASE (1<<0) #define REG_NEWLINE (1<<1) #define REG_NOTBOL (1<<2) #define REG_NOTEOL (1<<3) #define REG_EXTENDED (1<<4) /* if not set, Basic Onigular Expression */ #define REG_NOSUB (1<<5) /* POSIX error codes */ #define REG_NOMATCH 1 #define REG_BADPAT 2 #define REG_ECOLLATE 3 #define REG_ECTYPE 4 #define REG_EESCAPE 5 #define REG_ESUBREG 6 #define REG_EBRACK 7 #define REG_EPAREN 8 #define REG_EBRACE 9 #define REG_BADBR 10 #define REG_ERANGE 11 #define REG_ESPACE 12 #define REG_BADRPT 13 /* extended error codes */ #define REG_EONIG_INTERNAL 14 #define REG_EONIG_BADWC 15 #define REG_EONIG_BADARG 16 #define REG_EONIG_THREAD 17 /* character encodings (for reg_set_encoding()) */ #define REG_POSIX_ENCODING_ASCII 0 #define REG_POSIX_ENCODING_EUC_JP 1 #define REG_POSIX_ENCODING_SJIS 2 #define REG_POSIX_ENCODING_UTF8 3 #define REG_POSIX_ENCODING_UTF16_BE 4 #define REG_POSIX_ENCODING_UTF16_LE 5 typedef int regoff_t; typedef struct { regoff_t rm_so; regoff_t rm_eo; } regmatch_t; /* POSIX regex_t */ typedef struct { void* onig; /* Oniguruma regex_t* */ size_t re_nsub; int comp_options; } regex_t; #ifndef P_ #if defined(__STDC__) || defined(_WIN32) # define P_(args) args #else # define P_(args) () #endif #endif #ifndef ONIG_EXTERN #if defined(_WIN32) && !defined(__GNUC__) #if defined(EXPORT) #define ONIG_EXTERN extern __declspec(dllexport) #else #define ONIG_EXTERN extern __declspec(dllimport) #endif #endif #endif #ifndef ONIG_EXTERN #define ONIG_EXTERN extern #endif #ifndef ONIGURUMA_H typedef unsigned int OnigOptionType; /* syntax */ typedef struct { unsigned int op; unsigned int op2; unsigned int behavior; OnigOptionType options; /* default option */ } OnigSyntaxType; ONIG_EXTERN OnigSyntaxType OnigSyntaxPosixBasic; ONIG_EXTERN OnigSyntaxType OnigSyntaxPosixExtended; ONIG_EXTERN OnigSyntaxType OnigSyntaxEmacs; ONIG_EXTERN OnigSyntaxType OnigSyntaxGrep; ONIG_EXTERN OnigSyntaxType OnigSyntaxGnuRegex; ONIG_EXTERN OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN OnigSyntaxType OnigSyntaxRuby; /* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) #define ONIG_SYNTAX_GREP (&OnigSyntaxGrep) #define ONIG_SYNTAX_GNU_REGEX (&OnigSyntaxGnuRegex) #define ONIG_SYNTAX_JAVA (&OnigSyntaxJava) #define ONIG_SYNTAX_PERL (&OnigSyntaxPerl) #define ONIG_SYNTAX_RUBY (&OnigSyntaxRuby) /* default syntax */ #define ONIG_SYNTAX_DEFAULT OnigDefaultSyntax ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; ONIG_EXTERN int onig_set_default_syntax P_((OnigSyntaxType* syntax)); ONIG_EXTERN void onig_copy_syntax P_((OnigSyntaxType* to, OnigSyntaxType* from)); ONIG_EXTERN const char* onig_version P_((void)); ONIG_EXTERN const char* onig_copyright P_((void)); #endif /* ONIGURUMA_H */ ONIG_EXTERN int regcomp P_((regex_t* reg, const char* pat, int options)); ONIG_EXTERN OnigPosition regexec P_((OnigIterator* it, regex_t* reg, OnigPosition str, size_t nmatch, regmatch_t* matches, int options)); ONIG_EXTERN void regfree P_((regex_t* reg)); ONIG_EXTERN size_t regerror P_((int code, const regex_t* reg, char* buf, size_t size)); /* extended API */ ONIG_EXTERN void reg_set_encoding P_((int enc)); ONIG_EXTERN int reg_name_to_group_numbers P_((regex_t* reg, const unsigned char* name, const unsigned char* name_end, int** nums)); ONIG_EXTERN int reg_foreach_name P_((regex_t* reg, int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*), void* arg)); ONIG_EXTERN int reg_number_of_names P_((regex_t* reg)); #ifdef __cplusplus } #endif #endif /* ONIGPOSIX_H */ ================================================ FILE: src/Onigmo/oniguruma.h ================================================ #ifndef ONIGURUMA_H #define ONIGURUMA_H /********************************************************************** oniguruma.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2009 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ #ifdef __cplusplus extern "C" { #endif #define ONIGURUMA #define ONIGURUMA_VERSION_MAJOR 5 #define ONIGURUMA_VERSION_MINOR 13 #define ONIGURUMA_VERSION_TEENY 5 #ifdef __cplusplus # ifndef HAVE_PROTOTYPES # define HAVE_PROTOTYPES 1 # endif # ifndef HAVE_STDARG_PROTOTYPES # define HAVE_STDARG_PROTOTYPES 1 # endif #endif /* escape Mac OS X/Xcode 2.4/gcc 4.0.1 problem */ #if defined(__APPLE__) && defined(__GNUC__) && __GNUC__ >= 4 # ifndef HAVE_STDARG_PROTOTYPES # define HAVE_STDARG_PROTOTYPES 1 # endif #endif #ifdef HAVE_STDARG_H # ifndef HAVE_STDARG_PROTOTYPES # define HAVE_STDARG_PROTOTYPES 1 # endif #endif #ifndef P_ #if defined(__STDC__) || defined(_WIN32) # define P_(args) args #else # define P_(args) () #endif #endif #ifndef PV_ #ifdef HAVE_STDARG_PROTOTYPES # define PV_(args) args #else # define PV_(args) () #endif #endif #ifndef ONIG_EXTERN #if defined(_WIN32) && !defined(__GNUC__) #if defined(EXPORT) || defined(RUBY_EXPORT) #define ONIG_EXTERN extern __declspec(dllexport) #else #define ONIG_EXTERN extern __declspec(dllimport) #endif #endif #endif #ifndef ONIG_EXTERN #define ONIG_EXTERN extern #endif #include /* for size_t */ /* PART: character encoding */ #ifndef ONIG_ESCAPE_UCHAR_COLLISION #define UChar OnigUChar #endif typedef unsigned char OnigUChar; typedef unsigned int OnigCodePoint; typedef unsigned int OnigCtype; typedef size_t OnigDistance; #define ONIG_INFINITE_DISTANCE ~((OnigDistance )0) #if defined(_MSC_VER) typedef __int64 OnigPosition; #else typedef long long OnigPosition; #endif #define ONIG_BADPOS -1 #define ONIG_IS_BADPOS(p) (p == ONIG_BADPOS) #define ONIG_IS_NOT_BADPOS(p) (p != ONIG_BADPOS) typedef UChar (*OnigCharAtFunc)(OnigPosition pos, const void* ptr); typedef struct OnigIteratorStruct { OnigCharAtFunc at; const void* ptr; } OnigIterator; #define ONIG_CHARAT(pos) (it->at(pos, it->ptr)) /* Iterator API */ ONIG_EXTERN UChar onig_default_charat P_((OnigPosition pos, const void* ptr)); typedef unsigned int OnigCaseFoldType; /* case fold flag */ ONIG_EXTERN OnigCaseFoldType OnigDefaultCaseFoldFlag; /* #define ONIGENC_CASE_FOLD_HIRAGANA_KATAKANA (1<<1) */ /* #define ONIGENC_CASE_FOLD_KATAKANA_WIDTH (1<<2) */ #define ONIGENC_CASE_FOLD_TURKISH_AZERI (1<<20) #define INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR (1<<30) #define ONIGENC_CASE_FOLD_MIN INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR #define ONIGENC_CASE_FOLD_DEFAULT OnigDefaultCaseFoldFlag #define ONIGENC_MAX_COMP_CASE_FOLD_CODE_LEN 3 #define ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM 13 /* 13 => Unicode:0x1ffc */ /* code range */ #define ONIGENC_CODE_RANGE_NUM(range) ((int )range[0]) #define ONIGENC_CODE_RANGE_FROM(range,i) range[((i)*2) + 1] #define ONIGENC_CODE_RANGE_TO(range,i) range[((i)*2) + 2] typedef struct { int byte_len; /* argument(original) character(s) byte length */ int code_len; /* number of code */ OnigCodePoint code[ONIGENC_MAX_COMP_CASE_FOLD_CODE_LEN]; } OnigCaseFoldCodeItem; typedef struct { OnigCodePoint esc; OnigCodePoint anychar; OnigCodePoint anytime; OnigCodePoint zero_or_one_time; OnigCodePoint one_or_more_time; OnigCodePoint anychar_anytime; } OnigMetaCharTableType; typedef int (*OnigApplyAllCaseFoldFunc)(OnigCodePoint from, OnigCodePoint* to, int to_len, void* arg); typedef struct OnigEncodingTypeST { int (*mbc_enc_len)(const OnigUChar* p); int (*mbc_enc_len_se)(OnigIterator* it, OnigPosition p); const char* name; int max_enc_len; int min_enc_len; int (*is_mbc_newline)(const OnigUChar* p, const OnigUChar* end); int (*is_mbc_newline_se)(OnigIterator* it, OnigPosition p, OnigPosition end); OnigCodePoint (*mbc_to_code)(const OnigUChar* p, const OnigUChar* end); OnigCodePoint (*mbc_to_code_se)(OnigIterator* it, OnigPosition p, OnigPosition end); int (*code_to_mbclen)(OnigCodePoint code); int (*code_to_mbc)(OnigCodePoint code, OnigUChar *buf); int (*mbc_case_fold)(OnigCaseFoldType flag, const OnigUChar** pp, const OnigUChar* end, OnigUChar* to); int (*mbc_case_fold_se)(OnigIterator* it, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, OnigUChar* to); int (*apply_all_case_fold)(OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg); int (*get_case_fold_codes_by_str)(OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem acs[]); int (*property_name_to_ctype)(struct OnigEncodingTypeST* enc, OnigUChar* p, OnigUChar* end); int (*is_code_ctype)(OnigCodePoint code, OnigCtype ctype); int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[]); OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p); OnigPosition (*left_adjust_char_head_se)(OnigIterator* it, OnigPosition start, OnigPosition p); int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end); unsigned int flags; } OnigEncodingType; typedef OnigEncodingType* OnigEncoding; ONIG_EXTERN OnigEncodingType OnigEncodingASCII; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_1; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_2; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_3; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_4; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_5; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_6; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_7; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_8; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_9; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_10; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_11; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_13; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_14; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_15; ONIG_EXTERN OnigEncodingType OnigEncodingISO_8859_16; ONIG_EXTERN OnigEncodingType OnigEncodingUTF8; ONIG_EXTERN OnigEncodingType OnigEncodingUTF16_BE; ONIG_EXTERN OnigEncodingType OnigEncodingUTF16_LE; ONIG_EXTERN OnigEncodingType OnigEncodingUTF32_BE; ONIG_EXTERN OnigEncodingType OnigEncodingUTF32_LE; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_JP; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_TW; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_KR; ONIG_EXTERN OnigEncodingType OnigEncodingEUC_CN; ONIG_EXTERN OnigEncodingType OnigEncodingSJIS; ONIG_EXTERN OnigEncodingType OnigEncodingCP932; ONIG_EXTERN OnigEncodingType OnigEncodingKOI8; ONIG_EXTERN OnigEncodingType OnigEncodingKOI8_R; ONIG_EXTERN OnigEncodingType OnigEncodingCP1251; ONIG_EXTERN OnigEncodingType OnigEncodingBIG5; ONIG_EXTERN OnigEncodingType OnigEncodingGB18030; #define ONIG_ENCODING_ASCII (&OnigEncodingASCII) #define ONIG_ENCODING_ISO_8859_1 (&OnigEncodingISO_8859_1) #define ONIG_ENCODING_ISO_8859_2 (&OnigEncodingISO_8859_2) #define ONIG_ENCODING_ISO_8859_3 (&OnigEncodingISO_8859_3) #define ONIG_ENCODING_ISO_8859_4 (&OnigEncodingISO_8859_4) #define ONIG_ENCODING_ISO_8859_5 (&OnigEncodingISO_8859_5) #define ONIG_ENCODING_ISO_8859_6 (&OnigEncodingISO_8859_6) #define ONIG_ENCODING_ISO_8859_7 (&OnigEncodingISO_8859_7) #define ONIG_ENCODING_ISO_8859_8 (&OnigEncodingISO_8859_8) #define ONIG_ENCODING_ISO_8859_9 (&OnigEncodingISO_8859_9) #define ONIG_ENCODING_ISO_8859_10 (&OnigEncodingISO_8859_10) #define ONIG_ENCODING_ISO_8859_11 (&OnigEncodingISO_8859_11) #define ONIG_ENCODING_ISO_8859_13 (&OnigEncodingISO_8859_13) #define ONIG_ENCODING_ISO_8859_14 (&OnigEncodingISO_8859_14) #define ONIG_ENCODING_ISO_8859_15 (&OnigEncodingISO_8859_15) #define ONIG_ENCODING_ISO_8859_16 (&OnigEncodingISO_8859_16) #define ONIG_ENCODING_UTF8 (&OnigEncodingUTF8) #define ONIG_ENCODING_UTF16_BE (&OnigEncodingUTF16_BE) #define ONIG_ENCODING_UTF16_LE (&OnigEncodingUTF16_LE) #define ONIG_ENCODING_UTF32_BE (&OnigEncodingUTF32_BE) #define ONIG_ENCODING_UTF32_LE (&OnigEncodingUTF32_LE) #define ONIG_ENCODING_EUC_JP (&OnigEncodingEUC_JP) #define ONIG_ENCODING_EUC_TW (&OnigEncodingEUC_TW) #define ONIG_ENCODING_EUC_KR (&OnigEncodingEUC_KR) #define ONIG_ENCODING_EUC_CN (&OnigEncodingEUC_CN) #define ONIG_ENCODING_SJIS (&OnigEncodingSJIS) #define ONIG_ENCODING_CP932 (&OnigEncodingCP932) #define ONIG_ENCODING_KOI8 (&OnigEncodingKOI8) #define ONIG_ENCODING_KOI8_R (&OnigEncodingKOI8_R) #define ONIG_ENCODING_CP1251 (&OnigEncodingCP1251) #define ONIG_ENCODING_BIG5 (&OnigEncodingBIG5) #define ONIG_ENCODING_GB18030 (&OnigEncodingGB18030) #define ONIG_ENCODING_UNDEF ((OnigEncoding )0) /* work size */ #define ONIGENC_CODE_TO_MBC_MAXLEN 7 #define ONIGENC_MBC_CASE_FOLD_MAXLEN 18 /* 18: 6(max-byte) * 3(case-fold chars) */ /* character types */ #define ONIGENC_CTYPE_NEWLINE 0 #define ONIGENC_CTYPE_ALPHA 1 #define ONIGENC_CTYPE_BLANK 2 #define ONIGENC_CTYPE_CNTRL 3 #define ONIGENC_CTYPE_DIGIT 4 #define ONIGENC_CTYPE_GRAPH 5 #define ONIGENC_CTYPE_LOWER 6 #define ONIGENC_CTYPE_PRINT 7 #define ONIGENC_CTYPE_PUNCT 8 #define ONIGENC_CTYPE_SPACE 9 #define ONIGENC_CTYPE_UPPER 10 #define ONIGENC_CTYPE_XDIGIT 11 #define ONIGENC_CTYPE_WORD 12 #define ONIGENC_CTYPE_ALNUM 13 /* alpha || digit */ #define ONIGENC_CTYPE_ASCII 14 #define ONIGENC_MAX_STD_CTYPE ONIGENC_CTYPE_ASCII /* flags */ #define ONIGENC_FLAG_NONE 0U #define ONIGENC_FLAG_UNICODE 1U #define onig_enc_len(enc,p,end) ONIGENC_MBC_ENC_LEN(enc,p) #define ONIGENC_IS_UNDEF(enc) ((enc) == ONIG_ENCODING_UNDEF) #define ONIGENC_IS_SINGLEBYTE(enc) (ONIGENC_MBC_MAXLEN(enc) == 1) #define ONIGENC_IS_MBC_HEAD(enc,p) (ONIGENC_MBC_ENC_LEN(enc,p) != 1) #define ONIGENC_IS_MBC_HEAD_SE(it,enc,p) (ONIGENC_MBC_ENC_LEN_SE(it,enc,p) != 1) #define ONIGENC_IS_MBC_ASCII(p) (*(p) < 128) #define ONIGENC_IS_MBC_ASCII_SE(c) (c < 128) #define ONIGENC_IS_CODE_ASCII(code) ((code) < 128) #define ONIGENC_IS_MBC_WORD(enc,s,end) \ ONIGENC_IS_CODE_WORD(enc,ONIGENC_MBC_TO_CODE(enc,s,end)) #define ONIGENC_IS_MBC_WORD_SE(it,enc,s,end) \ ONIGENC_IS_CODE_WORD(enc,ONIGENC_MBC_TO_CODE_SE(it,enc,s,end)) #define ONIGENC_IS_MBC_SINGLEBYTE_SE(it,enc,s,end) \ (ONIGENC_MBC_TO_CODE_SE(it,enc,s,end) <= 0xFF) #define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \ onigenc_ascii_is_code_ctype( \ ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD) #define ONIGENC_IS_MBC_ASCII_WORD_SE(it,enc,s,end) \ onigenc_ascii_is_code_ctype( \ ONIGENC_MBC_TO_CODE_SE(it,enc,s,end),ONIGENC_CTYPE_WORD) #define ONIGENC_IS_UNICODE(enc) ((enc)->flags & ONIGENC_FLAG_UNICODE) #define ONIGENC_SCRIPT(enc,s,end) (onigenc_unicode_code_script(ONIGENC_MBC_TO_CODE(enc,s,end))) #define ONIGENC_SCRIPT_SE(it,enc,s,end) (onigenc_unicode_code_script(ONIGENC_MBC_TO_CODE_SE(it,enc,s,end))) #define ONIGENC_NAME(enc) ((enc)->name) #define ONIGENC_MBC_CASE_FOLD(enc,flag,pp,end,buf) \ (enc)->mbc_case_fold(flag,(const OnigUChar** )pp,end,buf) #define ONIGENC_MBC_CASE_FOLD_SE(it,enc,flag,pp,end,buf) \ (enc)->mbc_case_fold_se(it,flag,(OnigPosition* )pp,end,buf) #define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \ (enc)->is_allowed_reverse_match(s,end) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s) \ (enc)->left_adjust_char_head(start, s) #define ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it,enc,start,s) \ (enc)->left_adjust_char_head_se(it, start, s) #define ONIGENC_APPLY_ALL_CASE_FOLD(enc,case_fold_flag,f,arg) \ (enc)->apply_all_case_fold(case_fold_flag,f,arg) #define ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc,case_fold_flag,p,end,acs) \ (enc)->get_case_fold_codes_by_str(case_fold_flag,p,end,acs) #define ONIGENC_STEP_BACK(enc,start,s,n) \ onigenc_step_back((enc),(start),(s),(n)) #define ONIGENC_STEP_BACK_SE(it,enc,start,s,n) \ onigenc_step_back_se((it),(enc),(start),(s),(n)) #define ONIGENC_MBC_ENC_LEN(enc,p) (enc)->mbc_enc_len(p) #define ONIGENC_MBC_ENC_LEN_SE(it,enc,p) (enc)->mbc_enc_len_se((it),(p)) #define ONIGENC_MBC_MAXLEN(enc) ((enc)->max_enc_len) #define ONIGENC_MBC_MAXLEN_DIST(enc) ONIGENC_MBC_MAXLEN(enc) #define ONIGENC_MBC_MINLEN(enc) ((enc)->min_enc_len) #define ONIGENC_IS_MBC_NEWLINE(enc,p,end) (enc)->is_mbc_newline((p),(end)) #define ONIGENC_IS_MBC_NEWLINE_SE(it,enc,p,end) (enc)->is_mbc_newline_se((it),(p),(end)) #define ONIGENC_MBC_TO_CODE(enc,p,end) (enc)->mbc_to_code((p),(end)) #define ONIGENC_MBC_TO_CODE_SE(it,enc,p,end) (enc)->mbc_to_code_se((it),(p),(end)) #define ONIGENC_CODE_TO_MBCLEN(enc,code) (enc)->code_to_mbclen(code) #define ONIGENC_CODE_TO_MBC(enc,code,buf) (enc)->code_to_mbc(code,buf) #define ONIGENC_PROPERTY_NAME_TO_CTYPE(enc,p,end) \ (enc)->property_name_to_ctype(enc,p,end) #define ONIGENC_IS_CODE_CTYPE(enc,code,ctype) (enc)->is_code_ctype(code,ctype) #define ONIGENC_IS_CODE_NEWLINE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_NEWLINE) #define ONIGENC_IS_CODE_GRAPH(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_GRAPH) #define ONIGENC_IS_CODE_PRINT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PRINT) #define ONIGENC_IS_CODE_ALNUM(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALNUM) #define ONIGENC_IS_CODE_ALPHA(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_ALPHA) #define ONIGENC_IS_CODE_LOWER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_LOWER) #define ONIGENC_IS_CODE_UPPER(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_UPPER) #define ONIGENC_IS_CODE_CNTRL(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_CNTRL) #define ONIGENC_IS_CODE_PUNCT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_PUNCT) #define ONIGENC_IS_CODE_SPACE(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_SPACE) #define ONIGENC_IS_CODE_BLANK(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_BLANK) #define ONIGENC_IS_CODE_DIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_DIGIT) #define ONIGENC_IS_CODE_XDIGIT(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_XDIGIT) #define ONIGENC_IS_CODE_WORD(enc,code) \ ONIGENC_IS_CODE_CTYPE(enc,code,ONIGENC_CTYPE_WORD) #define ONIGENC_GET_CTYPE_CODE_RANGE(enc,ctype,sbout,ranges) \ (enc)->get_ctype_code_range(ctype,sbout,ranges) ONIG_EXTERN OnigUChar* onigenc_step_back P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, int n)); ONIG_EXTERN OnigPosition onigenc_step_back_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s, int n)); /* encoding API */ ONIG_EXTERN int onigenc_init P_((void)); ONIG_EXTERN int onigenc_set_default_encoding P_((OnigEncoding enc)); ONIG_EXTERN OnigEncoding onigenc_get_default_encoding P_((void)); ONIG_EXTERN void onigenc_set_default_caseconv_table P_((const OnigUChar* table)); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar** prev)); ONIG_EXTERN OnigPosition onigenc_get_right_adjust_char_head_with_prev_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s, OnigPosition* prev)); ONIG_EXTERN OnigUChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s)); ONIG_EXTERN OnigPosition onigenc_get_prev_char_head_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s)); ONIG_EXTERN OnigUChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s)); ONIG_EXTERN OnigPosition onigenc_get_left_adjust_char_head_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s)); ONIG_EXTERN OnigUChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s)); ONIG_EXTERN OnigPosition onigenc_get_right_adjust_char_head_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s)); ONIG_EXTERN int onigenc_strlen P_((OnigEncoding enc, const OnigUChar* p, const OnigUChar* end)); ONIG_EXTERN int onigenc_strlen_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition p, OnigPosition end)); ONIG_EXTERN int onigenc_strlen_null P_((OnigEncoding enc, const OnigUChar* p)); ONIG_EXTERN int onigenc_str_bytelen_null P_((OnigEncoding enc, const OnigUChar* p)); ONIG_EXTERN OnigPosition onigenc_str_bytelen_null_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition p)); /* PART: regular expression */ /* config parameters */ #define ONIG_NREGION 10 #define ONIG_MAX_BACKREF_NUM 1000 #define ONIG_MAX_REPEAT_NUM 100000 #define ONIG_MAX_MULTI_BYTE_RANGES_NUM 10000 /* constants */ #define ONIG_MAX_ERROR_MESSAGE_LEN 90 typedef unsigned int OnigOptionType; #define ONIG_OPTION_DEFAULT ONIG_OPTION_NONE /* options */ #define ONIG_OPTION_NONE 0U #define ONIG_OPTION_IGNORECASE 1U #define ONIG_OPTION_EXTEND (ONIG_OPTION_IGNORECASE << 1) #define ONIG_OPTION_MULTILINE (ONIG_OPTION_EXTEND << 1) #define ONIG_OPTION_DOTALL ONIG_OPTION_MULTILINE #define ONIG_OPTION_SINGLELINE (ONIG_OPTION_MULTILINE << 1) #define ONIG_OPTION_FIND_LONGEST (ONIG_OPTION_SINGLELINE << 1) #define ONIG_OPTION_FIND_NOT_EMPTY (ONIG_OPTION_FIND_LONGEST << 1) #define ONIG_OPTION_NEGATE_SINGLELINE (ONIG_OPTION_FIND_NOT_EMPTY << 1) #define ONIG_OPTION_DONT_CAPTURE_GROUP (ONIG_OPTION_NEGATE_SINGLELINE << 1) #define ONIG_OPTION_CAPTURE_GROUP (ONIG_OPTION_DONT_CAPTURE_GROUP << 1) /* options (search time) */ #define ONIG_OPTION_NOTBOL (ONIG_OPTION_CAPTURE_GROUP << 1) #define ONIG_OPTION_NOTEOL (ONIG_OPTION_NOTBOL << 1) #define ONIG_OPTION_POSIX_REGION (ONIG_OPTION_NOTEOL << 1) /* options (ctype range) */ #define ONIG_OPTION_ASCII_RANGE (ONIG_OPTION_POSIX_REGION << 1) #define ONIG_OPTION_POSIX_BRACKET_ALL_RANGE (ONIG_OPTION_ASCII_RANGE << 1) #define ONIG_OPTION_WORD_BOUND_ALL_RANGE (ONIG_OPTION_POSIX_BRACKET_ALL_RANGE << 1) /* options (newline) */ #define ONIG_OPTION_NEWLINE_CRLF (ONIG_OPTION_WORD_BOUND_ALL_RANGE << 1) // options (whole word) #define SE_ONIG_OPTION_WHOLEWORD (ONIG_OPTION_NEWLINE_CRLF << 1) #define ONIG_OPTION_MAXBIT SE_ONIG_OPTION_WHOLEWORD /* limit */ #define ONIG_OPTION_ON(options,regopt) ((options) |= (regopt)) #define ONIG_OPTION_OFF(options,regopt) ((options) &= ~(regopt)) #define ONIG_IS_OPTION_ON(options,option) ((options) & (option)) /* syntax */ typedef struct { unsigned int op; unsigned int op2; unsigned int behavior; OnigOptionType options; /* default option */ OnigMetaCharTableType meta_char_table; } OnigSyntaxType; ONIG_EXTERN OnigSyntaxType OnigSyntaxASIS; ONIG_EXTERN OnigSyntaxType OnigSyntaxWildChar; ONIG_EXTERN OnigSyntaxType OnigSyntaxPosixBasic; ONIG_EXTERN OnigSyntaxType OnigSyntaxPosixExtended; ONIG_EXTERN OnigSyntaxType OnigSyntaxEmacs; ONIG_EXTERN OnigSyntaxType OnigSyntaxGrep; ONIG_EXTERN OnigSyntaxType OnigSyntaxGnuRegex; ONIG_EXTERN OnigSyntaxType OnigSyntaxJava; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl58; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl58_NG; ONIG_EXTERN OnigSyntaxType OnigSyntaxPerl; ONIG_EXTERN OnigSyntaxType OnigSyntaxRuby; ONIG_EXTERN OnigSyntaxType OnigSyntaxPython; /* predefined syntaxes (see regsyntax.c) */ #define ONIG_SYNTAX_ASIS (&OnigSyntaxASIS) #define ONIG_SYNTAX_WILDCHAR (&OnigSyntaxWildChar) #define ONIG_SYNTAX_POSIX_BASIC (&OnigSyntaxPosixBasic) #define ONIG_SYNTAX_POSIX_EXTENDED (&OnigSyntaxPosixExtended) #define ONIG_SYNTAX_EMACS (&OnigSyntaxEmacs) #define ONIG_SYNTAX_GREP (&OnigSyntaxGrep) #define ONIG_SYNTAX_GNU_REGEX (&OnigSyntaxGnuRegex) #define ONIG_SYNTAX_JAVA (&OnigSyntaxJava) #define ONIG_SYNTAX_PERL58 (&OnigSyntaxPerl58) #define ONIG_SYNTAX_PERL58_NG (&OnigSyntaxPerl58_NG) #define ONIG_SYNTAX_PERL (&OnigSyntaxPerl) #define ONIG_SYNTAX_RUBY (&OnigSyntaxRuby) #define ONIG_SYNTAX_PYTHON (&OnigSyntaxPython) /* default syntax */ ONIG_EXTERN OnigSyntaxType* OnigDefaultSyntax; #define ONIG_SYNTAX_DEFAULT OnigDefaultSyntax /* syntax (operators) */ #define ONIG_SYN_OP_VARIABLE_META_CHARACTERS (1U<<0) #define ONIG_SYN_OP_DOT_ANYCHAR (1U<<1) /* . */ #define ONIG_SYN_OP_ASTERISK_ZERO_INF (1U<<2) /* * */ #define ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF (1U<<3) #define ONIG_SYN_OP_PLUS_ONE_INF (1U<<4) /* + */ #define ONIG_SYN_OP_ESC_PLUS_ONE_INF (1U<<5) #define ONIG_SYN_OP_QMARK_ZERO_ONE (1U<<6) /* ? */ #define ONIG_SYN_OP_ESC_QMARK_ZERO_ONE (1U<<7) #define ONIG_SYN_OP_BRACE_INTERVAL (1U<<8) /* {lower,upper} */ #define ONIG_SYN_OP_ESC_BRACE_INTERVAL (1U<<9) /* \{lower,upper\} */ #define ONIG_SYN_OP_VBAR_ALT (1U<<10) /* | */ #define ONIG_SYN_OP_ESC_VBAR_ALT (1U<<11) /* \| */ #define ONIG_SYN_OP_LPAREN_SUBEXP (1U<<12) /* (...) */ #define ONIG_SYN_OP_ESC_LPAREN_SUBEXP (1U<<13) /* \(...\) */ #define ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR (1U<<14) /* \A, \Z, \z */ #define ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR (1U<<15) /* \G */ #define ONIG_SYN_OP_DECIMAL_BACKREF (1U<<16) /* \num */ #define ONIG_SYN_OP_BRACKET_CC (1U<<17) /* [...] */ #define ONIG_SYN_OP_ESC_W_WORD (1U<<18) /* \w, \W */ #define ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END (1U<<19) /* \<. \> */ #define ONIG_SYN_OP_ESC_B_WORD_BOUND (1U<<20) /* \b, \B */ #define ONIG_SYN_OP_ESC_S_WHITE_SPACE (1U<<21) /* \s, \S */ #define ONIG_SYN_OP_ESC_D_DIGIT (1U<<22) /* \d, \D */ #define ONIG_SYN_OP_LINE_ANCHOR (1U<<23) /* ^, $ */ #define ONIG_SYN_OP_POSIX_BRACKET (1U<<24) /* [:xxxx:] */ #define ONIG_SYN_OP_QMARK_NON_GREEDY (1U<<25) /* ??,*?,+?,{n,m}? */ #define ONIG_SYN_OP_ESC_CONTROL_CHARS (1U<<26) /* \n,\r,\t,\a ... */ #define ONIG_SYN_OP_ESC_C_CONTROL (1U<<27) /* \cx */ #define ONIG_SYN_OP_ESC_OCTAL3 (1U<<28) /* \OOO */ #define ONIG_SYN_OP_ESC_X_HEX2 (1U<<29) /* \xHH */ #define ONIG_SYN_OP_ESC_X_BRACE_HEX8 (1U<<30) /* \x{7HHHHHHH} */ #define ONIG_SYN_OP_ESC_O_BRACE_OCTAL (1U<<31) /* \o{OOO} */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE (1U<<0) /* \Q...\E */ #define ONIG_SYN_OP2_QMARK_GROUP_EFFECT (1U<<1) /* (?...) */ #define ONIG_SYN_OP2_OPTION_PERL (1U<<2) /* (?imsxadlu), (?-imsx), (?^imsxalu) */ #define ONIG_SYN_OP2_OPTION_RUBY (1U<<3) /* (?imxadu), (?-imx) */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT (1U<<4) /* ?+,*+,++ */ #define ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL (1U<<5) /* {n,m}+ */ #define ONIG_SYN_OP2_CCLASS_SET_OP (1U<<6) /* [...&&..[..]..] */ #define ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP (1U<<7) /* (?...) */ #define ONIG_SYN_OP2_ESC_K_NAMED_BACKREF (1U<<8) /* \k */ #define ONIG_SYN_OP2_ESC_G_SUBEXP_CALL (1U<<9) /* \g, \g */ #define ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY (1U<<10) /* (?@..),(?@..) */ #define ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL (1U<<11) /* \C-x */ #define ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META (1U<<12) /* \M-x */ #define ONIG_SYN_OP2_ESC_V_VTAB (1U<<13) /* \v as VTAB */ #define ONIG_SYN_OP2_ESC_U_HEX4 (1U<<14) /* \uHHHH */ #define ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR (1U<<15) /* \`, \' */ #define ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY (1U<<16) /* \p{...}, \P{...} */ #define ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT (1U<<17) /* \p{^..}, \P{^..} */ /* #define ONIG_SYN_OP2_CHAR_PROPERTY_PREFIX_IS (1U<<18) */ #define ONIG_SYN_OP2_ESC_H_XDIGIT (1U<<19) /* \h, \H */ #define ONIG_SYN_OP2_INEFFECTIVE_ESCAPE (1U<<20) /* \ */ #define ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK (1U<<21) /* \R as (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) */ #define ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER (1U<<22) /* \X as (?>\P{M}\p{M}*) */ #define ONIG_SYN_OP2_ESC_V_VERTICAL_WHITESPACE (1U<<23) /* \v, \V -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_H_HORIZONTAL_WHITESPACE (1U<<24) /* \h, \H -- Perl */ /* NOTIMPL */ #define ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP (1U<<25) /* \K */ #define ONIG_SYN_OP2_ESC_G_BRACE_BACKREF (1U<<26) /* \g{name}, \g{n} */ #define ONIG_SYN_OP2_QMARK_SUBEXP_CALL (1U<<27) /* (?&name), (?n), (?R), (?0) */ #define ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET (1U<<28) /* (?|...) */ /* NOTIMPL */ #define ONIG_SYN_OP2_QMARK_LPAREN_CONDITION (1U<<29) /* (?(cond)yes...|no...) */ #define ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP (1U<<30) /* (?P...), (?P=name), (?P>name) -- Python/PCRE */ #define ONIG_SYN_OP2_OPTION_JAVA (1U<<31) /* (?idmsux), (?-idmsux) */ /* NOTIMPL */ /* syntax (behavior) */ #define ONIG_SYN_CONTEXT_INDEP_ANCHORS (1U<<31) /* not implemented */ #define ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS (1U<<0) /* ?, *, +, {n,m} */ #define ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS (1U<<1) /* error or ignore */ #define ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP (1U<<2) /* ...)... */ #define ONIG_SYN_ALLOW_INVALID_INTERVAL (1U<<3) /* {??? */ #define ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV (1U<<4) /* {,n} => {0,n} */ #define ONIG_SYN_STRICT_CHECK_BACKREF (1U<<5) /* /(\1)/,/\1()/ ..*/ #define ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND (1U<<6) /* (?<=a|bc) */ #define ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP (1U<<7) /* see doc/RE */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME (1U<<8) /* (?)(?) */ #define ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY (1U<<9) /* a{n}?=(?:a{n})? */ #define ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL (1U<<10) /* (?)(?)(?&x) */ /* syntax (behavior) in char class [...] */ #define ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC (1U<<20) /* [^...] */ #define ONIG_SYN_BACKSLASH_ESCAPE_IN_CC (1U<<21) /* [..\w..] etc.. */ #define ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC (1U<<22) #define ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC (1U<<23) /* [0-9-a]=[0-9\-a] */ /* syntax (behavior) warning */ #define ONIG_SYN_WARN_CC_OP_NOT_ESCAPED (1U<<24) /* [,-,] */ #define ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT (1U<<25) /* (?:a*)+ */ /* meta character specifiers (onig_set_meta_char()) */ #define ONIG_META_CHAR_ESCAPE 0 #define ONIG_META_CHAR_ANYCHAR 1 #define ONIG_META_CHAR_ANYTIME 2 #define ONIG_META_CHAR_ZERO_OR_ONE_TIME 3 #define ONIG_META_CHAR_ONE_OR_MORE_TIME 4 #define ONIG_META_CHAR_ANYCHAR_ANYTIME 5 #define ONIG_INEFFECTIVE_META_CHAR 0 /* error codes */ #define ONIG_IS_PATTERN_ERROR(ecode) ((ecode) <= -100 && (ecode) > -1000) /* normal return */ #define ONIG_NORMAL 0 #define ONIG_MISMATCH -1 #define ONIG_NO_SUPPORT_CONFIG -2 /* internal error */ #define ONIGERR_MEMORY -5 #define ONIGERR_TYPE_BUG -6 #define ONIGERR_PARSER_BUG -11 #define ONIGERR_STACK_BUG -12 #define ONIGERR_UNDEFINED_BYTECODE -13 #define ONIGERR_UNEXPECTED_BYTECODE -14 #define ONIGERR_MATCH_STACK_LIMIT_OVER -15 #define ONIGERR_DEFAULT_ENCODING_IS_NOT_SET -21 #define ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR -22 /* general error */ #define ONIGERR_INVALID_ARGUMENT -30 /* syntax error */ #define ONIGERR_END_PATTERN_AT_LEFT_BRACE -100 #define ONIGERR_END_PATTERN_AT_LEFT_BRACKET -101 #define ONIGERR_EMPTY_CHAR_CLASS -102 #define ONIGERR_PREMATURE_END_OF_CHAR_CLASS -103 #define ONIGERR_END_PATTERN_AT_ESCAPE -104 #define ONIGERR_END_PATTERN_AT_META -105 #define ONIGERR_END_PATTERN_AT_CONTROL -106 #define ONIGERR_META_CODE_SYNTAX -108 #define ONIGERR_CONTROL_CODE_SYNTAX -109 #define ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE -110 #define ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE -111 #define ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS -112 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED -113 #define ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID -114 #define ONIGERR_NESTED_REPEAT_OPERATOR -115 #define ONIGERR_UNMATCHED_CLOSE_PARENTHESIS -116 #define ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS -117 #define ONIGERR_END_PATTERN_IN_GROUP -118 #define ONIGERR_UNDEFINED_GROUP_OPTION -119 #define ONIGERR_INVALID_POSIX_BRACKET_TYPE -121 #define ONIGERR_INVALID_LOOK_BEHIND_PATTERN -122 #define ONIGERR_INVALID_REPEAT_RANGE_PATTERN -123 #define ONIGERR_INVALID_CONDITION_PATTERN -124 /* values error (syntax error) */ #define ONIGERR_TOO_BIG_NUMBER -200 #define ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE -201 #define ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE -202 #define ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS -203 #define ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE -204 #define ONIGERR_TOO_MANY_MULTI_BYTE_RANGES -205 #define ONIGERR_TOO_SHORT_MULTI_BYTE_STRING -206 #define ONIGERR_TOO_BIG_BACKREF_NUMBER -207 #define ONIGERR_INVALID_BACKREF -208 #define ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED -209 #define ONIGERR_TOO_SHORT_DIGITS -210 #define ONIGERR_TOO_LONG_WIDE_CHAR_VALUE -212 #define ONIGERR_EMPTY_GROUP_NAME -214 #define ONIGERR_INVALID_GROUP_NAME -215 #define ONIGERR_INVALID_CHAR_IN_GROUP_NAME -216 #define ONIGERR_UNDEFINED_NAME_REFERENCE -217 #define ONIGERR_UNDEFINED_GROUP_REFERENCE -218 #define ONIGERR_MULTIPLEX_DEFINED_NAME -219 #define ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL -220 #define ONIGERR_NEVER_ENDING_RECURSION -221 #define ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY -222 #define ONIGERR_INVALID_CHAR_PROPERTY_NAME -223 #define ONIGERR_INVALID_CODE_POINT_VALUE -400 #define ONIGERR_INVALID_WIDE_CHAR_VALUE -400 #define ONIGERR_TOO_BIG_WIDE_CHAR_VALUE -401 #define ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION -402 #define ONIGERR_INVALID_COMBINATION_OF_OPTIONS -403 /* errors related to thread */ #define ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT -1001 /* must be smaller than BIT_STATUS_BITS_NUM (unsigned int * 8) */ #define ONIG_MAX_CAPTURE_HISTORY_GROUP 31 #define ONIG_IS_CAPTURE_HISTORY_GROUP(r, i) \ ((i) <= ONIG_MAX_CAPTURE_HISTORY_GROUP && (r)->list && (r)->list[i]) typedef struct OnigCaptureTreeNodeStruct { int group; /* group number */ OnigPosition beg; OnigPosition end; int allocated; int num_childs; struct OnigCaptureTreeNodeStruct** childs; } OnigCaptureTreeNode; /* match result region type */ struct re_registers { int allocated; int num_regs; OnigPosition* beg; OnigPosition* end; /* extended */ OnigCaptureTreeNode* history_root; /* capture history tree root */ }; /* capture tree traverse */ #define ONIG_TRAVERSE_CALLBACK_AT_FIRST 1 #define ONIG_TRAVERSE_CALLBACK_AT_LAST 2 #define ONIG_TRAVERSE_CALLBACK_AT_BOTH \ ( ONIG_TRAVERSE_CALLBACK_AT_FIRST | ONIG_TRAVERSE_CALLBACK_AT_LAST ) #define ONIG_REGION_NOTPOS -1 typedef struct re_registers OnigRegion; typedef struct { OnigEncoding enc; OnigUChar* par; OnigUChar* par_end; } OnigErrorInfo; typedef struct { int lower; int upper; } OnigRepeatRange; typedef void (*OnigWarnFunc) P_((const char* s)); extern void onig_null_warn P_((const char* s)); #define ONIG_NULL_WARN onig_null_warn #define ONIG_CHAR_TABLE_SIZE 256 /* regex_t state */ #define ONIG_STATE_NORMAL 0 #define ONIG_STATE_SEARCHING 1 #define ONIG_STATE_COMPILING -1 #define ONIG_STATE_MODIFY -2 #define ONIG_STATE(reg) \ ((reg)->state > 0 ? ONIG_STATE_SEARCHING : (reg)->state) typedef struct re_pattern_buffer { /* common members of BBuf(bytes-buffer) */ unsigned char* p; /* compiled pattern */ unsigned int used; /* used space for p */ unsigned int alloc; /* allocated space for p */ int state; /* normal, searching, compiling */ int num_mem; /* used memory(...) num counted from 1 */ int num_repeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */ int num_null_check; /* OP_NULL_CHECK_START/END id counter */ int num_comb_exp_check; /* combination explosion check */ int num_call; /* number of subexp call */ unsigned int capture_history; /* (?@...) flag (1-31) */ unsigned int bt_mem_start; /* need backtrack flag */ unsigned int bt_mem_end; /* need backtrack flag */ int stack_pop_level; int repeat_range_alloc; OnigRepeatRange* repeat_range; OnigEncoding enc; OnigOptionType options; OnigSyntaxType* syntax; OnigCaseFoldType case_fold_flag; void* name_table; /* optimization info (string search, char-map and anchors) */ int optimize; /* optimize flag */ int threshold_len; /* search str-length for apply optimize */ int anchor; /* BEGIN_BUF, BEGIN_POS, (SEMI_)END_BUF */ OnigDistance anchor_dmin; /* (SEMI_)END_BUF anchor distance */ OnigDistance anchor_dmax; /* (SEMI_)END_BUF anchor distance */ int sub_anchor; /* start-anchor for exact or map */ unsigned char *exact; unsigned char *exact_end; unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */ int *int_map; /* BM skip for exact_len > 255 */ int *int_map_backward; /* BM skip for backward search */ OnigDistance dmin; /* min-distance of exact or map */ OnigDistance dmax; /* max-distance of exact or map */ /* regex_t link chain */ struct re_pattern_buffer* chain; /* escape compile-conflict */ } OnigRegexType; typedef OnigRegexType* OnigRegex; #ifndef ONIG_ESCAPE_REGEX_T_COLLISION typedef OnigRegexType regex_t; #endif typedef struct { int num_of_elements; OnigEncoding pattern_enc; OnigEncoding target_enc; OnigSyntaxType* syntax; OnigOptionType option; OnigCaseFoldType case_fold_flag; } OnigCompileInfo; /* Oniguruma Native API */ ONIG_EXTERN int onig_init P_((void)); ONIG_EXTERN int onig_error_code_to_str PV_((OnigUChar* s, OnigPosition err_code, ...)); ONIG_EXTERN void onig_set_warn_func P_((OnigWarnFunc f)); ONIG_EXTERN void onig_set_verb_warn_func P_((OnigWarnFunc f)); ONIG_EXTERN int onig_new P_((OnigRegex*, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); ONIG_EXTERN int onig_reg_init P_((OnigRegex reg, OnigOptionType option, OnigCaseFoldType case_fold_flag, OnigEncoding enc, OnigSyntaxType* syntax)); ONIG_EXTERN int onig_new_without_alloc P_((OnigRegex, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); ONIG_EXTERN int onig_new_deluxe P_((OnigRegex* reg, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo)); ONIG_EXTERN void onig_free P_((OnigRegex)); ONIG_EXTERN void onig_free_body P_((OnigRegex)); ONIG_EXTERN int onig_recompile P_((OnigRegex, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo)); ONIG_EXTERN int onig_recompile_deluxe P_((OnigRegex reg, const OnigUChar* pattern, const OnigUChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo)); ONIG_EXTERN OnigPosition onig_search P_((OnigIterator* it, OnigRegex, OnigPosition str, OnigPosition end, OnigPosition start, OnigPosition range, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN OnigPosition onig_search_gpos P_((OnigIterator* it, OnigRegex, OnigPosition str, OnigPosition end, OnigPosition global_pos, OnigPosition start, OnigPosition range, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN OnigPosition onig_match P_((OnigIterator* it, OnigRegex, OnigPosition str, OnigPosition end, OnigPosition at, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN OnigPosition onig_match_gpos P_((OnigIterator* it, OnigRegex, OnigPosition str, OnigPosition end, OnigPosition global_pos, OnigPosition at, OnigRegion* region, OnigOptionType option)); ONIG_EXTERN OnigRegion* onig_region_new P_((void)); ONIG_EXTERN void onig_region_init P_((OnigRegion* region)); ONIG_EXTERN void onig_region_free P_((OnigRegion* region, int free_self)); ONIG_EXTERN void onig_region_copy P_((OnigRegion* to, OnigRegion* from)); ONIG_EXTERN void onig_region_clear P_((OnigRegion* region)); ONIG_EXTERN int onig_region_resize P_((OnigRegion* region, int n)); ONIG_EXTERN int onig_region_set P_((OnigRegion* region, int at, int beg, int end)); ONIG_EXTERN int onig_name_to_group_numbers P_((OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, int** nums)); ONIG_EXTERN int onig_name_to_backref_number P_((OnigRegex reg, const OnigUChar* name, const OnigUChar* name_end, OnigRegion *region)); ONIG_EXTERN int onig_foreach_name P_((OnigRegex reg, int (*func)(const OnigUChar*, const OnigUChar*,int,int*,OnigRegex,void*), void* arg)); ONIG_EXTERN int onig_number_of_names P_((OnigRegex reg)); ONIG_EXTERN int onig_number_of_captures P_((OnigRegex reg)); ONIG_EXTERN int onig_number_of_capture_histories P_((OnigRegex reg)); ONIG_EXTERN OnigCaptureTreeNode* onig_get_capture_tree P_((OnigRegion* region)); ONIG_EXTERN int onig_capture_tree_traverse P_((OnigRegion* region, int at, int(*callback_func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg)); ONIG_EXTERN int onig_noname_group_capture_is_active P_((OnigRegex reg)); ONIG_EXTERN OnigEncoding onig_get_encoding P_((OnigRegex reg)); ONIG_EXTERN OnigOptionType onig_get_options P_((OnigRegex reg)); ONIG_EXTERN OnigCaseFoldType onig_get_case_fold_flag P_((OnigRegex reg)); ONIG_EXTERN OnigSyntaxType* onig_get_syntax P_((OnigRegex reg)); ONIG_EXTERN int onig_set_default_syntax P_((OnigSyntaxType* syntax)); ONIG_EXTERN void onig_copy_syntax P_((OnigSyntaxType* to, const OnigSyntaxType* from)); ONIG_EXTERN unsigned int onig_get_syntax_op P_((OnigSyntaxType* syntax)); ONIG_EXTERN unsigned int onig_get_syntax_op2 P_((OnigSyntaxType* syntax)); ONIG_EXTERN unsigned int onig_get_syntax_behavior P_((OnigSyntaxType* syntax)); ONIG_EXTERN OnigOptionType onig_get_syntax_options P_((OnigSyntaxType* syntax)); ONIG_EXTERN void onig_set_syntax_op P_((OnigSyntaxType* syntax, unsigned int op)); ONIG_EXTERN void onig_set_syntax_op2 P_((OnigSyntaxType* syntax, unsigned int op2)); ONIG_EXTERN void onig_set_syntax_behavior P_((OnigSyntaxType* syntax, unsigned int behavior)); ONIG_EXTERN void onig_set_syntax_options P_((OnigSyntaxType* syntax, OnigOptionType options)); ONIG_EXTERN int onig_set_meta_char P_((OnigSyntaxType* syntax, unsigned int what, OnigCodePoint code)); ONIG_EXTERN void onig_copy_encoding P_((OnigEncoding to, OnigEncoding from)); ONIG_EXTERN OnigCaseFoldType onig_get_default_case_fold_flag P_((void)); ONIG_EXTERN int onig_set_default_case_fold_flag P_((OnigCaseFoldType case_fold_flag)); ONIG_EXTERN unsigned int onig_get_match_stack_limit_size P_((void)); ONIG_EXTERN int onig_set_match_stack_limit_size P_((unsigned int size)); ONIG_EXTERN int onig_end P_((void)); ONIG_EXTERN const char* onig_version P_((void)); ONIG_EXTERN const char* onig_copyright P_((void)); #ifdef __cplusplus } #endif #endif /* ONIGURUMA_H */ ================================================ FILE: src/Onigmo/oniguruma.pc.in ================================================ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ datarootdir=@datarootdir@ datadir=@datadir@ Name: oniguruma Description: Regular expression library Version: @PACKAGE_VERSION@ Requires: Libs: -L${libdir} -lonig Cflags: -I${includedir} ================================================ FILE: src/Onigmo/regcomp.c ================================================ /********************************************************************** regcomp.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ #include "regparse.h" OnigCaseFoldType OnigDefaultCaseFoldFlag = ONIGENC_CASE_FOLD_MIN; extern OnigCaseFoldType onig_get_default_case_fold_flag(void) { return OnigDefaultCaseFoldFlag; } extern int onig_set_default_case_fold_flag(OnigCaseFoldType case_fold_flag) { OnigDefaultCaseFoldFlag = case_fold_flag; return 0; } #ifndef PLATFORM_UNALIGNED_WORD_ACCESS static unsigned char PadBuf[WORD_ALIGNMENT_SIZE]; #endif #if 0 static UChar* str_dup(UChar* s, UChar* end) { ptrdiff_t len = end - s; if (len > 0) { UChar* r = (UChar* )xmalloc(len + 1); CHECK_NULL_RETURN(r); xmemcpy(r, s, len); r[len] = (UChar )0; return r; } else return NULL; } #endif static void swap_node(Node* a, Node* b) { Node c; c = *a; *a = *b; *b = c; if (NTYPE(a) == NT_STR) { StrNode* sn = NSTR(a); if (sn->capa == 0) { size_t len = sn->end - sn->s; sn->s = sn->buf; sn->end = sn->s + len; } } if (NTYPE(b) == NT_STR) { StrNode* sn = NSTR(b); if (sn->capa == 0) { size_t len = sn->end - sn->s; sn->s = sn->buf; sn->end = sn->s + len; } } } static OnigDistance distance_add(OnigDistance d1, OnigDistance d2) { if (d1 == ONIG_INFINITE_DISTANCE || d2 == ONIG_INFINITE_DISTANCE) return ONIG_INFINITE_DISTANCE; else { if (d1 <= ONIG_INFINITE_DISTANCE - d2) return d1 + d2; else return ONIG_INFINITE_DISTANCE; } } static OnigDistance distance_multiply(OnigDistance d, int m) { if (m == 0) return 0; if (d < ONIG_INFINITE_DISTANCE / m) return d * m; else return ONIG_INFINITE_DISTANCE; } static int bitset_is_empty(BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { if (bs[i] != 0) return 0; } return 1; } #ifdef ONIG_DEBUG static int bitset_on_num(BitSetRef bs) { int i, n; n = 0; for (i = 0; i < SINGLE_BYTE_SIZE; i++) { if (BITSET_AT(bs, i)) n++; } return n; } #endif extern int onig_bbuf_init(BBuf* buf, OnigDistance size) { if (size <= 0) { size = 0; buf->p = NULL; } else { buf->p = (UChar* )xmalloc(size); if (IS_NULL(buf->p)) return(ONIGERR_MEMORY); } buf->alloc = (unsigned int )size; buf->used = 0; return 0; } #ifdef USE_SUBEXP_CALL static int unset_addr_list_init(UnsetAddrList* uslist, int size) { UnsetAddr* p; p = (UnsetAddr* )xmalloc(sizeof(UnsetAddr)* size); CHECK_NULL_RETURN_MEMERR(p); uslist->num = 0; uslist->alloc = size; uslist->us = p; return 0; } static void unset_addr_list_end(UnsetAddrList* uslist) { if (IS_NOT_NULL(uslist->us)) xfree(uslist->us); } static int unset_addr_list_add(UnsetAddrList* uslist, int offset, struct _Node* node) { UnsetAddr* p; int size; if (uslist->num >= uslist->alloc) { size = uslist->alloc * 2; p = (UnsetAddr* )xrealloc(uslist->us, sizeof(UnsetAddr) * size); CHECK_NULL_RETURN_MEMERR(p); uslist->alloc = size; uslist->us = p; } uslist->us[uslist->num].offset = offset; uslist->us[uslist->num].target = node; uslist->num++; return 0; } #endif /* USE_SUBEXP_CALL */ static int add_opcode(regex_t* reg, int opcode) { BBUF_ADD1(reg, opcode); return 0; } #ifdef USE_COMBINATION_EXPLOSION_CHECK static int add_state_check_num(regex_t* reg, int num) { StateCheckNumType n = (StateCheckNumType )num; BBUF_ADD(reg, &n, SIZE_STATE_CHECK_NUM); return 0; } #endif static int add_rel_addr(regex_t* reg, int addr) { RelAddrType ra = (RelAddrType )addr; BBUF_ADD(reg, &ra, SIZE_RELADDR); return 0; } static int add_abs_addr(regex_t* reg, int addr) { AbsAddrType ra = (AbsAddrType )addr; BBUF_ADD(reg, &ra, SIZE_ABSADDR); return 0; } static int add_length(regex_t* reg, OnigDistance len) { LengthType l = (LengthType )len; BBUF_ADD(reg, &l, SIZE_LENGTH); return 0; } static int add_mem_num(regex_t* reg, int num) { MemNumType n = (MemNumType )num; BBUF_ADD(reg, &n, SIZE_MEMNUM); return 0; } static int add_pointer(regex_t* reg, void* addr) { PointerType ptr = (PointerType )addr; BBUF_ADD(reg, &ptr, SIZE_POINTER); return 0; } static int add_option(regex_t* reg, OnigOptionType option) { BBUF_ADD(reg, &option, SIZE_OPTION); return 0; } static int add_opcode_rel_addr(regex_t* reg, int opcode, int addr) { int r; r = add_opcode(reg, opcode); if (r) return r; r = add_rel_addr(reg, addr); return r; } static int add_bytes(regex_t* reg, UChar* bytes, OnigDistance len) { BBUF_ADD(reg, bytes, len); return 0; } static int add_bitset(regex_t* reg, BitSetRef bs) { BBUF_ADD(reg, bs, SIZE_BITSET); return 0; } static int add_opcode_option(regex_t* reg, int opcode, OnigOptionType option) { int r; r = add_opcode(reg, opcode); if (r) return r; r = add_option(reg, option); return r; } static int compile_length_tree(Node* node, regex_t* reg); static int compile_tree(Node* node, regex_t* reg); #define IS_NEED_STR_LEN_OP_EXACT(op) \ ((op) == OP_EXACTN || (op) == OP_EXACTMB2N ||\ (op) == OP_EXACTMB3N || (op) == OP_EXACTMBN || (op) == OP_EXACTN_IC) static int select_str_opcode(int mb_len, OnigDistance str_len, int ignore_case) { int op; if (ignore_case) { switch (str_len) { case 1: op = OP_EXACT1_IC; break; default: op = OP_EXACTN_IC; break; } } else { switch (mb_len) { case 1: switch (str_len) { case 1: op = OP_EXACT1; break; case 2: op = OP_EXACT2; break; case 3: op = OP_EXACT3; break; case 4: op = OP_EXACT4; break; case 5: op = OP_EXACT5; break; default: op = OP_EXACTN; break; } break; case 2: switch (str_len) { case 1: op = OP_EXACTMB2N1; break; case 2: op = OP_EXACTMB2N2; break; case 3: op = OP_EXACTMB2N3; break; default: op = OP_EXACTMB2N; break; } break; case 3: op = OP_EXACTMB3N; break; default: op = OP_EXACTMBN; break; } } return op; } static int compile_tree_empty_check(Node* node, regex_t* reg, int empty_info) { int r; int saved_num_null_check = reg->num_null_check; if (empty_info != 0) { r = add_opcode(reg, OP_NULL_CHECK_START); if (r) return r; r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */ if (r) return r; reg->num_null_check++; } r = compile_tree(node, reg); if (r) return r; if (empty_info != 0) { if (empty_info == NQ_TARGET_IS_EMPTY) r = add_opcode(reg, OP_NULL_CHECK_END); else if (empty_info == NQ_TARGET_IS_EMPTY_MEM) r = add_opcode(reg, OP_NULL_CHECK_END_MEMST); else if (empty_info == NQ_TARGET_IS_EMPTY_REC) r = add_opcode(reg, OP_NULL_CHECK_END_MEMST_PUSH); if (r) return r; r = add_mem_num(reg, saved_num_null_check); /* NULL CHECK ID */ } return r; } #ifdef USE_SUBEXP_CALL static int compile_call(CallNode* node, regex_t* reg) { int r; r = add_opcode(reg, OP_CALL); if (r) return r; r = unset_addr_list_add(node->unset_addr_list, BBUF_GET_OFFSET_POS(reg), node->target); if (r) return r; r = add_abs_addr(reg, 0 /*dummy addr.*/); return r; } #endif static int compile_tree_n_times(Node* node, int n, regex_t* reg) { int i, r; for (i = 0; i < n; i++) { r = compile_tree(node, reg); if (r) return r; } return 0; } static int add_compile_string_length(UChar* s ARG_UNUSED, int mb_len, OnigDistance str_len, regex_t* reg ARG_UNUSED, int ignore_case) { int len; int op = select_str_opcode(mb_len, str_len, ignore_case); len = SIZE_OPCODE; if (op == OP_EXACTMBN) len += SIZE_LENGTH; if (IS_NEED_STR_LEN_OP_EXACT(op)) len += SIZE_LENGTH; len += mb_len * (int )str_len; return len; } static int add_compile_string(UChar* s, int mb_len, OnigDistance str_len, regex_t* reg, int ignore_case) { int op = select_str_opcode(mb_len, str_len, ignore_case); add_opcode(reg, op); if (op == OP_EXACTMBN) add_length(reg, mb_len); if (IS_NEED_STR_LEN_OP_EXACT(op)) { if (op == OP_EXACTN_IC) add_length(reg, mb_len * str_len); else add_length(reg, str_len); } add_bytes(reg, s, mb_len * str_len); return 0; } static int compile_length_string_node(Node* node, regex_t* reg) { int rlen, r, len, prev_len, slen, ambig; OnigEncoding enc = reg->enc; UChar *p, *prev; StrNode* sn; sn = NSTR(node); if (sn->end <= sn->s) return 0; ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; prev_len = enclen(enc, p); p += prev_len; slen = 1; rlen = 0; for (; p < sn->end; ) { len = enclen(enc, p); if (len == prev_len) { slen++; } else { r = add_compile_string_length(prev, prev_len, slen, reg, ambig); rlen += r; prev = p; slen = 1; prev_len = len; } p += len; } r = add_compile_string_length(prev, prev_len, slen, reg, ambig); rlen += r; return rlen; } static int compile_length_string_raw_node(StrNode* sn, regex_t* reg) { if (sn->end <= sn->s) return 0; return add_compile_string_length(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0); } static int compile_string_node(Node* node, regex_t* reg) { int r, len, prev_len, slen, ambig; OnigEncoding enc = reg->enc; UChar *p, *prev, *end; StrNode* sn; sn = NSTR(node); if (sn->end <= sn->s) return 0; end = sn->end; ambig = NSTRING_IS_AMBIG(node); p = prev = sn->s; prev_len = enclen(enc, p); p += prev_len; slen = 1; for (; p < end; ) { len = enclen(enc, p); if (len == prev_len) { slen++; } else { r = add_compile_string(prev, prev_len, slen, reg, ambig); if (r) return r; prev = p; slen = 1; prev_len = len; } p += len; } return add_compile_string(prev, prev_len, slen, reg, ambig); } static int compile_string_raw_node(StrNode* sn, regex_t* reg) { if (sn->end <= sn->s) return 0; return add_compile_string(sn->s, 1 /* sb */, sn->end - sn->s, reg, 0); } static int add_multi_byte_cclass(BBuf* mbuf, regex_t* reg) { #ifdef PLATFORM_UNALIGNED_WORD_ACCESS add_length(reg, mbuf->used); return add_bytes(reg, mbuf->p, mbuf->used); #else int r, pad_size; UChar* p = BBUF_GET_ADD_ADDRESS(reg) + SIZE_LENGTH; GET_ALIGNMENT_PAD_SIZE(p, pad_size); add_length(reg, mbuf->used + (WORD_ALIGNMENT_SIZE - 1)); if (pad_size != 0) add_bytes(reg, PadBuf, pad_size); r = add_bytes(reg, mbuf->p, mbuf->used); /* padding for return value from compile_length_cclass_node() to be fix. */ pad_size = (WORD_ALIGNMENT_SIZE - 1) - pad_size; if (pad_size != 0) add_bytes(reg, PadBuf, pad_size); return r; #endif } static int compile_length_cclass_node(CClassNode* cc, regex_t* reg) { int len; if (IS_NCCLASS_SHARE(cc)) { len = SIZE_OPCODE + SIZE_POINTER; return len; } if (IS_NULL(cc->mbuf)) { len = SIZE_OPCODE + SIZE_BITSET; } else { if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) { len = SIZE_OPCODE; } else { len = SIZE_OPCODE + SIZE_BITSET; } #ifdef PLATFORM_UNALIGNED_WORD_ACCESS len += SIZE_LENGTH + cc->mbuf->used; #else len += SIZE_LENGTH + cc->mbuf->used + (WORD_ALIGNMENT_SIZE - 1); #endif } return len; } static int compile_cclass_node(CClassNode* cc, regex_t* reg) { int r; if (IS_NCCLASS_SHARE(cc)) { add_opcode(reg, OP_CCLASS_NODE); r = add_pointer(reg, cc); return r; } if (IS_NULL(cc->mbuf)) { if (IS_NCCLASS_NOT(cc)) add_opcode(reg, OP_CCLASS_NOT); else add_opcode(reg, OP_CCLASS); r = add_bitset(reg, cc->bs); } else { if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) { if (IS_NCCLASS_NOT(cc)) add_opcode(reg, OP_CCLASS_MB_NOT); else add_opcode(reg, OP_CCLASS_MB); r = add_multi_byte_cclass(cc->mbuf, reg); } else { if (IS_NCCLASS_NOT(cc)) add_opcode(reg, OP_CCLASS_MIX_NOT); else add_opcode(reg, OP_CCLASS_MIX); r = add_bitset(reg, cc->bs); if (r) return r; r = add_multi_byte_cclass(cc->mbuf, reg); } } return r; } static int entry_repeat_range(regex_t* reg, int id, int lower, int upper) { #define REPEAT_RANGE_ALLOC 4 OnigRepeatRange* p; if (reg->repeat_range_alloc == 0) { p = (OnigRepeatRange* )xmalloc(sizeof(OnigRepeatRange) * REPEAT_RANGE_ALLOC); CHECK_NULL_RETURN_MEMERR(p); reg->repeat_range = p; reg->repeat_range_alloc = REPEAT_RANGE_ALLOC; } else if (reg->repeat_range_alloc <= id) { int n; n = reg->repeat_range_alloc + REPEAT_RANGE_ALLOC; p = (OnigRepeatRange* )xrealloc(reg->repeat_range, sizeof(OnigRepeatRange) * n); CHECK_NULL_RETURN_MEMERR(p); reg->repeat_range = p; reg->repeat_range_alloc = n; } else { p = reg->repeat_range; } p[id].lower = lower; p[id].upper = (IS_REPEAT_INFINITE(upper) ? 0x7fffffff : upper); return 0; } static int compile_range_repeat_node(QtfrNode* qn, int target_len, int empty_info, regex_t* reg) { int r; int num_repeat = reg->num_repeat; r = add_opcode(reg, qn->greedy ? OP_REPEAT : OP_REPEAT_NG); if (r) return r; r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */ reg->num_repeat++; if (r) return r; r = add_rel_addr(reg, target_len + SIZE_OP_REPEAT_INC); if (r) return r; r = entry_repeat_range(reg, num_repeat, qn->lower, qn->upper); if (r) return r; r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; if ( #ifdef USE_SUBEXP_CALL reg->num_call > 0 || #endif IS_QUANTIFIER_IN_REPEAT(qn)) { r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC_SG : OP_REPEAT_INC_NG_SG); } else { r = add_opcode(reg, qn->greedy ? OP_REPEAT_INC : OP_REPEAT_INC_NG); } if (r) return r; r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */ return r; } static int is_anychar_star_quantifier(QtfrNode* qn) { if (qn->greedy && IS_REPEAT_INFINITE(qn->upper) && NTYPE(qn->target) == NT_CANY) return 1; else return 0; } #define QUANTIFIER_EXPAND_LIMIT_SIZE 50 #define CKN_ON (ckn > 0) #ifdef USE_COMBINATION_EXPLOSION_CHECK static int compile_length_quantifier_node(QtfrNode* qn, regex_t* reg) { int len, mod_tlen, cklen; int ckn; int infinite = IS_REPEAT_INFINITE(qn->upper); int empty_info = qn->target_empty_info; int tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0); cklen = (CKN_ON ? SIZE_STATE_CHECK_NUM: 0); /* anychar repeat */ if (NTYPE(qn->target) == NT_CANY) { if (qn->greedy && infinite) { if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen; else return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen; } } if (empty_info != 0) mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END); else mod_tlen = tlen; if (infinite && qn->lower <= 1) { if (qn->greedy) { if (qn->lower == 1) len = SIZE_OP_JUMP; else len = 0; len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP; } else { if (qn->lower == 0) len = SIZE_OP_JUMP; else len = 0; len += mod_tlen + SIZE_OP_PUSH + cklen; } } else if (qn->upper == 0) { if (qn->is_refered != 0) /* /(?..){0}/ */ len = SIZE_OP_JUMP + tlen; else len = 0; } else if (qn->upper == 1 && qn->greedy) { if (qn->lower == 0) { if (CKN_ON) { len = SIZE_OP_STATE_CHECK_PUSH + tlen; } else { len = SIZE_OP_PUSH + tlen; } } else { len = tlen; } } else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */ len = SIZE_OP_PUSH + cklen + SIZE_OP_JUMP + tlen; } else { len = SIZE_OP_REPEAT_INC + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM; if (CKN_ON) len += SIZE_OP_STATE_CHECK; } return len; } static int compile_quantifier_node(QtfrNode* qn, regex_t* reg) { int r, mod_tlen; int ckn; int infinite = IS_REPEAT_INFINITE(qn->upper); int empty_info = qn->target_empty_info; int tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; ckn = ((reg->num_comb_exp_check > 0) ? qn->comb_exp_check_num : 0); if (is_anychar_star_quantifier(qn)) { r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) { if (IS_MULTILINE(reg->options)) r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT); else r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT); if (r) return r; if (CKN_ON) { r = add_state_check_num(reg, ckn); if (r) return r; } return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1); } else { if (IS_MULTILINE(reg->options)) { r = add_opcode(reg, (CKN_ON ? OP_STATE_CHECK_ANYCHAR_ML_STAR : OP_ANYCHAR_ML_STAR)); } else { r = add_opcode(reg, (CKN_ON ? OP_STATE_CHECK_ANYCHAR_STAR : OP_ANYCHAR_STAR)); } if (r) return r; if (CKN_ON) r = add_state_check_num(reg, ckn); return r; } } if (empty_info != 0) mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END); else mod_tlen = tlen; if (infinite && qn->lower <= 1) { if (qn->greedy) { if (qn->lower == 1) { r = add_opcode_rel_addr(reg, OP_JUMP, (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)); if (r) return r; } if (CKN_ON) { r = add_opcode(reg, OP_STATE_CHECK_PUSH); if (r) return r; r = add_state_check_num(reg, ckn); if (r) return r; r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP); } else { r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP); } if (r) return r; r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, -(mod_tlen + (int )SIZE_OP_JUMP + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH))); } else { if (qn->lower == 0) { r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen); if (r) return r; } r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; if (CKN_ON) { r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP); if (r) return r; r = add_state_check_num(reg, ckn); if (r) return r; r = add_rel_addr(reg, -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP)); } else r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH)); } } else if (qn->upper == 0) { if (qn->is_refered != 0) { /* /(?..){0}/ */ r = add_opcode_rel_addr(reg, OP_JUMP, tlen); if (r) return r; r = compile_tree(qn->target, reg); } else r = 0; } else if (qn->upper == 1 && qn->greedy) { if (qn->lower == 0) { if (CKN_ON) { r = add_opcode(reg, OP_STATE_CHECK_PUSH); if (r) return r; r = add_state_check_num(reg, ckn); if (r) return r; r = add_rel_addr(reg, tlen); } else { r = add_opcode_rel_addr(reg, OP_PUSH, tlen); } if (r) return r; } r = compile_tree(qn->target, reg); } else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */ if (CKN_ON) { r = add_opcode(reg, OP_STATE_CHECK_PUSH); if (r) return r; r = add_state_check_num(reg, ckn); if (r) return r; r = add_rel_addr(reg, SIZE_OP_JUMP); } else { r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP); } if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, tlen); if (r) return r; r = compile_tree(qn->target, reg); } else { r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg); if (CKN_ON) { if (r) return r; r = add_opcode(reg, OP_STATE_CHECK); if (r) return r; r = add_state_check_num(reg, ckn); } } return r; } #else /* USE_COMBINATION_EXPLOSION_CHECK */ static int compile_length_quantifier_node(QtfrNode* qn, regex_t* reg) { int len, mod_tlen; int infinite = IS_REPEAT_INFINITE(qn->upper); int empty_info = qn->target_empty_info; int tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; /* anychar repeat */ if (NTYPE(qn->target) == NT_CANY) { if (qn->greedy && infinite) { if (IS_NOT_NULL(qn->next_head_exact)) return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower; else return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower; } } if (empty_info != 0) mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END); else mod_tlen = tlen; if (infinite && (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) { if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) { len = SIZE_OP_JUMP; } else { len = tlen * qn->lower; } if (qn->greedy) { if (IS_NOT_NULL(qn->head_exact)) len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP; else if (IS_NOT_NULL(qn->next_head_exact)) len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP; else len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP; } else len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH; } else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?..){0}/ */ len = SIZE_OP_JUMP + tlen; } else if (!infinite && qn->greedy && (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper <= QUANTIFIER_EXPAND_LIMIT_SIZE)) { len = tlen * qn->lower; len += (SIZE_OP_PUSH + tlen) * (qn->upper - qn->lower); } else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */ len = SIZE_OP_PUSH + SIZE_OP_JUMP + tlen; } else { len = SIZE_OP_REPEAT_INC + mod_tlen + SIZE_OPCODE + SIZE_RELADDR + SIZE_MEMNUM; } return len; } static int compile_quantifier_node(QtfrNode* qn, regex_t* reg) { int i, r, mod_tlen; int infinite = IS_REPEAT_INFINITE(qn->upper); int empty_info = qn->target_empty_info; int tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; if (is_anychar_star_quantifier(qn)) { r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; if (IS_NOT_NULL(qn->next_head_exact)) { if (IS_MULTILINE(reg->options)) r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT); else r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT); if (r) return r; return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1); } else { if (IS_MULTILINE(reg->options)) return add_opcode(reg, OP_ANYCHAR_ML_STAR); else return add_opcode(reg, OP_ANYCHAR_STAR); } } if (empty_info != 0) mod_tlen = tlen + (SIZE_OP_NULL_CHECK_START + SIZE_OP_NULL_CHECK_END); else mod_tlen = tlen; if (infinite && (qn->lower <= 1 || tlen * qn->lower <= QUANTIFIER_EXPAND_LIMIT_SIZE)) { if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) { if (qn->greedy) { if (IS_NOT_NULL(qn->head_exact)) r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1); else if (IS_NOT_NULL(qn->next_head_exact)) r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT); else r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH); } else { r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP); } if (r) return r; } else { r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; } if (qn->greedy) { if (IS_NOT_NULL(qn->head_exact)) { r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1, mod_tlen + SIZE_OP_JUMP); if (r) return r; add_bytes(reg, NSTR(qn->head_exact)->s, 1); r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1)); } else if (IS_NOT_NULL(qn->next_head_exact)) { r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT, mod_tlen + SIZE_OP_JUMP); if (r) return r; add_bytes(reg, NSTR(qn->next_head_exact)->s, 1); r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT)); } else { r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP); if (r) return r; r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH)); } } else { r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen); if (r) return r; r = compile_tree_empty_check(qn->target, reg, empty_info); if (r) return r; r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH)); } } else if (qn->upper == 0 && qn->is_refered != 0) { /* /(?..){0}/ */ r = add_opcode_rel_addr(reg, OP_JUMP, tlen); if (r) return r; r = compile_tree(qn->target, reg); } else if (!infinite && qn->greedy && (qn->upper == 1 || (tlen + SIZE_OP_PUSH) * qn->upper <= QUANTIFIER_EXPAND_LIMIT_SIZE)) { int n = qn->upper - qn->lower; r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; for (i = 0; i < n; i++) { r = add_opcode_rel_addr(reg, OP_PUSH, (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH); if (r) return r; r = compile_tree(qn->target, reg); if (r) return r; } } else if (!qn->greedy && qn->upper == 1 && qn->lower == 0) { /* '??' */ r = add_opcode_rel_addr(reg, OP_PUSH, SIZE_OP_JUMP); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, tlen); if (r) return r; r = compile_tree(qn->target, reg); } else { r = compile_range_repeat_node(qn, mod_tlen, empty_info, reg); } return r; } #endif /* USE_COMBINATION_EXPLOSION_CHECK */ static int compile_length_option_node(EncloseNode* node, regex_t* reg) { int tlen; OnigOptionType prev = reg->options; reg->options = node->option; tlen = compile_length_tree(node->target, reg); reg->options = prev; if (tlen < 0) return tlen; if (IS_DYNAMIC_OPTION(prev ^ node->option)) { return SIZE_OP_SET_OPTION_PUSH + SIZE_OP_SET_OPTION + SIZE_OP_FAIL + tlen + SIZE_OP_SET_OPTION; } else return tlen; } static int compile_option_node(EncloseNode* node, regex_t* reg) { int r; OnigOptionType prev = reg->options; if (IS_DYNAMIC_OPTION(prev ^ node->option)) { r = add_opcode_option(reg, OP_SET_OPTION_PUSH, node->option); if (r) return r; r = add_opcode_option(reg, OP_SET_OPTION, prev); if (r) return r; r = add_opcode(reg, OP_FAIL); if (r) return r; } reg->options = node->option; r = compile_tree(node->target, reg); reg->options = prev; if (IS_DYNAMIC_OPTION(prev ^ node->option)) { if (r) return r; r = add_opcode_option(reg, OP_SET_OPTION, prev); } return r; } static int compile_length_enclose_node(EncloseNode* node, regex_t* reg) { int len; int tlen; if (node->type == ENCLOSE_OPTION) return compile_length_option_node(node, reg); if (node->target) { tlen = compile_length_tree(node->target, reg); if (tlen < 0) return tlen; } else tlen = 0; switch (node->type) { case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_CALLED(node)) { len = SIZE_OP_MEMORY_START_PUSH + tlen + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN; if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)) len += (IS_ENCLOSE_RECURSION(node) ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH); else len += (IS_ENCLOSE_RECURSION(node) ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END); } else #endif { if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum)) len = SIZE_OP_MEMORY_START_PUSH; else len = SIZE_OP_MEMORY_START; len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum) ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END); } break; case ENCLOSE_STOP_BACKTRACK: if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) { QtfrNode* qn = NQTFR(node->target); tlen = compile_length_tree(qn->target, reg); if (tlen < 0) return tlen; len = tlen * qn->lower + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP; } else { len = SIZE_OP_PUSH_STOP_BT + tlen + SIZE_OP_POP_STOP_BT; } break; case ENCLOSE_CONDITION: len = SIZE_OP_CONDITION; if (NTYPE(node->target) == NT_ALT) { Node* x = node->target; tlen = compile_length_tree(NCAR(x), reg); /* yes-node */ if (tlen < 0) return tlen; len += tlen + SIZE_OP_JUMP; if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG; x = NCDR(x); tlen = compile_length_tree(NCAR(x), reg); /* no-node */ if (tlen < 0) return tlen; len += tlen; if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN; } else { return ONIGERR_PARSER_BUG; } break; default: return ONIGERR_TYPE_BUG; break; } return len; } static int get_char_length_tree(Node* node, regex_t* reg, int* len); static int compile_enclose_node(EncloseNode* node, regex_t* reg) { int r, len; if (node->type == ENCLOSE_OPTION) return compile_option_node(node, reg); switch (node->type) { case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_CALLED(node)) { r = add_opcode(reg, OP_CALL); if (r) return r; node->call_addr = BBUF_GET_OFFSET_POS(reg) + SIZE_ABSADDR + SIZE_OP_JUMP; node->state |= NST_ADDR_FIXED; r = add_abs_addr(reg, (int )node->call_addr); if (r) return r; len = compile_length_tree(node->target, reg); len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN); if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)) len += (IS_ENCLOSE_RECURSION(node) ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH); else len += (IS_ENCLOSE_RECURSION(node) ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END); r = add_opcode_rel_addr(reg, OP_JUMP, len); if (r) return r; } #endif if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum)) r = add_opcode(reg, OP_MEMORY_START_PUSH); else r = add_opcode(reg, OP_MEMORY_START); if (r) return r; r = add_mem_num(reg, node->regnum); if (r) return r; r = compile_tree(node->target, reg); if (r) return r; #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_CALLED(node)) { if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)) r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node) ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH)); else r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node) ? OP_MEMORY_END_REC : OP_MEMORY_END)); if (r) return r; r = add_mem_num(reg, node->regnum); if (r) return r; r = add_opcode(reg, OP_RETURN); } else #endif { if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)) r = add_opcode(reg, OP_MEMORY_END_PUSH); else r = add_opcode(reg, OP_MEMORY_END); if (r) return r; r = add_mem_num(reg, node->regnum); } break; case ENCLOSE_STOP_BACKTRACK: if (IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(node)) { QtfrNode* qn = NQTFR(node->target); r = compile_tree_n_times(qn->target, qn->lower, reg); if (r) return r; len = compile_length_tree(qn->target, reg); if (len < 0) return len; r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_POP + SIZE_OP_JUMP); if (r) return r; r = compile_tree(qn->target, reg); if (r) return r; r = add_opcode(reg, OP_POP); if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP)); } else { r = add_opcode(reg, OP_PUSH_STOP_BT); if (r) return r; r = compile_tree(node->target, reg); if (r) return r; r = add_opcode(reg, OP_POP_STOP_BT); } break; case ENCLOSE_CONDITION: r = add_opcode(reg, OP_CONDITION); if (r) return r; r = add_mem_num(reg, node->regnum); if (r) return r; if (NTYPE(node->target) == NT_ALT) { Node* x = node->target; int len2; len = compile_length_tree(NCAR(x), reg); /* yes-node */ if (len < 0) return len; if (NCDR(x) == NULL) return ONIGERR_PARSER_BUG; x = NCDR(x); len2 = compile_length_tree(NCAR(x), reg); /* no-node */ if (len2 < 0) return len2; if (NCDR(x) != NULL) return ONIGERR_INVALID_CONDITION_PATTERN; x = node->target; r = add_rel_addr(reg, len + SIZE_OP_JUMP); if (r) return r; r = compile_tree(NCAR(x), reg); /* yes-node */ if (r) return r; r = add_opcode_rel_addr(reg, OP_JUMP, len2); if (r) return r; x = NCDR(x); r = compile_tree(NCAR(x), reg); /* no-node */ } else { return ONIGERR_PARSER_BUG; } break; default: return ONIGERR_TYPE_BUG; break; } return r; } static int compile_length_anchor_node(AnchorNode* node, regex_t* reg) { int len; int tlen = 0; if (node->target) { tlen = compile_length_tree(node->target, reg); if (tlen < 0) return tlen; } switch (node->type) { case ANCHOR_PREC_READ: len = SIZE_OP_PUSH_POS + tlen + SIZE_OP_POP_POS; break; case ANCHOR_PREC_READ_NOT: len = SIZE_OP_PUSH_POS_NOT + tlen + SIZE_OP_FAIL_POS; break; case ANCHOR_LOOK_BEHIND: len = SIZE_OP_LOOK_BEHIND + tlen; break; case ANCHOR_LOOK_BEHIND_NOT: len = SIZE_OP_PUSH_LOOK_BEHIND_NOT + tlen + SIZE_OP_FAIL_LOOK_BEHIND_NOT; break; default: len = SIZE_OPCODE; break; } return len; } static int compile_anchor_node(AnchorNode* node, regex_t* reg) { int r, len; switch (node->type) { case ANCHOR_BEGIN_BUF: r = add_opcode(reg, OP_BEGIN_BUF); break; case ANCHOR_END_BUF: r = add_opcode(reg, OP_END_BUF); break; case ANCHOR_BEGIN_LINE: r = add_opcode(reg, OP_BEGIN_LINE); break; case ANCHOR_END_LINE: r = add_opcode(reg, OP_END_LINE); break; case ANCHOR_SEMI_END_BUF: r = add_opcode(reg, OP_SEMI_END_BUF); break; case ANCHOR_BEGIN_POSITION: r = add_opcode(reg, OP_BEGIN_POSITION); break; /* used for implicit anchor optimization: /.*a/ ==> /(?:^|\G).*a/ */ case ANCHOR_ANYCHAR_STAR: r = add_opcode(reg, OP_BEGIN_POS_OR_LINE); break; case ANCHOR_WORD_BOUND: if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_BOUND); else r = add_opcode(reg, OP_WORD_BOUND); break; case ANCHOR_NOT_WORD_BOUND: if (node->ascii_range) r = add_opcode(reg, OP_NOT_ASCII_WORD_BOUND); else r = add_opcode(reg, OP_NOT_WORD_BOUND); break; #ifdef USE_WORD_BEGIN_END case ANCHOR_WORD_BEGIN: if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_BEGIN); else r = add_opcode(reg, OP_WORD_BEGIN); break; case ANCHOR_WORD_END: if (node->ascii_range) r = add_opcode(reg, OP_ASCII_WORD_END); else r = add_opcode(reg, OP_WORD_END); break; #endif case ANCHOR_KEEP: r = add_opcode(reg, OP_KEEP); break; case ANCHOR_PREC_READ: r = add_opcode(reg, OP_PUSH_POS); if (r) return r; r = compile_tree(node->target, reg); if (r) return r; r = add_opcode(reg, OP_POP_POS); break; case ANCHOR_PREC_READ_NOT: len = compile_length_tree(node->target, reg); if (len < 0) return len; r = add_opcode_rel_addr(reg, OP_PUSH_POS_NOT, len + SIZE_OP_FAIL_POS); if (r) return r; r = compile_tree(node->target, reg); if (r) return r; r = add_opcode(reg, OP_FAIL_POS); break; case ANCHOR_LOOK_BEHIND: { int n; r = add_opcode(reg, OP_LOOK_BEHIND); if (r) return r; if (node->char_len < 0) { r = get_char_length_tree(node->target, reg, &n); if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN; } else n = node->char_len; r = add_length(reg, n); if (r) return r; r = compile_tree(node->target, reg); } break; case ANCHOR_LOOK_BEHIND_NOT: { int n; len = compile_length_tree(node->target, reg); r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT, len + SIZE_OP_FAIL_LOOK_BEHIND_NOT); if (r) return r; if (node->char_len < 0) { r = get_char_length_tree(node->target, reg, &n); if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN; } else n = node->char_len; r = add_length(reg, n); if (r) return r; r = compile_tree(node->target, reg); if (r) return r; r = add_opcode(reg, OP_FAIL_LOOK_BEHIND_NOT); } break; default: return ONIGERR_TYPE_BUG; break; } return r; } static int compile_length_tree(Node* node, regex_t* reg) { int len, type, r; type = NTYPE(node); switch (type) { case NT_LIST: len = 0; do { r = compile_length_tree(NCAR(node), reg); if (r < 0) return r; len += r; } while (IS_NOT_NULL(node = NCDR(node))); r = len; break; case NT_ALT: { int n; n = r = 0; do { r += compile_length_tree(NCAR(node), reg); n++; } while (IS_NOT_NULL(node = NCDR(node))); r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1); } break; case NT_STR: if (NSTRING_IS_RAW(node)) r = compile_length_string_raw_node(NSTR(node), reg); else r = compile_length_string_node(node, reg); break; case NT_CCLASS: r = compile_length_cclass_node(NCCLASS(node), reg); break; case NT_CTYPE: case NT_CANY: r = SIZE_OPCODE; break; case NT_BREF: { BRefNode* br = NBREF(node); #ifdef USE_BACKREF_WITH_LEVEL if (IS_BACKREF_NEST_LEVEL(br)) { r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); } else #endif if (br->back_num == 1) { r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2) ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM)); } else { r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num); } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: r = SIZE_OP_CALL; break; #endif case NT_QTFR: r = compile_length_quantifier_node(NQTFR(node), reg); break; case NT_ENCLOSE: r = compile_length_enclose_node(NENCLOSE(node), reg); break; case NT_ANCHOR: r = compile_length_anchor_node(NANCHOR(node), reg); break; default: return ONIGERR_TYPE_BUG; break; } return r; } static int compile_tree(Node* node, regex_t* reg) { int n, type, len, pos, r = 0; type = NTYPE(node); switch (type) { case NT_LIST: do { r = compile_tree(NCAR(node), reg); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_ALT: { Node* x = node; len = 0; do { len += compile_length_tree(NCAR(x), reg); if (NCDR(x) != NULL) { len += SIZE_OP_PUSH + SIZE_OP_JUMP; } } while (IS_NOT_NULL(x = NCDR(x))); pos = reg->used + len; /* goal position */ do { len = compile_length_tree(NCAR(node), reg); if (IS_NOT_NULL(NCDR(node))) { r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP); if (r) break; } r = compile_tree(NCAR(node), reg); if (r) break; if (IS_NOT_NULL(NCDR(node))) { len = pos - (reg->used + SIZE_OP_JUMP); r = add_opcode_rel_addr(reg, OP_JUMP, len); if (r) break; } } while (IS_NOT_NULL(node = NCDR(node))); } break; case NT_STR: if (NSTRING_IS_RAW(node)) r = compile_string_raw_node(NSTR(node), reg); else r = compile_string_node(node, reg); break; case NT_CCLASS: r = compile_cclass_node(NCCLASS(node), reg); break; case NT_CTYPE: { int op; switch (NCTYPE(node)->ctype) { case ONIGENC_CTYPE_WORD: if (NCTYPE(node)->ascii_range != 0) { if (NCTYPE(node)->not != 0) op = OP_NOT_ASCII_WORD; else op = OP_ASCII_WORD; } else { if (NCTYPE(node)->not != 0) op = OP_NOT_WORD; else op = OP_WORD; } break; default: return ONIGERR_TYPE_BUG; break; } r = add_opcode(reg, op); } break; case NT_CANY: if (IS_MULTILINE(reg->options)) r = add_opcode(reg, OP_ANYCHAR_ML); else r = add_opcode(reg, OP_ANYCHAR); break; case NT_BREF: { BRefNode* br = NBREF(node); #ifdef USE_BACKREF_WITH_LEVEL if (IS_BACKREF_NEST_LEVEL(br)) { r = add_opcode(reg, OP_BACKREF_WITH_LEVEL); if (r) return r; r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE)); if (r) return r; r = add_length(reg, br->nest_level); if (r) return r; goto add_bacref_mems; } else #endif if (br->back_num == 1) { n = br->back_static[0]; if (IS_IGNORECASE(reg->options)) { r = add_opcode(reg, OP_BACKREFN_IC); if (r) return r; r = add_mem_num(reg, n); } else { switch (n) { case 1: r = add_opcode(reg, OP_BACKREF1); break; case 2: r = add_opcode(reg, OP_BACKREF2); break; default: r = add_opcode(reg, OP_BACKREFN); if (r) return r; r = add_mem_num(reg, n); break; } } } else { int i; int* p; if (IS_IGNORECASE(reg->options)) { r = add_opcode(reg, OP_BACKREF_MULTI_IC); } else { r = add_opcode(reg, OP_BACKREF_MULTI); } if (r) return r; #ifdef USE_BACKREF_WITH_LEVEL add_bacref_mems: #endif r = add_length(reg, br->back_num); if (r) return r; p = BACKREFS_P(br); for (i = br->back_num - 1; i >= 0; i--) { r = add_mem_num(reg, p[i]); if (r) return r; } } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: r = compile_call(NCALL(node), reg); break; #endif case NT_QTFR: r = compile_quantifier_node(NQTFR(node), reg); break; case NT_ENCLOSE: r = compile_enclose_node(NENCLOSE(node), reg); break; case NT_ANCHOR: r = compile_anchor_node(NANCHOR(node), reg); break; default: #ifdef ONIG_DEBUG fprintf(stderr, "compile_tree: undefined node type %d\n", NTYPE(node)); #endif break; } return r; } #ifdef USE_NAMED_GROUP static int noname_disable_map(Node** plink, GroupNumRemap* map, int* counter) { int r = 0; Node* node = *plink; switch (NTYPE(node)) { case NT_LIST: case NT_ALT: do { r = noname_disable_map(&(NCAR(node)), map, counter); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: { Node** ptarget = &(NQTFR(node)->target); Node* old = *ptarget; r = noname_disable_map(ptarget, map, counter); if (*ptarget != old && NTYPE(*ptarget) == NT_QTFR) { onig_reduce_nested_quantifier(node, *ptarget); } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); if (en->type == ENCLOSE_MEMORY) { if (IS_ENCLOSE_NAMED_GROUP(en)) { (*counter)++; map[en->regnum].new_val = *counter; en->regnum = *counter; r = noname_disable_map(&(en->target), map, counter); } else { *plink = en->target; en->target = NULL_NODE; onig_node_free(node); r = noname_disable_map(plink, map, counter); } } else r = noname_disable_map(&(en->target), map, counter); } break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = noname_disable_map(&(an->target), map, counter); break; } } break; default: break; } return r; } static int renumber_node_backref(Node* node, GroupNumRemap* map) { int i, pos, n, old_num; int *backs; BRefNode* bn = NBREF(node); if (! IS_BACKREF_NAME_REF(bn)) return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; old_num = bn->back_num; if (IS_NULL(bn->back_dynamic)) backs = bn->back_static; else backs = bn->back_dynamic; for (i = 0, pos = 0; i < old_num; i++) { n = map[backs[i]].new_val; if (n > 0) { backs[pos] = n; pos++; } } bn->back_num = pos; return 0; } static int renumber_by_map(Node* node, GroupNumRemap* map) { int r = 0; switch (NTYPE(node)) { case NT_LIST: case NT_ALT: do { r = renumber_by_map(NCAR(node), map); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = renumber_by_map(NQTFR(node)->target, map); break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); if (en->type == ENCLOSE_CONDITION) en->regnum = map[en->regnum].new_val; r = renumber_by_map(en->target, map); } break; case NT_BREF: r = renumber_node_backref(node, map); break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = renumber_by_map(an->target, map); break; } } break; default: break; } return r; } static int numbered_ref_check(Node* node) { int r = 0; switch (NTYPE(node)) { case NT_LIST: case NT_ALT: do { r = numbered_ref_check(NCAR(node)); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = numbered_ref_check(NQTFR(node)->target); break; case NT_ENCLOSE: r = numbered_ref_check(NENCLOSE(node)->target); break; case NT_BREF: if (! IS_BACKREF_NAME_REF(NBREF(node))) return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; break; default: break; } return r; } static int disable_noname_group_capture(Node** root, regex_t* reg, ScanEnv* env) { int r, i, pos, counter; BitStatusType loc; GroupNumRemap* map; map = (GroupNumRemap* )xalloca(sizeof(GroupNumRemap) * (env->num_mem + 1)); CHECK_NULL_RETURN_MEMERR(map); for (i = 1; i <= env->num_mem; i++) { map[i].new_val = 0; } counter = 0; r = noname_disable_map(root, map, &counter); if (r != 0) return r; r = renumber_by_map(*root, map); if (r != 0) return r; for (i = 1, pos = 1; i <= env->num_mem; i++) { if (map[i].new_val > 0) { SCANENV_MEM_NODES(env)[pos] = SCANENV_MEM_NODES(env)[i]; pos++; } } loc = env->capture_history; BIT_STATUS_CLEAR(env->capture_history); for (i = 1; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { if (BIT_STATUS_AT(loc, i)) { BIT_STATUS_ON_AT_SIMPLE(env->capture_history, map[i].new_val); } } env->num_mem = env->num_named; reg->num_mem = env->num_named; return onig_renumber_name_table(reg, map); } #endif /* USE_NAMED_GROUP */ #ifdef USE_SUBEXP_CALL static int unset_addr_list_fix(UnsetAddrList* uslist, regex_t* reg) { int i, offset; EncloseNode* en; AbsAddrType addr; for (i = 0; i < uslist->num; i++) { en = NENCLOSE(uslist->us[i].target); if (! IS_ENCLOSE_ADDR_FIXED(en)) return ONIGERR_PARSER_BUG; addr = en->call_addr; offset = uslist->us[i].offset; BBUF_WRITE(reg, offset, &addr, SIZE_ABSADDR); } return 0; } #endif #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT static int quantifiers_memory_node_info(Node* node) { int r = 0; switch (NTYPE(node)) { case NT_LIST: case NT_ALT: { int v; do { v = quantifiers_memory_node_info(NCAR(node)); if (v > r) r = v; } while (v >= 0 && IS_NOT_NULL(node = NCDR(node))); } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (IS_CALL_RECURSION(NCALL(node))) { return NQ_TARGET_IS_EMPTY_REC; /* tiny version */ } else r = quantifiers_memory_node_info(NCALL(node)->target); break; #endif case NT_QTFR: { QtfrNode* qn = NQTFR(node); if (qn->upper != 0) { r = quantifiers_memory_node_info(qn->target); } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_MEMORY: return NQ_TARGET_IS_EMPTY_MEM; break; case ENCLOSE_OPTION: case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: r = quantifiers_memory_node_info(en->target); break; default: break; } } break; case NT_BREF: case NT_STR: case NT_CTYPE: case NT_CCLASS: case NT_CANY: case NT_ANCHOR: default: break; } return r; } #endif /* USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT */ static int get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env) { OnigDistance tmin; int r = 0; *min = 0; switch (NTYPE(node)) { case NT_BREF: { int i; int* backs; Node** nodes = SCANENV_MEM_NODES(env); BRefNode* br = NBREF(node); if (br->state & NST_RECURSION) break; backs = BACKREFS_P(br); if (backs[0] > env->num_mem) return ONIGERR_INVALID_BACKREF; r = get_min_match_length(nodes[backs[0]], min, env); if (r != 0) break; for (i = 1; i < br->back_num; i++) { if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF; r = get_min_match_length(nodes[backs[i]], &tmin, env); if (r != 0) break; if (*min > tmin) *min = tmin; } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (IS_CALL_RECURSION(NCALL(node))) { EncloseNode* en = NENCLOSE(NCALL(node)->target); if (IS_ENCLOSE_MIN_FIXED(en)) *min = en->min_len; } else r = get_min_match_length(NCALL(node)->target, min, env); break; #endif case NT_LIST: do { r = get_min_match_length(NCAR(node), &tmin, env); if (r == 0) *min += tmin; } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_ALT: { Node *x, *y; y = node; do { x = NCAR(y); r = get_min_match_length(x, &tmin, env); if (r != 0) break; if (y == node) *min = tmin; else if (*min > tmin) *min = tmin; } while (r == 0 && IS_NOT_NULL(y = NCDR(y))); } break; case NT_STR: { StrNode* sn = NSTR(node); *min = sn->end - sn->s; } break; case NT_CTYPE: *min = 1; break; case NT_CCLASS: case NT_CANY: *min = 1; break; case NT_QTFR: { QtfrNode* qn = NQTFR(node); if (qn->lower > 0) { r = get_min_match_length(qn->target, min, env); if (r == 0) *min = distance_multiply(*min, qn->lower); } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_MIN_FIXED(en)) *min = en->min_len; else { r = get_min_match_length(en->target, min, env); if (r == 0) { en->min_len = *min; SET_ENCLOSE_STATUS(node, NST_MIN_FIXED); } } break; #endif case ENCLOSE_OPTION: case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: r = get_min_match_length(en->target, min, env); break; } } break; case NT_ANCHOR: default: break; } return r; } static int get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env) { OnigDistance tmax; int r = 0; *max = 0; switch (NTYPE(node)) { case NT_LIST: do { r = get_max_match_length(NCAR(node), &tmax, env); if (r == 0) *max = distance_add(*max, tmax); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_ALT: do { r = get_max_match_length(NCAR(node), &tmax, env); if (r == 0 && *max < tmax) *max = tmax; } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_STR: { StrNode* sn = NSTR(node); *max = sn->end - sn->s; } break; case NT_CTYPE: *max = ONIGENC_MBC_MAXLEN_DIST(env->enc); break; case NT_CCLASS: case NT_CANY: *max = ONIGENC_MBC_MAXLEN_DIST(env->enc); break; case NT_BREF: { int i; int* backs; Node** nodes = SCANENV_MEM_NODES(env); BRefNode* br = NBREF(node); if (br->state & NST_RECURSION) { *max = ONIG_INFINITE_DISTANCE; break; } backs = BACKREFS_P(br); for (i = 0; i < br->back_num; i++) { if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF; r = get_max_match_length(nodes[backs[i]], &tmax, env); if (r != 0) break; if (*max < tmax) *max = tmax; } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (! IS_CALL_RECURSION(NCALL(node))) r = get_max_match_length(NCALL(node)->target, max, env); else *max = ONIG_INFINITE_DISTANCE; break; #endif case NT_QTFR: { QtfrNode* qn = NQTFR(node); if (qn->upper != 0) { r = get_max_match_length(qn->target, max, env); if (r == 0 && *max != 0) { if (! IS_REPEAT_INFINITE(qn->upper)) *max = distance_multiply(*max, qn->upper); else *max = ONIG_INFINITE_DISTANCE; } } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_MAX_FIXED(en)) *max = en->max_len; else { r = get_max_match_length(en->target, max, env); if (r == 0) { en->max_len = *max; SET_ENCLOSE_STATUS(node, NST_MAX_FIXED); } } break; #endif case ENCLOSE_OPTION: case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: r = get_max_match_length(en->target, max, env); break; } } break; case NT_ANCHOR: default: break; } return r; } #define GET_CHAR_LEN_VARLEN -1 #define GET_CHAR_LEN_TOP_ALT_VARLEN -2 /* fixed size pattern node only */ static int get_char_length_tree1(Node* node, regex_t* reg, int* len, int level) { int tlen; int r = 0; level++; *len = 0; switch (NTYPE(node)) { case NT_LIST: do { r = get_char_length_tree1(NCAR(node), reg, &tlen, level); if (r == 0) *len = (int )distance_add(*len, tlen); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_ALT: { int tlen2; int varlen = 0; r = get_char_length_tree1(NCAR(node), reg, &tlen, level); while (r == 0 && IS_NOT_NULL(node = NCDR(node))) { r = get_char_length_tree1(NCAR(node), reg, &tlen2, level); if (r == 0) { if (tlen != tlen2) varlen = 1; } } if (r == 0) { if (varlen != 0) { if (level == 1) r = GET_CHAR_LEN_TOP_ALT_VARLEN; else r = GET_CHAR_LEN_VARLEN; } else *len = tlen; } } break; case NT_STR: { StrNode* sn = NSTR(node); UChar *s = sn->s; while (s < sn->end) { s += enclen(reg->enc, s); (*len)++; } } break; case NT_QTFR: { QtfrNode* qn = NQTFR(node); if (qn->lower == qn->upper) { r = get_char_length_tree1(qn->target, reg, &tlen, level); if (r == 0) *len = (int )distance_multiply(tlen, qn->lower); } else r = GET_CHAR_LEN_VARLEN; } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (! IS_CALL_RECURSION(NCALL(node))) r = get_char_length_tree1(NCALL(node)->target, reg, len, level); else r = GET_CHAR_LEN_VARLEN; break; #endif case NT_CTYPE: *len = 1; break; case NT_CCLASS: case NT_CANY: *len = 1; break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL if (IS_ENCLOSE_CLEN_FIXED(en)) *len = en->char_len; else { r = get_char_length_tree1(en->target, reg, len, level); if (r == 0) { en->char_len = *len; SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED); } } break; #endif case ENCLOSE_OPTION: case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: r = get_char_length_tree1(en->target, reg, len, level); break; default: break; } } break; case NT_ANCHOR: break; default: r = GET_CHAR_LEN_VARLEN; break; } return r; } static int get_char_length_tree(Node* node, regex_t* reg, int* len) { return get_char_length_tree1(node, reg, len, 0); } /* x is not included y ==> 1 : 0 */ static int is_not_included(Node* x, Node* y, regex_t* reg) { int i; OnigDistance len; OnigCodePoint code; UChar *p; int ytype; retry: ytype = NTYPE(y); switch (NTYPE(x)) { case NT_CTYPE: { switch (ytype) { case NT_CTYPE: if (NCTYPE(y)->ctype == NCTYPE(x)->ctype && NCTYPE(y)->not != NCTYPE(x)->not && NCTYPE(y)->ascii_range == NCTYPE(x)->ascii_range) return 1; else return 0; break; case NT_CCLASS: swap: { Node* tmp; tmp = x; x = y; y = tmp; goto retry; } break; case NT_STR: goto swap; break; default: break; } } break; case NT_CCLASS: { CClassNode* xc = NCCLASS(x); switch (ytype) { case NT_CTYPE: switch (NCTYPE(y)->ctype) { case ONIGENC_CTYPE_WORD: if (NCTYPE(y)->not == 0) { if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) { for (i = 0; i < SINGLE_BYTE_SIZE; i++) { if (BITSET_AT(xc->bs, i)) { if (NCTYPE(y)->ascii_range) { if (IS_CODE_SB_WORD(reg->enc, i)) return 0; } else { if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0; } } } return 1; } return 0; } else { for (i = 0; i < SINGLE_BYTE_SIZE; i++) { int is_word; if (NCTYPE(y)->ascii_range) is_word = IS_CODE_SB_WORD(reg->enc, i); else is_word = ONIGENC_IS_CODE_WORD(reg->enc, i); if (! is_word) { if (!IS_NCCLASS_NOT(xc)) { if (BITSET_AT(xc->bs, i)) return 0; } else { if (! BITSET_AT(xc->bs, i)) return 0; } } } return 1; } break; default: break; } break; case NT_CCLASS: { int v; CClassNode* yc = NCCLASS(y); for (i = 0; i < SINGLE_BYTE_SIZE; i++) { v = BITSET_AT(xc->bs, i); if ((v != 0 && !IS_NCCLASS_NOT(xc)) || (v == 0 && IS_NCCLASS_NOT(xc))) { v = BITSET_AT(yc->bs, i); if ((v != 0 && !IS_NCCLASS_NOT(yc)) || (v == 0 && IS_NCCLASS_NOT(yc))) return 0; } } if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) || (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc))) return 1; return 0; } break; case NT_STR: goto swap; break; default: break; } } break; case NT_STR: { StrNode* xs = NSTR(x); if (NSTRING_LEN(x) == 0) break; switch (ytype) { case NT_CTYPE: switch (NCTYPE(y)->ctype) { case ONIGENC_CTYPE_WORD: if (NCTYPE(y)->ascii_range) { if (ONIGENC_IS_MBC_ASCII_WORD(reg->enc, xs->s, xs->end)) return NCTYPE(y)->not; else return !(NCTYPE(y)->not); } else { if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end)) return NCTYPE(y)->not; else return !(NCTYPE(y)->not); } break; default: break; } break; case NT_CCLASS: { CClassNode* cc = NCCLASS(y); code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s, xs->s + ONIGENC_MBC_MAXLEN(reg->enc)); return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1); } break; case NT_STR: { UChar *q; StrNode* ys = NSTR(y); len = NSTRING_LEN(x); if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y); if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) { /* tiny version */ return 0; } else { for (i = 0, p = ys->s, q = xs->s; (OnigDistance )i < len; i++, p++, q++) { if (*p != *q) return 1; } } } break; default: break; } } break; default: break; } return 0; } static Node* get_head_value_node(Node* node, int exact, regex_t* reg) { Node* n = NULL_NODE; switch (NTYPE(node)) { case NT_BREF: case NT_ALT: case NT_CANY: #ifdef USE_SUBEXP_CALL case NT_CALL: #endif break; case NT_CTYPE: case NT_CCLASS: if (exact == 0) { n = node; } break; case NT_LIST: n = get_head_value_node(NCAR(node), exact, reg); break; case NT_STR: { StrNode* sn = NSTR(node); if (sn->end <= sn->s) break; if (exact != 0 && !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) { } else { n = node; } } break; case NT_QTFR: { QtfrNode* qn = NQTFR(node); if (qn->lower > 0) { if (IS_NOT_NULL(qn->head_exact)) n = qn->head_exact; else n = get_head_value_node(qn->target, exact, reg); } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_OPTION: { OnigOptionType options = reg->options; reg->options = NENCLOSE(node)->option; n = get_head_value_node(NENCLOSE(node)->target, exact, reg); reg->options = options; } break; case ENCLOSE_MEMORY: case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: n = get_head_value_node(en->target, exact, reg); break; } } break; case NT_ANCHOR: if (NANCHOR(node)->type == ANCHOR_PREC_READ) n = get_head_value_node(NANCHOR(node)->target, exact, reg); break; default: break; } return n; } static int check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask) { int type, r = 0; type = NTYPE(node); if ((NTYPE2BIT(type) & type_mask) == 0) return 1; switch (type) { case NT_LIST: case NT_ALT: do { r = check_type_tree(NCAR(node), type_mask, enclose_mask, anchor_mask); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = check_type_tree(NQTFR(node)->target, type_mask, enclose_mask, anchor_mask); break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); if ((en->type & enclose_mask) == 0) return 1; r = check_type_tree(en->target, type_mask, enclose_mask, anchor_mask); } break; case NT_ANCHOR: type = NANCHOR(node)->type; if ((type & anchor_mask) == 0) return 1; if (NANCHOR(node)->target) r = check_type_tree(NANCHOR(node)->target, type_mask, enclose_mask, anchor_mask); break; default: break; } return r; } #ifdef USE_SUBEXP_CALL #define RECURSION_EXIST 1 #define RECURSION_INFINITE 2 static int subexp_inf_recursive_check(Node* node, ScanEnv* env, int head) { int type; int r = 0; type = NTYPE(node); switch (type) { case NT_LIST: { Node *x; OnigDistance min; int ret; x = node; do { ret = subexp_inf_recursive_check(NCAR(x), env, head); if (ret < 0 || ret == RECURSION_INFINITE) return ret; r |= ret; if (head) { ret = get_min_match_length(NCAR(x), &min, env); if (ret != 0) return ret; if (min != 0) head = 0; } } while (IS_NOT_NULL(x = NCDR(x))); } break; case NT_ALT: { int ret; r = RECURSION_EXIST; do { ret = subexp_inf_recursive_check(NCAR(node), env, head); if (ret < 0 || ret == RECURSION_INFINITE) return ret; r &= ret; } while (IS_NOT_NULL(node = NCDR(node))); } break; case NT_QTFR: r = subexp_inf_recursive_check(NQTFR(node)->target, env, head); if (r == RECURSION_EXIST) { if (NQTFR(node)->lower == 0) r = 0; } break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = subexp_inf_recursive_check(an->target, env, head); break; } } break; case NT_CALL: r = subexp_inf_recursive_check(NCALL(node)->target, env, head); break; case NT_ENCLOSE: if (IS_ENCLOSE_MARK2(NENCLOSE(node))) return 0; else if (IS_ENCLOSE_MARK1(NENCLOSE(node))) return (head == 0 ? RECURSION_EXIST : RECURSION_INFINITE); else { SET_ENCLOSE_STATUS(node, NST_MARK2); r = subexp_inf_recursive_check(NENCLOSE(node)->target, env, head); CLEAR_ENCLOSE_STATUS(node, NST_MARK2); } break; default: break; } return r; } static int subexp_inf_recursive_check_trav(Node* node, ScanEnv* env) { int type; int r = 0; type = NTYPE(node); switch (type) { case NT_LIST: case NT_ALT: do { r = subexp_inf_recursive_check_trav(NCAR(node), env); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = subexp_inf_recursive_check_trav(NQTFR(node)->target, env); break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = subexp_inf_recursive_check_trav(an->target, env); break; } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); if (IS_ENCLOSE_RECURSION(en)) { SET_ENCLOSE_STATUS(node, NST_MARK1); r = subexp_inf_recursive_check(en->target, env, 1); if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION; CLEAR_ENCLOSE_STATUS(node, NST_MARK1); } r = subexp_inf_recursive_check_trav(en->target, env); } break; default: break; } return r; } static int subexp_recursive_check(Node* node) { int r = 0; switch (NTYPE(node)) { case NT_LIST: case NT_ALT: do { r |= subexp_recursive_check(NCAR(node)); } while (IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = subexp_recursive_check(NQTFR(node)->target); break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = subexp_recursive_check(an->target); break; } } break; case NT_CALL: r = subexp_recursive_check(NCALL(node)->target); if (r != 0) SET_CALL_RECURSION(node); break; case NT_ENCLOSE: if (IS_ENCLOSE_MARK2(NENCLOSE(node))) return 0; else if (IS_ENCLOSE_MARK1(NENCLOSE(node))) return 1; /* recursion */ else { SET_ENCLOSE_STATUS(node, NST_MARK2); r = subexp_recursive_check(NENCLOSE(node)->target); CLEAR_ENCLOSE_STATUS(node, NST_MARK2); } break; default: break; } return r; } static int subexp_recursive_check_trav(Node* node, ScanEnv* env) { #define FOUND_CALLED_NODE 1 int type; int r = 0; type = NTYPE(node); switch (type) { case NT_LIST: case NT_ALT: { int ret; do { ret = subexp_recursive_check_trav(NCAR(node), env); if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE; else if (ret < 0) return ret; } while (IS_NOT_NULL(node = NCDR(node))); } break; case NT_QTFR: r = subexp_recursive_check_trav(NQTFR(node)->target, env); if (NQTFR(node)->upper == 0) { if (r == FOUND_CALLED_NODE) NQTFR(node)->is_refered = 1; } break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = subexp_recursive_check_trav(an->target, env); break; } } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); if (! IS_ENCLOSE_RECURSION(en)) { if (IS_ENCLOSE_CALLED(en)) { SET_ENCLOSE_STATUS(node, NST_MARK1); r = subexp_recursive_check(en->target); if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION); CLEAR_ENCLOSE_STATUS(node, NST_MARK1); } } r = subexp_recursive_check_trav(en->target, env); if (IS_ENCLOSE_CALLED(en)) r |= FOUND_CALLED_NODE; } break; default: break; } return r; } static int setup_subexp_call(Node* node, ScanEnv* env) { int type; int r = 0; type = NTYPE(node); switch (type) { case NT_LIST: do { r = setup_subexp_call(NCAR(node), env); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_ALT: do { r = setup_subexp_call(NCAR(node), env); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_QTFR: r = setup_subexp_call(NQTFR(node)->target, env); break; case NT_ENCLOSE: r = setup_subexp_call(NENCLOSE(node)->target, env); break; case NT_CALL: { CallNode* cn = NCALL(node); Node** nodes = SCANENV_MEM_NODES(env); if (cn->group_num != 0) { int gnum = cn->group_num; #ifdef USE_NAMED_GROUP if (env->num_named > 0 && IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) && !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) { return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; } #endif if (gnum > env->num_mem) { onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end); return ONIGERR_UNDEFINED_GROUP_REFERENCE; } #ifdef USE_NAMED_GROUP set_call_attr: #endif cn->target = nodes[cn->group_num]; if (IS_NULL(cn->target)) { onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end); return ONIGERR_UNDEFINED_NAME_REFERENCE; } SET_ENCLOSE_STATUS(cn->target, NST_CALLED); BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num); cn->unset_addr_list = env->unset_addr_list; } #ifdef USE_NAMED_GROUP #ifdef USE_PERL_SUBEXP_CALL else if (cn->name == cn->name_end) { goto set_call_attr; } #endif else { int *refs; int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end, &refs); if (n <= 0) { onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end); return ONIGERR_UNDEFINED_NAME_REFERENCE; } else if (n > 1 && ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL)) { onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end); return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL; } else { cn->group_num = refs[0]; goto set_call_attr; } } #endif } break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND: case ANCHOR_LOOK_BEHIND_NOT: r = setup_subexp_call(an->target, env); break; } } break; default: break; } return r; } #endif /* divide different length alternatives in look-behind. (?<=A|B) ==> (?<=A)|(?<=B) (? (?type; head = an->target; np = NCAR(head); swap_node(node, head); NCAR(node) = head; NANCHOR(head)->target = np; np = node; while ((np = NCDR(np)) != NULL_NODE) { insert_node = onig_node_new_anchor(anc_type); CHECK_NULL_RETURN_MEMERR(insert_node); NANCHOR(insert_node)->target = NCAR(np); NCAR(np) = insert_node; } if (anc_type == ANCHOR_LOOK_BEHIND_NOT) { np = node; do { SET_NTYPE(np, NT_LIST); /* alt -> list */ } while ((np = NCDR(np)) != NULL_NODE); } return 0; } static int setup_look_behind(Node* node, regex_t* reg, ScanEnv* env) { int r, len; AnchorNode* an = NANCHOR(node); r = get_char_length_tree(an->target, reg, &len); if (r == 0) an->char_len = len; else if (r == GET_CHAR_LEN_VARLEN) r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN; else if (r == GET_CHAR_LEN_TOP_ALT_VARLEN) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND)) r = divide_look_behind_alternatives(node); else r = ONIGERR_INVALID_LOOK_BEHIND_PATTERN; } return r; } static int next_setup(Node* node, Node* next_node, int in_root, regex_t* reg) { int type; retry: type = NTYPE(node); if (type == NT_QTFR) { QtfrNode* qn = NQTFR(node); if (qn->greedy && IS_REPEAT_INFINITE(qn->upper)) { #ifdef USE_QTFR_PEEK_NEXT Node* n = get_head_value_node(next_node, 1, reg); /* '\0': for UTF-16BE etc... */ if (IS_NOT_NULL(n) && NSTR(n)->s[0] != '\0') { qn->next_head_exact = n; } #endif /* automatic possessivation a*b ==> (?>a*)b */ if (qn->lower <= 1) { int ttype = NTYPE(qn->target); if (IS_NODE_TYPE_SIMPLE(ttype)) { Node *x, *y; x = get_head_value_node(qn->target, 0, reg); if (IS_NOT_NULL(x)) { y = get_head_value_node(next_node, 0, reg); if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) { Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK); CHECK_NULL_RETURN_MEMERR(en); SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT); swap_node(node, en); NENCLOSE(node)->target = en; } } } } #ifndef ONIG_DONT_OPTIMIZE if (NTYPE(node) == NT_QTFR && /* the type may be changed by above block */ in_root && /* qn->lower == 0 && */ NTYPE(qn->target) == NT_CANY && ! IS_MULTILINE(reg->options)) { /* implicit anchor: /.*a/ ==> /(?:^|\G).*a/ */ Node *np; np = onig_node_new_list(NULL_NODE, NULL_NODE); CHECK_NULL_RETURN_MEMERR(np); swap_node(node, np); NCDR(node) = onig_node_new_list(np, NULL_NODE); if (IS_NULL(NCDR(node))) { onig_node_free(np); return ONIGERR_MEMORY; } np = onig_node_new_anchor(ANCHOR_ANYCHAR_STAR); /* (?:^|\G) */ CHECK_NULL_RETURN_MEMERR(np); NCAR(node) = np; } #endif } } else if (type == NT_ENCLOSE) { EncloseNode* en = NENCLOSE(node); in_root = 0; if (en->type == ENCLOSE_MEMORY) { node = en->target; goto retry; } } return 0; } static int update_string_node_case_fold(regex_t* reg, Node *node) { UChar *p, *end, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN]; UChar *sbuf, *ebuf, *sp; int r, i, len; OnigDistance sbuf_size; StrNode* sn = NSTR(node); end = sn->end; sbuf_size = (end - sn->s) * 2; sbuf = (UChar* )xmalloc(sbuf_size); CHECK_NULL_RETURN_MEMERR(sbuf); ebuf = sbuf + sbuf_size; sp = sbuf; p = sn->s; while (p < end) { len = ONIGENC_MBC_CASE_FOLD(reg->enc, reg->case_fold_flag, &p, end, buf); for (i = 0; i < len; i++) { if (sp >= ebuf) { UChar* p = (UChar* )xrealloc(sbuf, sbuf_size * 2); if (IS_NULL(p)) { xfree(sbuf); return ONIGERR_MEMORY; } sbuf = p; sp = sbuf + sbuf_size; sbuf_size *= 2; ebuf = sbuf + sbuf_size; } *sp++ = buf[i]; } } r = onig_node_str_set(node, sbuf, sp); if (r != 0) { xfree(sbuf); return r; } xfree(sbuf); return 0; } static int expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end, regex_t* reg) { int r; Node *node; node = onig_node_new_str(s, end); if (IS_NULL(node)) return ONIGERR_MEMORY; r = update_string_node_case_fold(reg, node); if (r != 0) { onig_node_free(node); return r; } NSTRING_SET_AMBIG(node); NSTRING_SET_DONT_GET_OPT_INFO(node); *rnode = node; return 0; } static int expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[], UChar *p, int slen, UChar *end, regex_t* reg, Node **rnode) { int r, i, j, len, varlen, varclen; Node *anode, *var_anode, *snode, *xnode, *an; UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; *rnode = var_anode = NULL_NODE; varlen = 0; varclen = 0; for (i = 0; i < item_num; i++) { if (items[i].byte_len != slen) { varlen = 1; break; } if (items[i].code_len != 1) { varclen = 1; } } if (varlen != 0) { *rnode = var_anode = onig_node_new_alt(NULL_NODE, NULL_NODE); if (IS_NULL(var_anode)) return ONIGERR_MEMORY; xnode = onig_node_new_list(NULL, NULL); if (IS_NULL(xnode)) goto mem_err; NCAR(var_anode) = xnode; anode = onig_node_new_alt(NULL_NODE, NULL_NODE); if (IS_NULL(anode)) goto mem_err; NCAR(xnode) = anode; } else { *rnode = anode = onig_node_new_alt(NULL_NODE, NULL_NODE); if (IS_NULL(anode)) return ONIGERR_MEMORY; } snode = onig_node_new_str(p, p + slen); if (IS_NULL(snode)) goto mem_err; NCAR(anode) = snode; for (i = 0; i < item_num; i++) { snode = onig_node_new_str(NULL, NULL); if (IS_NULL(snode)) goto mem_err; for (j = 0; j < items[i].code_len; j++) { len = ONIGENC_CODE_TO_MBC(reg->enc, items[i].code[j], buf); if (len < 0) { r = len; goto mem_err2; } r = onig_node_str_cat(snode, buf, buf + len); if (r != 0) goto mem_err2; } an = onig_node_new_alt(NULL_NODE, NULL_NODE); if (IS_NULL(an)) { goto mem_err2; } if (items[i].byte_len != slen) { Node *rem; UChar *q = p + items[i].byte_len; if (q < end) { r = expand_case_fold_make_rem_string(&rem, q, end, reg); if (r != 0) { onig_node_free(an); goto mem_err2; } xnode = onig_node_list_add(NULL_NODE, snode); if (IS_NULL(xnode)) { onig_node_free(an); onig_node_free(rem); goto mem_err2; } if (IS_NULL(onig_node_list_add(xnode, rem))) { onig_node_free(an); onig_node_free(xnode); onig_node_free(rem); goto mem_err; } NCAR(an) = xnode; } else { NCAR(an) = snode; } NCDR(var_anode) = an; var_anode = an; } else { NCAR(an) = snode; NCDR(anode) = an; anode = an; } } if (varclen && !varlen) return 2; return varlen; mem_err2: onig_node_free(snode); mem_err: onig_node_free(*rnode); return ONIGERR_MEMORY; } static int expand_case_fold_string(Node* node, regex_t* reg) { #define THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION 8 int r, n, len, alt_num; int varlen = 0; UChar *start, *end, *p; Node *top_root, *root, *snode, *prev_node; OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; StrNode* sn = NSTR(node); if (NSTRING_IS_AMBIG(node)) return 0; start = sn->s; end = sn->end; if (start >= end) return 0; r = 0; top_root = root = prev_node = snode = NULL_NODE; alt_num = 1; p = start; while (p < end) { n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag, p, end, items); if (n < 0) { r = n; goto err; } len = enclen(reg->enc, p); if (n == 0) { if (IS_NULL(snode)) { if (IS_NULL(root) && IS_NOT_NULL(prev_node)) { top_root = root = onig_node_list_add(NULL_NODE, prev_node); if (IS_NULL(root)) { onig_node_free(prev_node); goto mem_err; } } prev_node = snode = onig_node_new_str(NULL, NULL); if (IS_NULL(snode)) goto mem_err; if (IS_NOT_NULL(root)) { if (IS_NULL(onig_node_list_add(root, snode))) { onig_node_free(snode); goto mem_err; } } } r = onig_node_str_cat(snode, p, p + len); if (r != 0) goto err; } else { alt_num *= (n + 1); if (alt_num > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break; if (IS_NULL(root) && IS_NOT_NULL(prev_node)) { top_root = root = onig_node_list_add(NULL_NODE, prev_node); if (IS_NULL(root)) { onig_node_free(prev_node); goto mem_err; } } r = expand_case_fold_string_alt(n, items, p, len, end, reg, &prev_node); if (r < 0) goto mem_err; if (r > 0) varlen = 1; if (r == 1) { if (IS_NULL(root)) { top_root = prev_node; } else { if (IS_NULL(onig_node_list_add(root, prev_node))) { onig_node_free(prev_node); goto mem_err; } } root = NCAR(prev_node); } else { /* r == 0 || r == 2 */ if (IS_NOT_NULL(root)) { if (IS_NULL(onig_node_list_add(root, prev_node))) { onig_node_free(prev_node); goto mem_err; } } } snode = NULL_NODE; } p += len; } if (p < end) { Node *srem; r = expand_case_fold_make_rem_string(&srem, p, end, reg); if (r != 0) goto mem_err; if (IS_NOT_NULL(prev_node) && IS_NULL(root)) { top_root = root = onig_node_list_add(NULL_NODE, prev_node); if (IS_NULL(root)) { onig_node_free(srem); onig_node_free(prev_node); goto mem_err; } } if (IS_NULL(root)) { prev_node = srem; } else { if (IS_NULL(onig_node_list_add(root, srem))) { onig_node_free(srem); goto mem_err; } } } /* ending */ top_root = (IS_NOT_NULL(top_root) ? top_root : prev_node); if (!varlen) { /* When all expanded strings are same length, case-insensitive BM search will be used. */ r = update_string_node_case_fold(reg, node); if (r == 0) { NSTRING_SET_AMBIG(node); } } else { swap_node(node, top_root); r = 0; } onig_node_free(top_root); return r; mem_err: r = ONIGERR_MEMORY; err: onig_node_free(top_root); return r; } #ifdef USE_COMBINATION_EXPLOSION_CHECK #define CEC_THRES_NUM_BIG_REPEAT 512 #define CEC_INFINITE_NUM 0x7fffffff #define CEC_IN_INFINITE_REPEAT (1<<0) #define CEC_IN_FINITE_REPEAT (1<<1) #define CEC_CONT_BIG_REPEAT (1<<2) static int setup_comb_exp_check(Node* node, int state, ScanEnv* env) { int type; int r = state; type = NTYPE(node); switch (type) { case NT_LIST: { Node* prev = NULL_NODE; do { r = setup_comb_exp_check(NCAR(node), r, env); prev = NCAR(node); } while (r >= 0 && IS_NOT_NULL(node = NCDR(node))); } break; case NT_ALT: { int ret; do { ret = setup_comb_exp_check(NCAR(node), state, env); r |= ret; } while (ret >= 0 && IS_NOT_NULL(node = NCDR(node))); } break; case NT_QTFR: { int child_state = state; int add_state = 0; QtfrNode* qn = NQTFR(node); Node* target = qn->target; int var_num; if (! IS_REPEAT_INFINITE(qn->upper)) { if (qn->upper > 1) { /* {0,1}, {1,1} are allowed */ child_state |= CEC_IN_FINITE_REPEAT; /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */ if (env->backrefed_mem == 0) { if (NTYPE(qn->target) == NT_ENCLOSE) { EncloseNode* en = NENCLOSE(qn->target); if (en->type == ENCLOSE_MEMORY) { if (NTYPE(en->target) == NT_QTFR) { QtfrNode* q = NQTFR(en->target); if (IS_REPEAT_INFINITE(q->upper) && q->greedy == qn->greedy) { qn->upper = (qn->lower == 0 ? 1 : qn->lower); if (qn->upper == 1) child_state = state; } } } } } } } if (state & CEC_IN_FINITE_REPEAT) { qn->comb_exp_check_num = -1; } else { if (IS_REPEAT_INFINITE(qn->upper)) { var_num = CEC_INFINITE_NUM; child_state |= CEC_IN_INFINITE_REPEAT; } else { var_num = qn->upper - qn->lower; } if (var_num >= CEC_THRES_NUM_BIG_REPEAT) add_state |= CEC_CONT_BIG_REPEAT; if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) || ((state & CEC_CONT_BIG_REPEAT) != 0 && var_num >= CEC_THRES_NUM_BIG_REPEAT)) { if (qn->comb_exp_check_num == 0) { env->num_comb_exp_check++; qn->comb_exp_check_num = env->num_comb_exp_check; if (env->curr_max_regnum > env->comb_exp_max_regnum) env->comb_exp_max_regnum = env->curr_max_regnum; } } } r = setup_comb_exp_check(target, child_state, env); r |= add_state; } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_MEMORY: { if (env->curr_max_regnum < en->regnum) env->curr_max_regnum = en->regnum; r = setup_comb_exp_check(en->target, state, env); } break; default: r = setup_comb_exp_check(en->target, state, env); break; } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (IS_CALL_RECURSION(NCALL(node))) env->has_recursion = 1; else r = setup_comb_exp_check(NCALL(node)->target, state, env); break; #endif default: break; } return r; } #endif #define IN_ALT (1<<0) #define IN_NOT (1<<1) #define IN_REPEAT (1<<2) #define IN_VAR_REPEAT (1<<3) #define IN_ROOT (1<<4) /* setup_tree does the following work. 1. check empty loop. (set qn->target_empty_info) 2. expand ignore-case in char class. 3. set memory status bit flags. (reg->mem_stats) 4. set qn->head_exact for [push, exact] -> [push_or_jump_exact1, exact]. 5. find invalid patterns in look-behind. 6. expand repeated string. */ static int setup_tree(Node* node, regex_t* reg, int state, ScanEnv* env) { int type; int r = 0; int in_root = state & IN_ROOT; state &= ~IN_ROOT; restart: type = NTYPE(node); switch (type) { case NT_LIST: { Node* prev = NULL_NODE; int prev_in_root = 0; state |= in_root; do { r = setup_tree(NCAR(node), reg, state, env); if (IS_NOT_NULL(prev) && r == 0) { r = next_setup(prev, NCAR(node), prev_in_root, reg); } prev = NCAR(node); prev_in_root = state & IN_ROOT; state &= ~IN_ROOT; } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); } break; case NT_ALT: do { r = setup_tree(NCAR(node), reg, (state | IN_ALT), env); } while (r == 0 && IS_NOT_NULL(node = NCDR(node))); break; case NT_CCLASS: break; case NT_STR: if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) { r = expand_case_fold_string(node, reg); } break; case NT_CTYPE: case NT_CANY: break; #ifdef USE_SUBEXP_CALL case NT_CALL: break; #endif case NT_BREF: { int i; int* p; Node** nodes = SCANENV_MEM_NODES(env); BRefNode* br = NBREF(node); p = BACKREFS_P(br); for (i = 0; i < br->back_num; i++) { if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF; BIT_STATUS_ON_AT(env->backrefed_mem, p[i]); BIT_STATUS_ON_AT(env->bt_mem_start, p[i]); #ifdef USE_BACKREF_WITH_LEVEL if (IS_BACKREF_NEST_LEVEL(br)) { BIT_STATUS_ON_AT(env->bt_mem_end, p[i]); } #endif SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED); } } break; case NT_QTFR: { OnigDistance d; QtfrNode* qn = NQTFR(node); Node* target = qn->target; if ((state & IN_REPEAT) != 0) { qn->state |= NST_IN_REPEAT; } if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) { r = get_min_match_length(target, &d, env); if (r) break; if (d == 0) { qn->target_empty_info = NQ_TARGET_IS_EMPTY; #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT r = quantifiers_memory_node_info(target); if (r < 0) break; if (r > 0) { qn->target_empty_info = r; } #endif #if 0 r = get_max_match_length(target, &d, env); if (r == 0 && d == 0) { /* ()* ==> ()?, ()+ ==> () */ qn->upper = 1; if (qn->lower > 1) qn->lower = 1; if (NTYPE(target) == NT_STR) { qn->upper = qn->lower = 0; /* /(?:)+/ ==> // */ } } #endif } } state |= IN_REPEAT; if (qn->lower != qn->upper) state |= IN_VAR_REPEAT; r = setup_tree(target, reg, state, env); if (r) break; /* expand string */ #define EXPAND_STRING_MAX_LENGTH 100 if (NTYPE(target) == NT_STR) { if (qn->lower > 1) { int i, n = qn->lower; OnigDistance len = NSTRING_LEN(target); StrNode* sn = NSTR(target); Node* np; np = onig_node_new_str(sn->s, sn->end); if (IS_NULL(np)) return ONIGERR_MEMORY; NSTR(np)->flag = sn->flag; for (i = 1; i < n && (i+1) * len <= EXPAND_STRING_MAX_LENGTH; i++) { r = onig_node_str_cat(np, sn->s, sn->end); if (r) { onig_node_free(np); return r; } } if (i < qn->upper || IS_REPEAT_INFINITE(qn->upper)) { Node *np1, *np2; qn->lower -= i; if (! IS_REPEAT_INFINITE(qn->upper)) qn->upper -= i; np1 = onig_node_new_list(np, NULL); if (IS_NULL(np1)) { onig_node_free(np); return ONIGERR_MEMORY; } swap_node(np1, node); np2 = onig_node_list_add(node, np1); if (IS_NULL(np2)) { onig_node_free(np1); return ONIGERR_MEMORY; } } else { swap_node(np, node); onig_node_free(np); } break; /* break case NT_QTFR: */ } } #ifdef USE_OP_PUSH_OR_JUMP_EXACT if (qn->greedy && (qn->target_empty_info != 0)) { if (NTYPE(target) == NT_QTFR) { QtfrNode* tqn = NQTFR(target); if (IS_NOT_NULL(tqn->head_exact)) { qn->head_exact = tqn->head_exact; tqn->head_exact = NULL; } } else { qn->head_exact = get_head_value_node(qn->target, 1, reg); } } #endif } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_OPTION: { OnigOptionType options = reg->options; state |= in_root; reg->options = NENCLOSE(node)->option; r = setup_tree(NENCLOSE(node)->target, reg, state, env); reg->options = options; } break; case ENCLOSE_MEMORY: if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT)) != 0) { BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum); /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */ } r = setup_tree(en->target, reg, state, env); break; case ENCLOSE_STOP_BACKTRACK: { Node* target = en->target; r = setup_tree(target, reg, state, env); if (NTYPE(target) == NT_QTFR) { QtfrNode* tqn = NQTFR(target); if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 && tqn->greedy != 0) { /* (?>a*), a*+ etc... */ int qtype = NTYPE(tqn->target); if (IS_NODE_TYPE_SIMPLE(qtype)) SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT); } } } break; case ENCLOSE_CONDITION: #ifdef USE_NAMED_GROUP if (! IS_ENCLOSE_NAME_REF(NENCLOSE(node)) && env->num_named > 0 && IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) && !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) { return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED; } #endif r = setup_tree(NENCLOSE(node)->target, reg, state, env); break; } } break; case NT_ANCHOR: { AnchorNode* an = NANCHOR(node); switch (an->type) { case ANCHOR_PREC_READ: r = setup_tree(an->target, reg, state, env); break; case ANCHOR_PREC_READ_NOT: r = setup_tree(an->target, reg, (state | IN_NOT), env); break; /* allowed node types in look-behind */ #define ALLOWED_TYPE_IN_LB \ ( BIT_NT_LIST | BIT_NT_ALT | BIT_NT_STR | BIT_NT_CCLASS | BIT_NT_CTYPE | \ BIT_NT_CANY | BIT_NT_ANCHOR | BIT_NT_ENCLOSE | BIT_NT_QTFR | BIT_NT_CALL ) #define ALLOWED_ENCLOSE_IN_LB ( ENCLOSE_MEMORY | ENCLOSE_OPTION ) #define ALLOWED_ENCLOSE_IN_LB_NOT ENCLOSE_OPTION #define ALLOWED_ANCHOR_IN_LB \ ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \ ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \ ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \ ANCHOR_WORD_BEGIN | ANCHOR_WORD_END ) #define ALLOWED_ANCHOR_IN_LB_NOT \ ( ANCHOR_LOOK_BEHIND | ANCHOR_LOOK_BEHIND_NOT | ANCHOR_BEGIN_LINE | \ ANCHOR_END_LINE | ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_KEEP | \ ANCHOR_WORD_BOUND | ANCHOR_NOT_WORD_BOUND | \ ANCHOR_WORD_BEGIN | ANCHOR_WORD_END ) case ANCHOR_LOOK_BEHIND: { r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB, ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB); if (r < 0) return r; if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN; r = setup_look_behind(node, reg, env); if (r != 0) return r; if (NTYPE(node) != NT_ANCHOR) goto restart; r = setup_tree(an->target, reg, state, env); } break; case ANCHOR_LOOK_BEHIND_NOT: { r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB, ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT); if (r < 0) return r; if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN; r = setup_look_behind(node, reg, env); if (r != 0) return r; if (NTYPE(node) != NT_ANCHOR) goto restart; r = setup_tree(an->target, reg, (state | IN_NOT), env); } break; } } break; default: break; } return r; } #ifndef USE_SUNDAY_QUICK_SEARCH /* set skip map for Boyer-Moore search */ static int set_bm_skip(UChar* s, UChar* end, regex_t* reg, UChar skip[], int** int_skip, int ignore_case) { OnigDistance i, len; int clen, flen, n, j, k; UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN]; OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; OnigEncoding enc = reg->enc; len = end - s; if (len < ONIG_CHAR_TABLE_SIZE) { for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )len; n = 0; for (i = 0; i < len - 1; i += clen) { p = s + i; if (ignore_case) n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag, p, end, items); clen = enclen(enc, p); for (j = 0; j < n; j++) { if ((items[j].code_len != 1) || (items[j].byte_len != clen)) return 1; /* different length isn't supported. */ flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]); if (flen != clen) return 1; /* different length isn't supported. */ } for (j = 0; j < clen; j++) { skip[s[i + j]] = (UChar )(len - 1 - i - j); for (k = 0; k < n; k++) { skip[buf[k][j]] = (UChar )(len - 1 - i - j); } } } } else { if (IS_NULL(*int_skip)) { *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE); if (IS_NULL(*int_skip)) return ONIGERR_MEMORY; } for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )len; n = 0; for (i = 0; i < len - 1; i += clen) { p = s + i; if (ignore_case) n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag, p, end, items); clen = enclen(enc, p); for (j = 0; j < n; j++) { if ((items[j].code_len != 1) || (items[j].byte_len != clen)) return 1; /* different length isn't supported. */ flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]); if (flen != clen) return 1; /* different length isn't supported. */ } for (j = 0; j < clen; j++) { (*int_skip)[s[i + j]] = (int )(len - 1 - i - j); for (k = 0; k < n; k++) { (*int_skip)[buf[k][j]] = (int )(len - 1 - i - j); } } } } return 0; } #else /* USE_SUNDAY_QUICK_SEARCH */ /* set skip map for Sunday's quick search */ static int set_bm_skip(UChar* s, UChar* end, regex_t* reg, UChar skip[], int** int_skip, int ignore_case) { OnigDistance i, len; int clen, flen, n, j, k; UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN]; OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; OnigEncoding enc = reg->enc; len = end - s; if (len < ONIG_CHAR_TABLE_SIZE) { for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )(len + 1); n = 0; for (i = 0; i < len; i += clen) { p = s + i; if (ignore_case) n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag, p, end, items); clen = enclen(enc, p); for (j = 0; j < n; j++) { if ((items[j].code_len != 1) || (items[j].byte_len != clen)) return 1; /* different length isn't supported. */ flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]); if (flen != clen) return 1; /* different length isn't supported. */ } for (j = 0; j < clen; j++) { skip[s[i + j]] = (UChar )(len - i - j); for (k = 0; k < n; k++) { skip[buf[k][j]] = (UChar )(len - i - j); } } } } else { if (IS_NULL(*int_skip)) { *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE); if (IS_NULL(*int_skip)) return ONIGERR_MEMORY; } for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )(len + 1); n = 0; for (i = 0; i < len; i += clen) { p = s + i; if (ignore_case) n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag, p, end, items); clen = enclen(enc, p); for (j = 0; j < n; j++) { if ((items[j].code_len != 1) || (items[j].byte_len != clen)) return 1; /* different length isn't supported. */ flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]); if (flen != clen) return 1; /* different length isn't supported. */ } for (j = 0; j < clen; j++) { (*int_skip)[s[i + j]] = (int )(len - i - j); for (k = 0; k < n; k++) { (*int_skip)[buf[k][j]] = (int )(len - i - j); } } } } return 0; } #endif /* USE_SUNDAY_QUICK_SEARCH */ #define OPT_EXACT_MAXLEN 24 typedef struct { OnigDistance min; /* min byte length */ OnigDistance max; /* max byte length */ } MinMaxLen; typedef struct { MinMaxLen mmd; OnigEncoding enc; OnigOptionType options; OnigCaseFoldType case_fold_flag; ScanEnv* scan_env; } OptEnv; typedef struct { int left_anchor; int right_anchor; } OptAncInfo; typedef struct { MinMaxLen mmd; /* info position */ OptAncInfo anc; int reach_end; int ignore_case; /* -1: unset, 0: case sensitive, 1: ignore case */ int len; UChar s[OPT_EXACT_MAXLEN]; } OptExactInfo; typedef struct { MinMaxLen mmd; /* info position */ OptAncInfo anc; int value; /* weighted value */ UChar map[ONIG_CHAR_TABLE_SIZE]; } OptMapInfo; typedef struct { MinMaxLen len; OptAncInfo anc; OptExactInfo exb; /* boundary */ OptExactInfo exm; /* middle */ OptExactInfo expr; /* prec read (?=...) */ OptMapInfo map; /* boundary */ } NodeOptInfo; static int map_position_value(OnigEncoding enc, int i) { static const short int ByteValTable[] = { 5, 1, 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, 1, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 4, 7, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 5, 5, 5, 5, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 1 }; if (i < (int )(sizeof(ByteValTable)/sizeof(ByteValTable[0]))) { if (i == 0 && ONIGENC_MBC_MINLEN(enc) > 1) return 20; else return (int )ByteValTable[i]; } else return 4; /* Take it easy. */ } static int distance_value(MinMaxLen* mm) { /* 1000 / (min-max-dist + 1) */ static const short int dist_vals[] = { 1000, 500, 333, 250, 200, 167, 143, 125, 111, 100, 91, 83, 77, 71, 67, 63, 59, 56, 53, 50, 48, 45, 43, 42, 40, 38, 37, 36, 34, 33, 32, 31, 30, 29, 29, 28, 27, 26, 26, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10 }; OnigDistance d; if (mm->max == ONIG_INFINITE_DISTANCE) return 0; d = mm->max - mm->min; if (d < sizeof(dist_vals)/sizeof(dist_vals[0])) /* return dist_vals[d] * 16 / (mm->min + 12); */ return (int )dist_vals[d]; else return 1; } static int comp_distance_value(MinMaxLen* d1, MinMaxLen* d2, int v1, int v2) { if (v2 <= 0) return -1; if (v1 <= 0) return 1; v1 *= distance_value(d1); v2 *= distance_value(d2); if (v2 > v1) return 1; if (v2 < v1) return -1; if (d2->min < d1->min) return 1; if (d2->min > d1->min) return -1; return 0; } static int is_equal_mml(MinMaxLen* a, MinMaxLen* b) { return (a->min == b->min && a->max == b->max) ? 1 : 0; } static void set_mml(MinMaxLen* mml, OnigDistance min, OnigDistance max) { mml->min = min; mml->max = max; } static void clear_mml(MinMaxLen* mml) { mml->min = mml->max = 0; } static void copy_mml(MinMaxLen* to, MinMaxLen* from) { to->min = from->min; to->max = from->max; } static void add_mml(MinMaxLen* to, MinMaxLen* from) { to->min = distance_add(to->min, from->min); to->max = distance_add(to->max, from->max); } #if 0 static void add_len_mml(MinMaxLen* to, OnigDistance len) { to->min = distance_add(to->min, len); to->max = distance_add(to->max, len); } #endif static void alt_merge_mml(MinMaxLen* to, MinMaxLen* from) { if (to->min > from->min) to->min = from->min; if (to->max < from->max) to->max = from->max; } static void copy_opt_env(OptEnv* to, OptEnv* from) { *to = *from; } static void clear_opt_anc_info(OptAncInfo* anc) { anc->left_anchor = 0; anc->right_anchor = 0; } static void copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from) { *to = *from; } static void concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right, OnigDistance left_len, OnigDistance right_len) { clear_opt_anc_info(to); to->left_anchor = left->left_anchor; if (left_len == 0) { to->left_anchor |= right->left_anchor; } to->right_anchor = right->right_anchor; if (right_len == 0) { to->right_anchor |= left->right_anchor; } } static int is_left_anchor(int anc) { if (anc == ANCHOR_END_BUF || anc == ANCHOR_SEMI_END_BUF || anc == ANCHOR_END_LINE || anc == ANCHOR_PREC_READ || anc == ANCHOR_PREC_READ_NOT) return 0; return 1; } static int is_set_opt_anc_info(OptAncInfo* to, int anc) { if ((to->left_anchor & anc) != 0) return 1; return ((to->right_anchor & anc) != 0 ? 1 : 0); } static void add_opt_anc_info(OptAncInfo* to, int anc) { if (is_left_anchor(anc)) to->left_anchor |= anc; else to->right_anchor |= anc; } static void remove_opt_anc_info(OptAncInfo* to, int anc) { if (is_left_anchor(anc)) to->left_anchor &= ~anc; else to->right_anchor &= ~anc; } static void alt_merge_opt_anc_info(OptAncInfo* to, OptAncInfo* add) { to->left_anchor &= add->left_anchor; to->right_anchor &= add->right_anchor; } static int is_full_opt_exact_info(OptExactInfo* ex) { return (ex->len >= OPT_EXACT_MAXLEN ? 1 : 0); } static void clear_opt_exact_info(OptExactInfo* ex) { clear_mml(&ex->mmd); clear_opt_anc_info(&ex->anc); ex->reach_end = 0; ex->ignore_case = -1; /* unset */ ex->len = 0; ex->s[0] = '\0'; } static void copy_opt_exact_info(OptExactInfo* to, OptExactInfo* from) { *to = *from; } static void concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc) { int i, j, len; UChar *p, *end; OptAncInfo tanc; if (to->ignore_case < 0) to->ignore_case = add->ignore_case; else if (to->ignore_case != add->ignore_case) return ; /* avoid */ p = add->s; end = p + add->len; for (i = to->len; p < end; ) { len = enclen(enc, p); if (i + len > OPT_EXACT_MAXLEN) break; for (j = 0; j < len && p < end; j++) to->s[i++] = *p++; } to->len = i; to->reach_end = (p == end ? add->reach_end : 0); concat_opt_anc_info(&tanc, &to->anc, &add->anc, 1, 1); if (! to->reach_end) tanc.right_anchor = 0; copy_opt_anc_info(&to->anc, &tanc); } static void concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end, int raw ARG_UNUSED, OnigEncoding enc) { int i, j, len; UChar *p; for (i = to->len, p = s; p < end && i < OPT_EXACT_MAXLEN; ) { len = enclen(enc, p); if (i + len > OPT_EXACT_MAXLEN) break; for (j = 0; j < len && p < end; j++) to->s[i++] = *p++; } to->len = i; } static void alt_merge_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OptEnv* env) { int i, j, len; if (add->len == 0 || to->len == 0) { clear_opt_exact_info(to); return ; } if (! is_equal_mml(&to->mmd, &add->mmd)) { clear_opt_exact_info(to); return ; } for (i = 0; i < to->len && i < add->len; ) { if (to->s[i] != add->s[i]) break; len = enclen(env->enc, to->s + i); for (j = 1; j < len; j++) { if (to->s[i+j] != add->s[i+j]) break; } if (j < len) break; i += len; } if (! add->reach_end || i < add->len || i < to->len) { to->reach_end = 0; } to->len = i; if (to->ignore_case < 0) to->ignore_case = add->ignore_case; else if (add->ignore_case >= 0) to->ignore_case |= add->ignore_case; alt_merge_opt_anc_info(&to->anc, &add->anc); if (! to->reach_end) to->anc.right_anchor = 0; } static void select_opt_exact_info(OnigEncoding enc, OptExactInfo* now, OptExactInfo* alt) { int v1, v2; v1 = now->len; v2 = alt->len; if (v2 == 0) { return ; } else if (v1 == 0) { copy_opt_exact_info(now, alt); return ; } else if (v1 <= 2 && v2 <= 2) { /* ByteValTable[x] is big value --> low price */ v2 = map_position_value(enc, now->s[0]); v1 = map_position_value(enc, alt->s[0]); if (now->len > 1) v1 += 5; if (alt->len > 1) v2 += 5; } if (now->ignore_case <= 0) v1 *= 2; if (alt->ignore_case <= 0) v2 *= 2; if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0) copy_opt_exact_info(now, alt); } static void clear_opt_map_info(OptMapInfo* map) { static const OptMapInfo clean_info = { {0, 0}, {0, 0}, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; xmemcpy(map, &clean_info, sizeof(OptMapInfo)); } static void copy_opt_map_info(OptMapInfo* to, OptMapInfo* from) { *to = *from; } static void add_char_opt_map_info(OptMapInfo* map, UChar c, OnigEncoding enc) { if (map->map[c] == 0) { map->map[c] = 1; map->value += map_position_value(enc, c); } } static int add_char_amb_opt_map_info(OptMapInfo* map, UChar* p, UChar* end, OnigEncoding enc, OnigCaseFoldType case_fold_flag) { OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM]; UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; int i, n; add_char_opt_map_info(map, p[0], enc); case_fold_flag = DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag); n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, case_fold_flag, p, end, items); if (n < 0) return n; for (i = 0; i < n; i++) { ONIGENC_CODE_TO_MBC(enc, items[i].code[0], buf); add_char_opt_map_info(map, buf[0], enc); } return 0; } static void select_opt_map_info(OptMapInfo* now, OptMapInfo* alt) { const int z = 1<<15; /* 32768: something big value */ int v1, v2; if (alt->value == 0) return ; if (now->value == 0) { copy_opt_map_info(now, alt); return ; } v1 = z / now->value; v2 = z / alt->value; if (comp_distance_value(&now->mmd, &alt->mmd, v1, v2) > 0) copy_opt_map_info(now, alt); } static int comp_opt_exact_or_map_info(OptExactInfo* e, OptMapInfo* m) { #define COMP_EM_BASE 20 int ve, vm; if (m->value <= 0) return -1; ve = COMP_EM_BASE * e->len * (e->ignore_case > 0 ? 1 : 2); vm = COMP_EM_BASE * 5 * 2 / m->value; return comp_distance_value(&e->mmd, &m->mmd, ve, vm); } static void alt_merge_opt_map_info(OnigEncoding enc, OptMapInfo* to, OptMapInfo* add) { int i, val; /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */ if (to->value == 0) return ; if (add->value == 0 || to->mmd.max < add->mmd.min) { clear_opt_map_info(to); return ; } alt_merge_mml(&to->mmd, &add->mmd); val = 0; for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) { if (add->map[i]) to->map[i] = 1; if (to->map[i]) val += map_position_value(enc, i); } to->value = val; alt_merge_opt_anc_info(&to->anc, &add->anc); } static void set_bound_node_opt_info(NodeOptInfo* opt, MinMaxLen* mmd) { copy_mml(&(opt->exb.mmd), mmd); copy_mml(&(opt->expr.mmd), mmd); copy_mml(&(opt->map.mmd), mmd); } static void clear_node_opt_info(NodeOptInfo* opt) { clear_mml(&opt->len); clear_opt_anc_info(&opt->anc); clear_opt_exact_info(&opt->exb); clear_opt_exact_info(&opt->exm); clear_opt_exact_info(&opt->expr); clear_opt_map_info(&opt->map); } static void copy_node_opt_info(NodeOptInfo* to, NodeOptInfo* from) { *to = *from; } static void concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add) { int exb_reach, exm_reach; OptAncInfo tanc; concat_opt_anc_info(&tanc, &to->anc, &add->anc, to->len.max, add->len.max); copy_opt_anc_info(&to->anc, &tanc); if (add->exb.len > 0 && to->len.max == 0) { concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc, to->len.max, add->len.max); copy_opt_anc_info(&add->exb.anc, &tanc); } if (add->map.value > 0 && to->len.max == 0) { if (add->map.mmd.max == 0) add->map.anc.left_anchor |= to->anc.left_anchor; } exb_reach = to->exb.reach_end; exm_reach = to->exm.reach_end; if (add->len.max != 0) to->exb.reach_end = to->exm.reach_end = 0; if (add->exb.len > 0) { if (exb_reach) { concat_opt_exact_info(&to->exb, &add->exb, enc); clear_opt_exact_info(&add->exb); } else if (exm_reach) { concat_opt_exact_info(&to->exm, &add->exb, enc); clear_opt_exact_info(&add->exb); } } select_opt_exact_info(enc, &to->exm, &add->exb); select_opt_exact_info(enc, &to->exm, &add->exm); if (to->expr.len > 0) { if (add->len.max > 0) { if (to->expr.len > (int )add->len.max) to->expr.len = (int )add->len.max; if (to->expr.mmd.max == 0) select_opt_exact_info(enc, &to->exb, &to->expr); else select_opt_exact_info(enc, &to->exm, &to->expr); } } else if (add->expr.len > 0) { copy_opt_exact_info(&to->expr, &add->expr); } select_opt_map_info(&to->map, &add->map); add_mml(&to->len, &add->len); } static void alt_merge_node_opt_info(NodeOptInfo* to, NodeOptInfo* add, OptEnv* env) { alt_merge_opt_anc_info (&to->anc, &add->anc); alt_merge_opt_exact_info(&to->exb, &add->exb, env); alt_merge_opt_exact_info(&to->exm, &add->exm, env); alt_merge_opt_exact_info(&to->expr, &add->expr, env); alt_merge_opt_map_info(env->enc, &to->map, &add->map); alt_merge_mml(&to->len, &add->len); } #define MAX_NODE_OPT_INFO_REF_COUNT 5 static int optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env) { int type; int r = 0; clear_node_opt_info(opt); set_bound_node_opt_info(opt, &env->mmd); type = NTYPE(node); switch (type) { case NT_LIST: { OptEnv nenv; NodeOptInfo nopt; Node* nd = node; copy_opt_env(&nenv, env); do { r = optimize_node_left(NCAR(nd), &nopt, &nenv); if (r == 0) { add_mml(&nenv.mmd, &nopt.len); concat_left_node_opt_info(env->enc, opt, &nopt); } } while (r == 0 && IS_NOT_NULL(nd = NCDR(nd))); } break; case NT_ALT: { NodeOptInfo nopt; Node* nd = node; do { r = optimize_node_left(NCAR(nd), &nopt, env); if (r == 0) { if (nd == node) copy_node_opt_info(opt, &nopt); else alt_merge_node_opt_info(opt, &nopt, env); } } while ((r == 0) && IS_NOT_NULL(nd = NCDR(nd))); } break; case NT_STR: { StrNode* sn = NSTR(node); OnigDistance slen = sn->end - sn->s; int is_raw = NSTRING_IS_RAW(node); if (! NSTRING_IS_AMBIG(node)) { concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, is_raw, env->enc); opt->exb.ignore_case = 0; if (slen > 0) { add_char_opt_map_info(&opt->map, *(sn->s), env->enc); } set_mml(&opt->len, slen, slen); } else { OnigDistance max; if (NSTRING_IS_DONT_GET_OPT_INFO(node)) { int n = onigenc_strlen(env->enc, sn->s, sn->end); max = ONIGENC_MBC_MAXLEN_DIST(env->enc) * n; } else { concat_opt_exact_info_str(&opt->exb, sn->s, sn->end, is_raw, env->enc); opt->exb.ignore_case = 1; if (slen > 0) { r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end, env->enc, env->case_fold_flag); if (r != 0) break; } max = slen; } set_mml(&opt->len, slen, max); } if ((OnigDistance )opt->exb.len == slen) opt->exb.reach_end = 1; } break; case NT_CCLASS: { int i, z; CClassNode* cc = NCCLASS(node); /* no need to check ignore case. (set in setup_tree()) */ if (IS_NOT_NULL(cc->mbuf) || IS_NCCLASS_NOT(cc)) { OnigDistance min = ONIGENC_MBC_MINLEN(env->enc); OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc); set_mml(&opt->len, min, max); } else { for (i = 0; i < SINGLE_BYTE_SIZE; i++) { z = BITSET_AT(cc->bs, i); if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) { add_char_opt_map_info(&opt->map, (UChar )i, env->enc); } } set_mml(&opt->len, 1, 1); } } break; case NT_CTYPE: { int i, min, max; int maxcode; max = ONIGENC_MBC_MAXLEN_DIST(env->enc); if (max == 1) { min = 1; maxcode = NCTYPE(node)->ascii_range ? 0x80 : SINGLE_BYTE_SIZE; switch (NCTYPE(node)->ctype) { case ONIGENC_CTYPE_WORD: if (NCTYPE(node)->not != 0) { for (i = 0; i < SINGLE_BYTE_SIZE; i++) { if (! ONIGENC_IS_CODE_WORD(env->enc, i) || i >= maxcode) { add_char_opt_map_info(&opt->map, (UChar )i, env->enc); } } } else { for (i = 0; i < maxcode; i++) { if (ONIGENC_IS_CODE_WORD(env->enc, i)) { add_char_opt_map_info(&opt->map, (UChar )i, env->enc); } } } break; } } else { min = ONIGENC_MBC_MINLEN(env->enc); } set_mml(&opt->len, min, max); } break; case NT_CANY: { OnigDistance min = ONIGENC_MBC_MINLEN(env->enc); OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc); set_mml(&opt->len, min, max); } break; case NT_ANCHOR: switch (NANCHOR(node)->type) { case ANCHOR_BEGIN_BUF: case ANCHOR_BEGIN_POSITION: case ANCHOR_BEGIN_LINE: case ANCHOR_END_BUF: case ANCHOR_SEMI_END_BUF: case ANCHOR_END_LINE: case ANCHOR_LOOK_BEHIND: /* just for (?<=x).* */ add_opt_anc_info(&opt->anc, NANCHOR(node)->type); break; case ANCHOR_PREC_READ: { NodeOptInfo nopt; r = optimize_node_left(NANCHOR(node)->target, &nopt, env); if (r == 0) { if (nopt.exb.len > 0) copy_opt_exact_info(&opt->expr, &nopt.exb); else if (nopt.exm.len > 0) copy_opt_exact_info(&opt->expr, &nopt.exm); opt->expr.reach_end = 0; if (nopt.map.value > 0) copy_opt_map_info(&opt->map, &nopt.map); } } break; case ANCHOR_PREC_READ_NOT: case ANCHOR_LOOK_BEHIND_NOT: break; } break; case NT_BREF: { int i; int* backs; OnigDistance min, max, tmin, tmax; Node** nodes = SCANENV_MEM_NODES(env->scan_env); BRefNode* br = NBREF(node); if (br->state & NST_RECURSION) { set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE); break; } backs = BACKREFS_P(br); r = get_min_match_length(nodes[backs[0]], &min, env->scan_env); if (r != 0) break; r = get_max_match_length(nodes[backs[0]], &max, env->scan_env); if (r != 0) break; for (i = 1; i < br->back_num; i++) { r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env); if (r != 0) break; r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env); if (r != 0) break; if (min > tmin) min = tmin; if (max < tmax) max = tmax; } if (r == 0) set_mml(&opt->len, min, max); } break; #ifdef USE_SUBEXP_CALL case NT_CALL: if (IS_CALL_RECURSION(NCALL(node))) set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE); else { OnigOptionType save = env->options; env->options = NENCLOSE(NCALL(node)->target)->option; r = optimize_node_left(NCALL(node)->target, opt, env); env->options = save; } break; #endif case NT_QTFR: { int i; OnigDistance min, max; NodeOptInfo nopt; QtfrNode* qn = NQTFR(node); r = optimize_node_left(qn->target, &nopt, env); if (r) break; if (/*qn->lower == 0 &&*/ IS_REPEAT_INFINITE(qn->upper)) { if (env->mmd.max == 0 && NTYPE(qn->target) == NT_CANY && qn->greedy) { if (IS_MULTILINE(env->options)) /* implicit anchor: /.*a/ ==> /\A.*a/ */ add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML); else add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR); } } else { if (qn->lower > 0) { copy_node_opt_info(opt, &nopt); if (nopt.exb.len > 0) { if (nopt.exb.reach_end) { for (i = 2; i <= qn->lower && ! is_full_opt_exact_info(&opt->exb); i++) { concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc); } if (i < qn->lower) { opt->exb.reach_end = 0; } } } if (qn->lower != qn->upper) { opt->exb.reach_end = 0; opt->exm.reach_end = 0; } if (qn->lower > 1) opt->exm.reach_end = 0; } } min = distance_multiply(nopt.len.min, qn->lower); if (IS_REPEAT_INFINITE(qn->upper)) max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0); else max = distance_multiply(nopt.len.max, qn->upper); set_mml(&opt->len, min, max); } break; case NT_ENCLOSE: { EncloseNode* en = NENCLOSE(node); switch (en->type) { case ENCLOSE_OPTION: { OnigOptionType save = env->options; env->options = en->option; r = optimize_node_left(en->target, opt, env); env->options = save; } break; case ENCLOSE_MEMORY: #ifdef USE_SUBEXP_CALL en->opt_count++; if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) { OnigDistance min, max; min = 0; max = ONIG_INFINITE_DISTANCE; if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len; if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len; set_mml(&opt->len, min, max); } else #endif { r = optimize_node_left(en->target, opt, env); if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) { if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum)) remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK); } } break; case ENCLOSE_STOP_BACKTRACK: case ENCLOSE_CONDITION: r = optimize_node_left(en->target, opt, env); break; } } break; default: #ifdef ONIG_DEBUG fprintf(stderr, "optimize_node_left: undefined node type %d\n", NTYPE(node)); #endif r = ONIGERR_TYPE_BUG; break; } return r; } static int set_optimize_exact_info(regex_t* reg, OptExactInfo* e) { int r; int allow_reverse; if (e->len == 0) return 0; reg->exact = (UChar* )xmalloc(e->len); CHECK_NULL_RETURN_MEMERR(reg->exact); xmemcpy(reg->exact, e->s, e->len); reg->exact_end = reg->exact + e->len; allow_reverse = ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end); if (e->ignore_case > 0) { if (e->len >= 3 || (e->len >= 2 && allow_reverse)) { r = set_bm_skip(reg->exact, reg->exact_end, reg, reg->map, &(reg->int_map), 1); if (r == 0) { reg->optimize = (allow_reverse != 0 ? ONIG_OPTIMIZE_EXACT_BM_IC : ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC); } else { reg->optimize = ONIG_OPTIMIZE_EXACT_IC; } } else { reg->optimize = ONIG_OPTIMIZE_EXACT_IC; } } else { if (e->len >= 3 || (e->len >= 2 && allow_reverse)) { r = set_bm_skip(reg->exact, reg->exact_end, reg, reg->map, &(reg->int_map), 0); if (r) return r; reg->optimize = (allow_reverse != 0 ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV); } else { reg->optimize = ONIG_OPTIMIZE_EXACT; } } reg->dmin = e->mmd.min; reg->dmax = e->mmd.max; if (reg->dmin != ONIG_INFINITE_DISTANCE) { reg->threshold_len = (int )(reg->dmin + (reg->exact_end - reg->exact)); } return 0; } static void set_optimize_map_info(regex_t* reg, OptMapInfo* m) { int i; for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) reg->map[i] = m->map[i]; reg->optimize = ONIG_OPTIMIZE_MAP; reg->dmin = m->mmd.min; reg->dmax = m->mmd.max; if (reg->dmin != ONIG_INFINITE_DISTANCE) { reg->threshold_len = (int )(reg->dmin + 1); } } static void set_sub_anchor(regex_t* reg, OptAncInfo* anc) { reg->sub_anchor |= anc->left_anchor & ANCHOR_BEGIN_LINE; reg->sub_anchor |= anc->right_anchor & ANCHOR_END_LINE; } #ifdef ONIG_DEBUG static void print_optimize_info(FILE* f, regex_t* reg); #endif static int set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env) { int r; NodeOptInfo opt; OptEnv env; env.enc = reg->enc; env.options = reg->options; env.case_fold_flag = reg->case_fold_flag; env.scan_env = scan_env; clear_mml(&env.mmd); r = optimize_node_left(node, &opt, &env); if (r) return r; reg->anchor = opt.anc.left_anchor & (ANCHOR_BEGIN_BUF | ANCHOR_BEGIN_POSITION | ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML | ANCHOR_LOOK_BEHIND); reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF); if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) { reg->anchor_dmin = opt.len.min; reg->anchor_dmax = opt.len.max; } if (opt.exb.len > 0 || opt.exm.len > 0) { select_opt_exact_info(reg->enc, &opt.exb, &opt.exm); if (opt.map.value > 0 && comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) { goto set_map; } else { r = set_optimize_exact_info(reg, &opt.exb); set_sub_anchor(reg, &opt.exb.anc); } } else if (opt.map.value > 0) { set_map: set_optimize_map_info(reg, &opt.map); set_sub_anchor(reg, &opt.map.anc); } else { reg->sub_anchor |= opt.anc.left_anchor & ANCHOR_BEGIN_LINE; if (opt.len.max == 0) reg->sub_anchor |= opt.anc.right_anchor & ANCHOR_END_LINE; } #if defined(ONIG_DEBUG_COMPILE) || defined(ONIG_DEBUG_MATCH) print_optimize_info(stderr, reg); #endif return r; } static void clear_optimize_info(regex_t* reg) { reg->optimize = ONIG_OPTIMIZE_NONE; reg->anchor = 0; reg->anchor_dmin = 0; reg->anchor_dmax = 0; reg->sub_anchor = 0; reg->exact_end = (UChar* )NULL; reg->threshold_len = 0; if (IS_NOT_NULL(reg->exact)) { xfree(reg->exact); reg->exact = (UChar* )NULL; } } #ifdef ONIG_DEBUG static void print_enc_string(FILE* fp, OnigEncoding enc, const UChar *s, const UChar *end) { fprintf(fp, "\nPATTERN: /"); if (ONIGENC_MBC_MINLEN(enc) > 1) { const UChar *p; OnigCodePoint code; p = s; while (p < end) { code = ONIGENC_MBC_TO_CODE(enc, p, end); if (code >= 0x80) { fprintf(fp, " 0x%04x ", (int )code); } else { fputc((int )code, fp); } p += enclen(enc, p); } } else { while (s < end) { fputc((int )*s, fp); s++; } } fprintf(fp, "/\n"); } static void print_distance_range(FILE* f, OnigDistance a, OnigDistance b) { if (a == ONIG_INFINITE_DISTANCE) fputs("inf", f); else fprintf(f, "(%u)", a); fputs("-", f); if (b == ONIG_INFINITE_DISTANCE) fputs("inf", f); else fprintf(f, "(%u)", b); } static void print_anchor(FILE* f, int anchor) { int q = 0; fprintf(f, "["); if (anchor & ANCHOR_BEGIN_BUF) { fprintf(f, "begin-buf"); q = 1; } if (anchor & ANCHOR_BEGIN_LINE) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "begin-line"); } if (anchor & ANCHOR_BEGIN_POSITION) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "begin-pos"); } if (anchor & ANCHOR_END_BUF) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "end-buf"); } if (anchor & ANCHOR_SEMI_END_BUF) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "semi-end-buf"); } if (anchor & ANCHOR_END_LINE) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "end-line"); } if (anchor & ANCHOR_ANYCHAR_STAR) { if (q) fprintf(f, ", "); q = 1; fprintf(f, "anychar-star"); } if (anchor & ANCHOR_ANYCHAR_STAR_ML) { if (q) fprintf(f, ", "); fprintf(f, "anychar-star-ml"); } fprintf(f, "]"); } static void print_optimize_info(FILE* f, regex_t* reg) { static const char* on[] = { "NONE", "EXACT", "EXACT_BM", "EXACT_BM_NOT_REV", "EXACT_IC", "MAP", "EXACT_BM_IC", "EXACT_BM_NOT_REV_IC" }; fprintf(f, "optimize: %s\n", on[reg->optimize]); fprintf(f, " anchor: "); print_anchor(f, reg->anchor); if ((reg->anchor & ANCHOR_END_BUF_MASK) != 0) print_distance_range(f, reg->anchor_dmin, reg->anchor_dmax); fprintf(f, "\n"); if (reg->optimize) { fprintf(f, " sub anchor: "); print_anchor(f, reg->sub_anchor); fprintf(f, "\n"); } fprintf(f, "\n"); if (reg->exact) { UChar *p; fprintf(f, "exact: ["); for (p = reg->exact; p < reg->exact_end; p++) { fputc(*p, f); } fprintf(f, "]: length: %d\n", (reg->exact_end - reg->exact)); } else if (reg->optimize & ONIG_OPTIMIZE_MAP) { int c, i, n = 0; for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) if (reg->map[i]) n++; fprintf(f, "map: n=%d\n", n); if (n > 0) { c = 0; fputc('[', f); for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) { if (reg->map[i] != 0) { if (c > 0) fputs(", ", f); c++; if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 && ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i)) fputc(i, f); else fprintf(f, "%d", i); } } fprintf(f, "]\n"); } } } #endif /* ONIG_DEBUG */ extern void onig_free_body(regex_t* reg) { if (IS_NOT_NULL(reg)) { if (IS_NOT_NULL(reg->p)) xfree(reg->p); if (IS_NOT_NULL(reg->exact)) xfree(reg->exact); if (IS_NOT_NULL(reg->int_map)) xfree(reg->int_map); if (IS_NOT_NULL(reg->int_map_backward)) xfree(reg->int_map_backward); if (IS_NOT_NULL(reg->repeat_range)) xfree(reg->repeat_range); if (IS_NOT_NULL(reg->chain)) onig_free(reg->chain); #ifdef USE_NAMED_GROUP onig_names_free(reg); #endif } } extern void onig_free(regex_t* reg) { if (IS_NOT_NULL(reg)) { onig_free_body(reg); xfree(reg); } } size_t onig_memsize(const regex_t *reg) { size_t size = sizeof(regex_t); if (IS_NULL(reg)) return 0; if (IS_NOT_NULL(reg->p)) size += reg->alloc; if (IS_NOT_NULL(reg->exact)) size += reg->exact_end - reg->exact; if (IS_NOT_NULL(reg->int_map)) size += sizeof(int) * ONIG_CHAR_TABLE_SIZE; if (IS_NOT_NULL(reg->int_map_backward)) size += sizeof(int) * ONIG_CHAR_TABLE_SIZE; if (IS_NOT_NULL(reg->repeat_range)) size += reg->repeat_range_alloc * sizeof(OnigRepeatRange); if (IS_NOT_NULL(reg->chain)) size += onig_memsize(reg->chain); return size; } size_t onig_region_memsize(const OnigRegion *regs) { size_t size = sizeof(*regs); if (IS_NULL(regs)) return 0; size += regs->allocated * (sizeof(*regs->beg) + sizeof(*regs->end)); return size; } #define REGEX_TRANSFER(to,from) do {\ (to)->state = ONIG_STATE_MODIFY;\ onig_free_body(to);\ xmemcpy(to, from, sizeof(regex_t));\ xfree(from);\ } while (0) extern void onig_transfer(regex_t* to, regex_t* from) { THREAD_ATOMIC_START; REGEX_TRANSFER(to, from); THREAD_ATOMIC_END; } #define REGEX_CHAIN_HEAD(reg) do {\ while (IS_NOT_NULL((reg)->chain)) {\ (reg) = (reg)->chain;\ }\ } while (0) extern void onig_chain_link_add(regex_t* to, regex_t* add) { THREAD_ATOMIC_START; REGEX_CHAIN_HEAD(to); to->chain = add; THREAD_ATOMIC_END; } extern void onig_chain_reduce(regex_t* reg) { regex_t *head, *prev; prev = reg; head = prev->chain; if (IS_NOT_NULL(head)) { reg->state = ONIG_STATE_MODIFY; while (IS_NOT_NULL(head->chain)) { prev = head; head = head->chain; } prev->chain = (regex_t* )NULL; REGEX_TRANSFER(reg, head); } } #ifdef ONIG_DEBUG static void print_compiled_byte_code_list P_((FILE* f, regex_t* reg)); #endif #ifdef ONIG_DEBUG_PARSE_TREE static void print_tree P_((FILE* f, Node* node)); #endif extern int onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo) { #define COMPILE_INIT_SIZE 20 int r; OnigDistance init_size; Node* root; ScanEnv scan_env = {0}; #ifdef USE_SUBEXP_CALL UnsetAddrList uslist; #endif if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL; reg->state = ONIG_STATE_COMPILING; #ifdef ONIG_DEBUG print_enc_string(stderr, reg->enc, pattern, pattern_end); #endif if (reg->alloc == 0) { init_size = (pattern_end - pattern) * 2; if (init_size <= 0) init_size = COMPILE_INIT_SIZE; r = BBUF_INIT(reg, init_size); if (r != 0) goto end; } else reg->used = 0; reg->num_mem = 0; reg->num_repeat = 0; reg->num_null_check = 0; reg->repeat_range_alloc = 0; reg->repeat_range = (OnigRepeatRange* )NULL; #ifdef USE_COMBINATION_EXPLOSION_CHECK reg->num_comb_exp_check = 0; #endif r = onig_parse_make_tree(&root, pattern, pattern_end, reg, &scan_env); if (r != 0) goto err; #ifdef USE_NAMED_GROUP /* mixed use named group and no-named group */ if (scan_env.num_named > 0 && IS_SYNTAX_BV(scan_env.syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) && !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) { if (scan_env.num_named != scan_env.num_mem) r = disable_noname_group_capture(&root, reg, &scan_env); else r = numbered_ref_check(root); if (r != 0) goto err; } #endif #ifdef USE_SUBEXP_CALL if (scan_env.num_call > 0) { r = unset_addr_list_init(&uslist, scan_env.num_call); if (r != 0) goto err; scan_env.unset_addr_list = &uslist; r = setup_subexp_call(root, &scan_env); if (r != 0) goto err_unset; r = subexp_recursive_check_trav(root, &scan_env); if (r < 0) goto err_unset; r = subexp_inf_recursive_check_trav(root, &scan_env); if (r != 0) goto err_unset; reg->num_call = scan_env.num_call; } else reg->num_call = 0; #endif r = setup_tree(root, reg, IN_ROOT, &scan_env); if (r != 0) goto err_unset; #ifdef ONIG_DEBUG_PARSE_TREE print_tree(stderr, root); #endif reg->capture_history = scan_env.capture_history; reg->bt_mem_start = scan_env.bt_mem_start; reg->bt_mem_start |= reg->capture_history; if (IS_FIND_CONDITION(reg->options)) BIT_STATUS_ON_ALL(reg->bt_mem_end); else { reg->bt_mem_end = scan_env.bt_mem_end; reg->bt_mem_end |= reg->capture_history; } #ifdef USE_COMBINATION_EXPLOSION_CHECK if (scan_env.backrefed_mem == 0 #ifdef USE_SUBEXP_CALL || scan_env.num_call == 0 #endif ) { setup_comb_exp_check(root, 0, &scan_env); #ifdef USE_SUBEXP_CALL if (scan_env.has_recursion != 0) { scan_env.num_comb_exp_check = 0; } else #endif if (scan_env.comb_exp_max_regnum > 0) { int i; for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) { if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) { scan_env.num_comb_exp_check = 0; break; } } } } reg->num_comb_exp_check = scan_env.num_comb_exp_check; #endif clear_optimize_info(reg); #ifndef ONIG_DONT_OPTIMIZE r = set_optimize_info_from_tree(root, reg, &scan_env); if (r != 0) goto err_unset; #endif if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) { xfree(scan_env.mem_nodes_dynamic); scan_env.mem_nodes_dynamic = (Node** )NULL; } if (IS_WHOLEWORD(reg->options)) r = add_opcode(reg, OP_WORD_BEGIN); r = compile_tree(root, reg); if (r == 0) { if (IS_WHOLEWORD(reg->options)) r = add_opcode(reg, OP_WORD_END); r = add_opcode(reg, OP_END); #ifdef USE_SUBEXP_CALL if (scan_env.num_call > 0) { r = unset_addr_list_fix(&uslist, reg); unset_addr_list_end(&uslist); if (r) goto err; } #endif if ((reg->num_repeat != 0) || (reg->bt_mem_end != 0)) reg->stack_pop_level = STACK_POP_LEVEL_ALL; else { if (reg->bt_mem_start != 0) reg->stack_pop_level = STACK_POP_LEVEL_MEM_START; else reg->stack_pop_level = STACK_POP_LEVEL_FREE; } } #ifdef USE_SUBEXP_CALL else if (scan_env.num_call > 0) { unset_addr_list_end(&uslist); } #endif onig_node_free(root); #ifdef ONIG_DEBUG_COMPILE #ifdef USE_NAMED_GROUP onig_print_names(stderr, reg); #endif print_compiled_byte_code_list(stderr, reg); #endif end: reg->state = ONIG_STATE_NORMAL; return r; err_unset: #ifdef USE_SUBEXP_CALL if (scan_env.num_call > 0) { unset_addr_list_end(&uslist); } #endif err: if (IS_NOT_NULL(scan_env.error)) { if (IS_NOT_NULL(einfo)) { einfo->enc = scan_env.enc; einfo->par = scan_env.error; einfo->par_end = scan_env.error_end; } } onig_node_free(root); if (IS_NOT_NULL(scan_env.mem_nodes_dynamic)) xfree(scan_env.mem_nodes_dynamic); return r; } #ifdef USE_RECOMPILE_API extern int onig_recompile(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo) { int r; regex_t *new_reg; r = onig_new(&new_reg, pattern, pattern_end, option, enc, syntax, einfo); if (r) return r; if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_transfer(reg, new_reg); } else { onig_chain_link_add(reg, new_reg); } return 0; } #endif static int onig_inited = 0; extern int onig_reg_init(regex_t* reg, OnigOptionType option, OnigCaseFoldType case_fold_flag, OnigEncoding enc, OnigSyntaxType* syntax) { if (! onig_inited) onig_init(); if (IS_NULL(reg)) return ONIGERR_INVALID_ARGUMENT; if (ONIGENC_IS_UNDEF(enc)) return ONIGERR_DEFAULT_ENCODING_IS_NOT_SET; if ((option & (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP)) == (ONIG_OPTION_DONT_CAPTURE_GROUP|ONIG_OPTION_CAPTURE_GROUP)) { return ONIGERR_INVALID_COMBINATION_OF_OPTIONS; } (reg)->state = ONIG_STATE_MODIFY; if ((option & ONIG_OPTION_NEGATE_SINGLELINE) != 0) { option |= syntax->options; option &= ~ONIG_OPTION_SINGLELINE; } else option |= syntax->options; (reg)->enc = enc; (reg)->options = option; (reg)->syntax = syntax; (reg)->optimize = 0; (reg)->exact = (UChar* )NULL; (reg)->int_map = (int* )NULL; (reg)->int_map_backward = (int* )NULL; (reg)->chain = (regex_t* )NULL; (reg)->p = (UChar* )NULL; (reg)->alloc = 0; (reg)->used = 0; (reg)->name_table = (void* )NULL; (reg)->case_fold_flag = case_fold_flag; return 0; } extern int onig_new_without_alloc(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo) { int r; r = onig_reg_init(reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax); if (r) return r; r = onig_compile(reg, pattern, pattern_end, einfo); return r; } extern int onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigOptionType option, OnigEncoding enc, OnigSyntaxType* syntax, OnigErrorInfo* einfo) { int r; *reg = (regex_t* )xmalloc(sizeof(regex_t)); if (IS_NULL(*reg)) return ONIGERR_MEMORY; r = onig_reg_init(*reg, option, ONIGENC_CASE_FOLD_DEFAULT, enc, syntax); if (r) goto err; r = onig_compile(*reg, pattern, pattern_end, einfo); if (r) { err: onig_free(*reg); *reg = NULL; } return r; } extern int onig_init(void) { if (onig_inited != 0) return 0; THREAD_SYSTEM_INIT; THREAD_ATOMIC_START; onig_inited = 1; onigenc_init(); /* onigenc_set_default_caseconv_table((UChar* )0); */ #ifdef ONIG_DEBUG_STATISTICS onig_statistics_init(); #endif THREAD_ATOMIC_END; return 0; } extern int onig_end(void) { THREAD_ATOMIC_START; #ifdef ONIG_DEBUG_STATISTICS onig_print_statistics(stderr); #endif #ifdef USE_SHARED_CCLASS_TABLE onig_free_shared_cclass_table(); #endif #ifdef USE_PARSE_TREE_NODE_RECYCLE onig_free_node_list(); #endif #ifdef USE_SHARED_UNICODE_TABLE onig_free_shared_unicode_table(); #endif onig_inited = 0; THREAD_ATOMIC_END; THREAD_SYSTEM_END; return 0; } extern int onig_is_in_code_range(const UChar* p, OnigCodePoint code) { OnigCodePoint n, *data; OnigCodePoint low, high, x; GET_CODE_POINT(n, p); data = (OnigCodePoint* )p; data++; for (low = 0, high = n; low < high; ) { x = (low + high) >> 1; if (code > data[x * 2 + 1]) low = x + 1; else high = x; } return ((low < n && code >= data[low * 2]) ? 1 : 0); } extern int onig_is_code_in_cc_len(int elen, OnigCodePoint code, CClassNode* cc) { int found; if (elen > 1 || (code >= SINGLE_BYTE_SIZE)) { if (IS_NULL(cc->mbuf)) { found = 0; } else { found = (onig_is_in_code_range(cc->mbuf->p, code) != 0 ? 1 : 0); } } else { found = (BITSET_AT(cc->bs, code) == 0 ? 0 : 1); } if (IS_NCCLASS_NOT(cc)) return !found; else return found; } extern int onig_is_code_in_cc(OnigEncoding enc, OnigCodePoint code, CClassNode* cc) { int len; if (ONIGENC_MBC_MINLEN(enc) > 1) { len = 2; } else { len = ONIGENC_CODE_TO_MBCLEN(enc, code); } return onig_is_code_in_cc_len(len, code, cc); } #ifdef ONIG_DEBUG /* arguments type */ #define ARG_SPECIAL -1 #define ARG_NON 0 #define ARG_RELADDR 1 #define ARG_ABSADDR 2 #define ARG_LENGTH 3 #define ARG_MEMNUM 4 #define ARG_OPTION 5 #define ARG_STATE_CHECK 6 OnigOpInfoType OnigOpInfo[] = { { OP_FINISH, "finish", ARG_NON }, { OP_END, "end", ARG_NON }, { OP_EXACT1, "exact1", ARG_SPECIAL }, { OP_EXACT2, "exact2", ARG_SPECIAL }, { OP_EXACT3, "exact3", ARG_SPECIAL }, { OP_EXACT4, "exact4", ARG_SPECIAL }, { OP_EXACT5, "exact5", ARG_SPECIAL }, { OP_EXACTN, "exactn", ARG_SPECIAL }, { OP_EXACTMB2N1, "exactmb2-n1", ARG_SPECIAL }, { OP_EXACTMB2N2, "exactmb2-n2", ARG_SPECIAL }, { OP_EXACTMB2N3, "exactmb2-n3", ARG_SPECIAL }, { OP_EXACTMB2N, "exactmb2-n", ARG_SPECIAL }, { OP_EXACTMB3N, "exactmb3n" , ARG_SPECIAL }, { OP_EXACTMBN, "exactmbn", ARG_SPECIAL }, { OP_EXACT1_IC, "exact1-ic", ARG_SPECIAL }, { OP_EXACTN_IC, "exactn-ic", ARG_SPECIAL }, { OP_CCLASS, "cclass", ARG_SPECIAL }, { OP_CCLASS_MB, "cclass-mb", ARG_SPECIAL }, { OP_CCLASS_MIX, "cclass-mix", ARG_SPECIAL }, { OP_CCLASS_NOT, "cclass-not", ARG_SPECIAL }, { OP_CCLASS_MB_NOT, "cclass-mb-not", ARG_SPECIAL }, { OP_CCLASS_MIX_NOT, "cclass-mix-not", ARG_SPECIAL }, { OP_CCLASS_NODE, "cclass-node", ARG_SPECIAL }, { OP_ANYCHAR, "anychar", ARG_NON }, { OP_ANYCHAR_ML, "anychar-ml", ARG_NON }, { OP_ANYCHAR_STAR, "anychar*", ARG_NON }, { OP_ANYCHAR_ML_STAR, "anychar-ml*", ARG_NON }, { OP_ANYCHAR_STAR_PEEK_NEXT, "anychar*-peek-next", ARG_SPECIAL }, { OP_ANYCHAR_ML_STAR_PEEK_NEXT, "anychar-ml*-peek-next", ARG_SPECIAL }, { OP_WORD, "word", ARG_NON }, { OP_NOT_WORD, "not-word", ARG_NON }, { OP_WORD_BOUND, "word-bound", ARG_NON }, { OP_NOT_WORD_BOUND, "not-word-bound", ARG_NON }, { OP_WORD_BEGIN, "word-begin", ARG_NON }, { OP_WORD_END, "word-end", ARG_NON }, { OP_ASCII_WORD, "ascii-word", ARG_NON }, { OP_NOT_ASCII_WORD, "not-ascii-word", ARG_NON }, { OP_ASCII_WORD_BOUND, "ascii-word-bound", ARG_NON }, { OP_NOT_ASCII_WORD_BOUND,"not-ascii-word-bound", ARG_NON }, { OP_ASCII_WORD_BEGIN, "ascii-word-begin", ARG_NON }, { OP_ASCII_WORD_END, "ascii-word-end", ARG_NON }, { OP_BEGIN_BUF, "begin-buf", ARG_NON }, { OP_END_BUF, "end-buf", ARG_NON }, { OP_BEGIN_LINE, "begin-line", ARG_NON }, { OP_END_LINE, "end-line", ARG_NON }, { OP_SEMI_END_BUF, "semi-end-buf", ARG_NON }, { OP_BEGIN_POSITION, "begin-position", ARG_NON }, { OP_BEGIN_POS_OR_LINE, "begin-pos-or-line", ARG_NON }, { OP_BACKREF1, "backref1", ARG_NON }, { OP_BACKREF2, "backref2", ARG_NON }, { OP_BACKREFN, "backrefn", ARG_MEMNUM }, { OP_BACKREFN_IC, "backrefn-ic", ARG_SPECIAL }, { OP_BACKREF_MULTI, "backref_multi", ARG_SPECIAL }, { OP_BACKREF_MULTI_IC, "backref_multi-ic", ARG_SPECIAL }, { OP_BACKREF_WITH_LEVEL, "backref_at_level", ARG_SPECIAL }, { OP_MEMORY_START_PUSH, "mem-start-push", ARG_MEMNUM }, { OP_MEMORY_START, "mem-start", ARG_MEMNUM }, { OP_MEMORY_END_PUSH, "mem-end-push", ARG_MEMNUM }, { OP_MEMORY_END_PUSH_REC, "mem-end-push-rec", ARG_MEMNUM }, { OP_MEMORY_END, "mem-end", ARG_MEMNUM }, { OP_MEMORY_END_REC, "mem-end-rec", ARG_MEMNUM }, { OP_SET_OPTION_PUSH, "set-option-push", ARG_OPTION }, { OP_SET_OPTION, "set-option", ARG_OPTION }, { OP_KEEP, "keep", ARG_NON }, { OP_FAIL, "fail", ARG_NON }, { OP_JUMP, "jump", ARG_RELADDR }, { OP_PUSH, "push", ARG_RELADDR }, { OP_POP, "pop", ARG_NON }, { OP_PUSH_OR_JUMP_EXACT1, "push-or-jump-e1", ARG_SPECIAL }, { OP_PUSH_IF_PEEK_NEXT, "push-if-peek-next", ARG_SPECIAL }, { OP_REPEAT, "repeat", ARG_SPECIAL }, { OP_REPEAT_NG, "repeat-ng", ARG_SPECIAL }, { OP_REPEAT_INC, "repeat-inc", ARG_MEMNUM }, { OP_REPEAT_INC_NG, "repeat-inc-ng", ARG_MEMNUM }, { OP_REPEAT_INC_SG, "repeat-inc-sg", ARG_MEMNUM }, { OP_REPEAT_INC_NG_SG, "repeat-inc-ng-sg", ARG_MEMNUM }, { OP_NULL_CHECK_START, "null-check-start", ARG_MEMNUM }, { OP_NULL_CHECK_END, "null-check-end", ARG_MEMNUM }, { OP_NULL_CHECK_END_MEMST,"null-check-end-memst", ARG_MEMNUM }, { OP_NULL_CHECK_END_MEMST_PUSH,"null-check-end-memst-push", ARG_MEMNUM }, { OP_PUSH_POS, "push-pos", ARG_NON }, { OP_POP_POS, "pop-pos", ARG_NON }, { OP_PUSH_POS_NOT, "push-pos-not", ARG_RELADDR }, { OP_FAIL_POS, "fail-pos", ARG_NON }, { OP_PUSH_STOP_BT, "push-stop-bt", ARG_NON }, { OP_POP_STOP_BT, "pop-stop-bt", ARG_NON }, { OP_LOOK_BEHIND, "look-behind", ARG_SPECIAL }, { OP_PUSH_LOOK_BEHIND_NOT, "push-look-behind-not", ARG_SPECIAL }, { OP_FAIL_LOOK_BEHIND_NOT, "fail-look-behind-not", ARG_NON }, { OP_CALL, "call", ARG_ABSADDR }, { OP_RETURN, "return", ARG_NON }, { OP_CONDITION, "condition", ARG_SPECIAL }, { OP_STATE_CHECK_PUSH, "state-check-push", ARG_SPECIAL }, { OP_STATE_CHECK_PUSH_OR_JUMP, "state-check-push-or-jump", ARG_SPECIAL }, { OP_STATE_CHECK, "state-check", ARG_STATE_CHECK }, { OP_STATE_CHECK_ANYCHAR_STAR, "state-check-anychar*", ARG_STATE_CHECK }, { OP_STATE_CHECK_ANYCHAR_ML_STAR, "state-check-anychar-ml*", ARG_STATE_CHECK }, { -1, "", ARG_NON } }; static const char* op2name(int opcode) { int i; for (i = 0; OnigOpInfo[i].opcode >= 0; i++) { if (opcode == OnigOpInfo[i].opcode) return OnigOpInfo[i].name; } return ""; } static int op2arg_type(int opcode) { int i; for (i = 0; OnigOpInfo[i].opcode >= 0; i++) { if (opcode == OnigOpInfo[i].opcode) return OnigOpInfo[i].arg_type; } return ARG_SPECIAL; } static void Indent(FILE* f, int indent) { int i; for (i = 0; i < indent; i++) putc(' ', f); } static void p_string(FILE* f, int len, UChar* s) { fputs(":", f); while (len-- > 0) { fputc(*s++, f); } } static void p_len_string(FILE* f, LengthType len, int mb_len, UChar* s) { int x = len * mb_len; fprintf(f, ":%d:", len); while (x-- > 0) { fputc(*s++, f); } } extern void onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar** nextp, OnigEncoding enc) { int i, n, arg_type; RelAddrType addr; LengthType len; MemNumType mem; StateCheckNumType scn; OnigCodePoint code; UChar *q; fprintf(f, "[%s", op2name(*bp)); arg_type = op2arg_type(*bp); if (arg_type != ARG_SPECIAL) { bp++; switch (arg_type) { case ARG_NON: break; case ARG_RELADDR: GET_RELADDR_INC(addr, bp); fprintf(f, ":(%d)", addr); break; case ARG_ABSADDR: GET_ABSADDR_INC(addr, bp); fprintf(f, ":(%d)", addr); break; case ARG_LENGTH: GET_LENGTH_INC(len, bp); fprintf(f, ":%d", len); break; case ARG_MEMNUM: mem = *((MemNumType* )bp); bp += SIZE_MEMNUM; fprintf(f, ":%d", mem); break; case ARG_OPTION: { OnigOptionType option = *((OnigOptionType* )bp); bp += SIZE_OPTION; fprintf(f, ":%d", option); } break; case ARG_STATE_CHECK: scn = *((StateCheckNumType* )bp); bp += SIZE_STATE_CHECK_NUM; fprintf(f, ":%d", scn); break; } } else { switch (*bp++) { case OP_EXACT1: case OP_ANYCHAR_STAR_PEEK_NEXT: case OP_ANYCHAR_ML_STAR_PEEK_NEXT: p_string(f, 1, bp++); break; case OP_EXACT2: p_string(f, 2, bp); bp += 2; break; case OP_EXACT3: p_string(f, 3, bp); bp += 3; break; case OP_EXACT4: p_string(f, 4, bp); bp += 4; break; case OP_EXACT5: p_string(f, 5, bp); bp += 5; break; case OP_EXACTN: GET_LENGTH_INC(len, bp); p_len_string(f, len, 1, bp); bp += len; break; case OP_EXACTMB2N1: p_string(f, 2, bp); bp += 2; break; case OP_EXACTMB2N2: p_string(f, 4, bp); bp += 4; break; case OP_EXACTMB2N3: p_string(f, 6, bp); bp += 6; break; case OP_EXACTMB2N: GET_LENGTH_INC(len, bp); p_len_string(f, len, 2, bp); bp += len * 2; break; case OP_EXACTMB3N: GET_LENGTH_INC(len, bp); p_len_string(f, len, 3, bp); bp += len * 3; break; case OP_EXACTMBN: { int mb_len; GET_LENGTH_INC(mb_len, bp); GET_LENGTH_INC(len, bp); fprintf(f, ":%d:%d:", mb_len, len); n = len * mb_len; while (n-- > 0) { fputc(*bp++, f); } } break; case OP_EXACT1_IC: len = enclen(enc, bp); p_string(f, len, bp); bp += len; break; case OP_EXACTN_IC: GET_LENGTH_INC(len, bp); p_len_string(f, len, 1, bp); bp += len; break; case OP_CCLASS: n = bitset_on_num((BitSetRef )bp); bp += SIZE_BITSET; fprintf(f, ":%d", n); break; case OP_CCLASS_NOT: n = bitset_on_num((BitSetRef )bp); bp += SIZE_BITSET; fprintf(f, ":%d", n); break; case OP_CCLASS_MB: case OP_CCLASS_MB_NOT: GET_LENGTH_INC(len, bp); q = bp; #ifndef PLATFORM_UNALIGNED_WORD_ACCESS ALIGNMENT_RIGHT(q); #endif GET_CODE_POINT(code, q); bp += len; fprintf(f, ":%d:%d", (int )code, len); break; case OP_CCLASS_MIX: case OP_CCLASS_MIX_NOT: n = bitset_on_num((BitSetRef )bp); bp += SIZE_BITSET; GET_LENGTH_INC(len, bp); q = bp; #ifndef PLATFORM_UNALIGNED_WORD_ACCESS ALIGNMENT_RIGHT(q); #endif GET_CODE_POINT(code, q); bp += len; fprintf(f, ":%d:%d:%d", n, (int )code, len); break; case OP_CCLASS_NODE: { CClassNode *cc; GET_POINTER_INC(cc, bp); n = bitset_on_num(cc->bs); fprintf(f, ":%u:%d", (unsigned int )cc, n); } break; case OP_BACKREFN_IC: mem = *((MemNumType* )bp); bp += SIZE_MEMNUM; fprintf(f, ":%d", mem); break; case OP_BACKREF_MULTI_IC: case OP_BACKREF_MULTI: fputs(" ", f); GET_LENGTH_INC(len, bp); for (i = 0; i < len; i++) { GET_MEMNUM_INC(mem, bp); if (i > 0) fputs(", ", f); fprintf(f, "%d", mem); } break; case OP_BACKREF_WITH_LEVEL: { OnigOptionType option; LengthType level; GET_OPTION_INC(option, bp); fprintf(f, ":%d", option); GET_LENGTH_INC(level, bp); fprintf(f, ":%d", level); fputs(" ", f); GET_LENGTH_INC(len, bp); for (i = 0; i < len; i++) { GET_MEMNUM_INC(mem, bp); if (i > 0) fputs(", ", f); fprintf(f, "%d", mem); } } break; case OP_REPEAT: case OP_REPEAT_NG: { mem = *((MemNumType* )bp); bp += SIZE_MEMNUM; addr = *((RelAddrType* )bp); bp += SIZE_RELADDR; fprintf(f, ":%d:%d", mem, addr); } break; case OP_PUSH_OR_JUMP_EXACT1: case OP_PUSH_IF_PEEK_NEXT: addr = *((RelAddrType* )bp); bp += SIZE_RELADDR; fprintf(f, ":(%d)", addr); p_string(f, 1, bp); bp += 1; break; case OP_LOOK_BEHIND: GET_LENGTH_INC(len, bp); fprintf(f, ":%d", len); break; case OP_PUSH_LOOK_BEHIND_NOT: GET_RELADDR_INC(addr, bp); GET_LENGTH_INC(len, bp); fprintf(f, ":%d:(%d)", len, addr); break; case OP_STATE_CHECK_PUSH: case OP_STATE_CHECK_PUSH_OR_JUMP: scn = *((StateCheckNumType* )bp); bp += SIZE_STATE_CHECK_NUM; addr = *((RelAddrType* )bp); bp += SIZE_RELADDR; fprintf(f, ":%d:(%d)", scn, addr); break; case OP_CONDITION: GET_MEMNUM_INC(mem, bp); GET_RELADDR_INC(addr, bp); fprintf(f, ":%d:(%d)", mem, addr); break; default: fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n", *--bp); } } fputs("]", f); if (nextp) *nextp = bp; } static void print_compiled_byte_code_list(FILE* f, regex_t* reg) { int ncode; UChar* bp = reg->p; UChar* end = reg->p + reg->used; fprintf(f, "code length: %d", reg->used); ncode = -1; while (bp < end) { ncode++; if (ncode % 5 == 0) fprintf(f, "\n%ld:", bp - reg->p); else fprintf(f, " %ld:", bp - reg->p); onig_print_compiled_byte_code(f, bp, &bp, reg->enc); } fprintf(f, "\n"); } static void print_indent_tree(FILE* f, Node* node, int indent) { int i, type, container_p = 0; int add = 3; UChar* p; Indent(f, indent); if (IS_NULL(node)) { fprintf(f, "ERROR: null node!!!\n"); exit (0); } type = NTYPE(node); switch (type) { case NT_LIST: case NT_ALT: if (NTYPE(node) == NT_LIST) fprintf(f, "\n", (int )node); else fprintf(f, "\n", (int )node); print_indent_tree(f, NCAR(node), indent + add); while (IS_NOT_NULL(node = NCDR(node))) { if (NTYPE(node) != type) { fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node)); exit(0); } print_indent_tree(f, NCAR(node), indent + add); } break; case NT_STR: fprintf(f, "", (NSTRING_IS_RAW(node) ? "-raw" : ""), (int )node); for (p = NSTR(node)->s; p < NSTR(node)->end; p++) { if (*p >= 0x20 && *p < 0x7f) fputc(*p, f); else { fprintf(f, " 0x%02x", *p); } } break; case NT_CCLASS: fprintf(f, "", (int )node); if (IS_NCCLASS_NOT(NCCLASS(node))) fputs(" not", f); if (NCCLASS(node)->mbuf) { BBuf* bbuf = NCCLASS(node)->mbuf; for (i = 0; i < (int )bbuf->used; i++) { if (i > 0) fprintf(f, ","); fprintf(f, "%0x", bbuf->p[i]); } } break; case NT_CTYPE: fprintf(f, " ", (int )node); switch (NCTYPE(node)->ctype) { case ONIGENC_CTYPE_WORD: if (NCTYPE(node)->not != 0) fputs("not word", f); else fputs("word", f); break; default: fprintf(f, "ERROR: undefined ctype.\n"); exit(0); } break; case NT_CANY: fprintf(f, "", (int )node); break; case NT_ANCHOR: fprintf(f, " ", (int )node); switch (NANCHOR(node)->type) { case ANCHOR_BEGIN_BUF: fputs("begin buf", f); break; case ANCHOR_END_BUF: fputs("end buf", f); break; case ANCHOR_BEGIN_LINE: fputs("begin line", f); break; case ANCHOR_END_LINE: fputs("end line", f); break; case ANCHOR_SEMI_END_BUF: fputs("semi end buf", f); break; case ANCHOR_BEGIN_POSITION: fputs("begin position", f); break; case ANCHOR_ANYCHAR_STAR: fputs("begin position/line", f); break; case ANCHOR_WORD_BOUND: fputs("word bound", f); break; case ANCHOR_NOT_WORD_BOUND: fputs("not word bound", f); break; #ifdef USE_WORD_BEGIN_END case ANCHOR_WORD_BEGIN: fputs("word begin", f); break; case ANCHOR_WORD_END: fputs("word end", f); break; #endif case ANCHOR_PREC_READ: fputs("prec read", f); container_p = TRUE; break; case ANCHOR_PREC_READ_NOT: fputs("prec read not", f); container_p = TRUE; break; case ANCHOR_LOOK_BEHIND: fputs("look_behind", f); container_p = TRUE; break; case ANCHOR_LOOK_BEHIND_NOT: fputs("look_behind_not",f); container_p = TRUE; break; case ANCHOR_KEEP: fputs("keep",f); break; default: fprintf(f, "ERROR: undefined anchor type.\n"); break; } break; case NT_BREF: { int* p; BRefNode* br = NBREF(node); p = BACKREFS_P(br); fprintf(f, "", (int )node); for (i = 0; i < br->back_num; i++) { if (i > 0) fputs(", ", f); fprintf(f, "%d", p[i]); } } break; #ifdef USE_SUBEXP_CALL case NT_CALL: { CallNode* cn = NCALL(node); fprintf(f, "", (int )node); p_string(f, cn->name_end - cn->name, cn->name); } break; #endif case NT_QTFR: fprintf(f, "{%d,%d}%s\n", (int )node, NQTFR(node)->lower, NQTFR(node)->upper, (NQTFR(node)->greedy ? "" : "?")); print_indent_tree(f, NQTFR(node)->target, indent + add); break; case NT_ENCLOSE: fprintf(f, " ", (int )node); switch (NENCLOSE(node)->type) { case ENCLOSE_OPTION: fprintf(f, "option:%d", NENCLOSE(node)->option); break; case ENCLOSE_MEMORY: fprintf(f, "memory:%d", NENCLOSE(node)->regnum); break; case ENCLOSE_STOP_BACKTRACK: fprintf(f, "stop-bt"); break; case ENCLOSE_CONDITION: fprintf(f, "condition:%d", NENCLOSE(node)->regnum); break; default: break; } fprintf(f, "\n"); print_indent_tree(f, NENCLOSE(node)->target, indent + add); break; default: fprintf(f, "print_indent_tree: undefined node type %d\n", NTYPE(node)); break; } if (type != NT_LIST && type != NT_ALT && type != NT_QTFR && type != NT_ENCLOSE) fprintf(f, "\n"); if (container_p) print_indent_tree(f, NANCHOR(node)->target, indent + add); fflush(f); } #endif /* ONIG_DEBUG */ #ifdef ONIG_DEBUG_PARSE_TREE static void print_tree(FILE* f, Node* node) { print_indent_tree(f, node, 0); } #endif ================================================ FILE: src/Onigmo/regenc.c ================================================ /********************************************************************** regenc.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" OnigEncoding OnigEncDefaultCharEncoding = ONIG_ENCODING_INIT_DEFAULT; extern int onigenc_init(void) { return 0; } extern OnigEncoding onigenc_get_default_encoding(void) { return OnigEncDefaultCharEncoding; } extern int onigenc_set_default_encoding(OnigEncoding enc) { OnigEncDefaultCharEncoding = enc; return 0; } extern UChar* onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); if (p < s) { p += enclen(enc, p); } return p; } extern OnigPosition onigenc_get_right_adjust_char_head_se(OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s) { OnigPosition p = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, start, s); if (p < s) { p += enclen_se(it, enc, p); } return p; } extern UChar* onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc, const UChar* start, const UChar* s, const UChar** prev) { UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); if (p < s) { if (prev) *prev = (const UChar* )p; p += enclen(enc, p); } else { if (prev) *prev = (const UChar* )NULL; /* Sorry */ } return p; } extern OnigPosition onigenc_get_right_adjust_char_head_with_prev_se(OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s, OnigPosition* prev) { OnigPosition p = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, start, s); if (p < s) { if (prev) *prev = p; p += enclen_se(it, enc, p); } else { if (prev) *prev = ONIG_BADPOS; /* Sorry */ } return p; } extern UChar* onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { if (s <= start) return (UChar* )NULL; return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1); } extern OnigPosition onigenc_get_prev_char_head_se(OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s) { if (s <= start) return ONIG_BADPOS; return ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, start, s - 1); } extern UChar* onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, int n) { while (ONIG_IS_NOT_NULL(s) && n-- > 0) { if (s <= start) return (UChar* )NULL; s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1); } return (UChar* )s; } extern OnigPosition onigenc_step_back_se(OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s, int n) { while (ONIG_IS_NOT_BADPOS(s) && n-- > 0) { if (s <= start) return ONIG_BADPOS; s = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, start, s - 1); } return s; } extern UChar* onigenc_step(OnigEncoding enc, const UChar* p, const UChar* end, int n) { UChar* q = (UChar* )p; while (n-- > 0) { q += ONIGENC_MBC_ENC_LEN(enc, q); } return (q <= end ? q : NULL); } extern int onigenc_strlen(OnigEncoding enc, const UChar* p, const UChar* end) { int n = 0; UChar* q = (UChar* )p; while (q < end) { q += ONIGENC_MBC_ENC_LEN(enc, q); n++; } return n; } extern int onigenc_strlen_se(OnigIterator* it, OnigEncoding enc, OnigPosition p, OnigPosition end) { int n = 0; while (p < end) { p += ONIGENC_MBC_ENC_LEN_SE(it, enc, p); n++; } return n; } extern int onigenc_strlen_null(OnigEncoding enc, const UChar* s) { int n = 0; UChar* p = (UChar* )s; while (1) { if (*p == '\0') { UChar* q; int len = ONIGENC_MBC_MINLEN(enc); if (len == 1) return n; q = p + 1; while (len > 1) { if (*q != '\0') break; q++; len--; } if (len == 1) return n; } p += ONIGENC_MBC_ENC_LEN(enc, p); n++; } } extern int onigenc_str_bytelen_null(OnigEncoding enc, const UChar* s) { UChar* start = (UChar* )s; UChar* p = (UChar* )s; while (1) { if (*p == '\0') { UChar* q; int len = ONIGENC_MBC_MINLEN(enc); if (len == 1) return (int )(p - start); q = p + 1; while (len > 1) { if (*q != '\0') break; q++; len--; } if (len == 1) return (int )(p - start); } p += ONIGENC_MBC_ENC_LEN(enc, p); } } extern OnigPosition onigenc_str_bytelen_null_se(OnigIterator* it, OnigEncoding enc, OnigPosition s) { OnigPosition start = s; OnigPosition p = s; while (1) { if (ONIG_CHARAT(p) == '\0') { OnigPosition q; int len = ONIGENC_MBC_MINLEN(enc); if (len == 1) return p - start; q = p + 1; while (len > 1) { if (ONIG_CHARAT(q) != '\0') break; q++; len--; } if (len == 1) return p - start; } p += ONIGENC_MBC_ENC_LEN_SE(it, enc, p); } } const UChar OnigEncAsciiToLowerCaseTable[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; #ifdef USE_UPPER_CASE_TABLE const UChar OnigEncAsciiToUpperCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; #endif const unsigned short OnigEncAsciiCtypeTable[256] = { 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0, 0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; const UChar OnigEncISO_8859_1_ToLowerCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\327', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377' }; #ifdef USE_UPPER_CASE_TABLE const UChar OnigEncISO_8859_1_ToUpperCaseTable[256] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', '\140', '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', '\130', '\131', '\132', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\367', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\377', }; #endif extern void onigenc_set_default_caseconv_table(const UChar* table ARG_UNUSED) { /* nothing */ /* obsoleted. */ } extern UChar* onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s) { return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s); } extern OnigPosition onigenc_get_left_adjust_char_head_se(OnigIterator* it, OnigEncoding enc, OnigPosition start, OnigPosition s) { return ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, start, s); } const OnigPairCaseFoldCodes OnigAsciiLowerMap[] = { { 0x41, 0x61 }, { 0x42, 0x62 }, { 0x43, 0x63 }, { 0x44, 0x64 }, { 0x45, 0x65 }, { 0x46, 0x66 }, { 0x47, 0x67 }, { 0x48, 0x68 }, { 0x49, 0x69 }, { 0x4a, 0x6a }, { 0x4b, 0x6b }, { 0x4c, 0x6c }, { 0x4d, 0x6d }, { 0x4e, 0x6e }, { 0x4f, 0x6f }, { 0x50, 0x70 }, { 0x51, 0x71 }, { 0x52, 0x72 }, { 0x53, 0x73 }, { 0x54, 0x74 }, { 0x55, 0x75 }, { 0x56, 0x76 }, { 0x57, 0x77 }, { 0x58, 0x78 }, { 0x59, 0x79 }, { 0x5a, 0x7a } }; extern int onigenc_ascii_apply_all_case_fold(OnigCaseFoldType flag ARG_UNUSED, OnigApplyAllCaseFoldFunc f, void* arg) { OnigCodePoint code; int i, r; for (i = 0; i < (int )(sizeof(OnigAsciiLowerMap)/sizeof(OnigPairCaseFoldCodes)); i++) { code = OnigAsciiLowerMap[i].to; r = (*f)(OnigAsciiLowerMap[i].from, &code, 1, arg); if (r != 0) return r; code = OnigAsciiLowerMap[i].from; r = (*f)(OnigAsciiLowerMap[i].to, &code, 1, arg); if (r != 0) return r; } return 0; } extern int onigenc_ascii_get_case_fold_codes_by_str(OnigCaseFoldType flag ARG_UNUSED, const OnigUChar* p, const OnigUChar* end ARG_UNUSED, OnigCaseFoldCodeItem items[]) { if (0x41 <= *p && *p <= 0x5a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p + 0x20); return 1; } else if (0x61 <= *p && *p <= 0x7a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p - 0x20); return 1; } else return 0; } static int ss_apply_all_case_fold(OnigCaseFoldType flag ARG_UNUSED, OnigApplyAllCaseFoldFunc f, void* arg) { static OnigCodePoint ss[] = { 0x73, 0x73 }; return (*f)((OnigCodePoint )0xdf, ss, 2, arg); } extern int onigenc_apply_all_case_fold_with_map(int map_size, const OnigPairCaseFoldCodes map[], int ess_tsett_flag, OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg) { OnigCodePoint code; int i, r; r = onigenc_ascii_apply_all_case_fold(flag, f, arg); if (r != 0) return r; for (i = 0; i < map_size; i++) { code = map[i].to; r = (*f)(map[i].from, &code, 1, arg); if (r != 0) return r; code = map[i].from; r = (*f)(map[i].to, &code, 1, arg); if (r != 0) return r; } if (ess_tsett_flag != 0) return ss_apply_all_case_fold(flag, f, arg); return 0; } extern int onigenc_get_case_fold_codes_by_str_with_map(int map_size, const OnigPairCaseFoldCodes map[], int ess_tsett_flag, OnigCaseFoldType flag ARG_UNUSED, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[]) { if (0x41 <= *p && *p <= 0x5a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p + 0x20); if (*p == 0x53 && ess_tsett_flag != 0 && end > p + 1 && (*(p+1) == 0x53 || *(p+1) == 0x73)) { /* SS */ items[1].byte_len = 2; items[1].code_len = 1; items[1].code[0] = (OnigCodePoint )0xdf; return 2; } else return 1; } else if (0x61 <= *p && *p <= 0x7a) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = (OnigCodePoint )(*p - 0x20); if (*p == 0x73 && ess_tsett_flag != 0 && end > p + 1 && (*(p+1) == 0x73 || *(p+1) == 0x53)) { /* ss */ items[1].byte_len = 2; items[1].code_len = 1; items[1].code[0] = (OnigCodePoint )0xdf; return 2; } else return 1; } else if (*p == 0xdf && ess_tsett_flag != 0) { items[0].byte_len = 1; items[0].code_len = 2; items[0].code[0] = (OnigCodePoint )'s'; items[0].code[1] = (OnigCodePoint )'s'; items[1].byte_len = 1; items[1].code_len = 2; items[1].code[0] = (OnigCodePoint )'S'; items[1].code[1] = (OnigCodePoint )'S'; items[2].byte_len = 1; items[2].code_len = 2; items[2].code[0] = (OnigCodePoint )'s'; items[2].code[1] = (OnigCodePoint )'S'; items[3].byte_len = 1; items[3].code_len = 2; items[3].code[0] = (OnigCodePoint )'S'; items[3].code[1] = (OnigCodePoint )'s'; return 4; } else { int i; for (i = 0; i < map_size; i++) { if (*p == map[i].from) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = map[i].to; return 1; } else if (*p == map[i].to) { items[0].byte_len = 1; items[0].code_len = 1; items[0].code[0] = map[i].from; return 1; } } } return 0; } extern int onigenc_not_support_get_ctype_code_range(OnigCtype ctype ARG_UNUSED, OnigCodePoint* sb_out ARG_UNUSED, const OnigCodePoint* ranges[] ARG_UNUSED) { return ONIG_NO_SUPPORT_CONFIG; } extern int onigenc_is_mbc_newline_0x0a(const UChar* p, const UChar* end) { if (p < end) { if (*p == 0x0a) return 1; } return 0; } extern int onigenc_is_mbc_newline_0x0a_se(OnigIterator* it, OnigPosition p, OnigPosition end) { if (p < end) { if (ONIG_CHARAT(p) == 0x0a) return 1; } return 0; } /* for single byte encodings */ extern int onigenc_ascii_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** p, const UChar*end ARG_UNUSED, UChar* lower) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(**p); (*p)++; return 1; /* return byte length of converted char to lower */ } /* for single byte encodings */ extern int onigenc_ascii_mbc_case_fold_se(OnigIterator* it, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* p, OnigPosition end ARG_UNUSED, UChar* lower) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(ONIG_CHARAT(*p)); (*p)++; return 1; /* return byte length of converted char to lower */ } #if 0 extern int onigenc_ascii_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; (*pp)++; return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); } #endif extern int onigenc_single_byte_mbc_enc_len(const UChar* p ARG_UNUSED) { return 1; } extern int onigenc_single_byte_mbc_enc_len_se(OnigIterator* it ARG_UNUSED, OnigPosition p ARG_UNUSED) { return 1; } extern OnigCodePoint onigenc_single_byte_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED) { return (OnigCodePoint )(*p); } extern OnigCodePoint onigenc_single_byte_mbc_to_code_se(OnigIterator* it, OnigPosition p, OnigPosition end ARG_UNUSED) { return (OnigCodePoint )(ONIG_CHARAT(p)); } extern int onigenc_single_byte_code_to_mbclen(OnigCodePoint code ARG_UNUSED) { return (code < 0x100 ? 1 : ONIGERR_INVALID_CODE_POINT_VALUE); } extern int onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf) { *buf = (UChar )(code & 0xff); return 1; } extern UChar* onigenc_single_byte_left_adjust_char_head(const UChar* start ARG_UNUSED, const UChar* s) { return (UChar* )s; } extern OnigPosition onigenc_single_byte_left_adjust_char_head_se(OnigIterator* it ARG_UNUSED, OnigPosition start ARG_UNUSED, OnigPosition s) { return s; } extern int onigenc_always_true_is_allowed_reverse_match(const UChar* s ARG_UNUSED, const UChar* end ARG_UNUSED) { return TRUE; } extern int onigenc_always_false_is_allowed_reverse_match(const UChar* s ARG_UNUSED, const UChar* end ARG_UNUSED) { return FALSE; } extern int onigenc_ascii_is_code_ctype(OnigCodePoint code, unsigned int ctype) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else return FALSE; } extern OnigCodePoint onigenc_mbn_mbc_to_code(OnigEncoding enc, const UChar* p, const UChar* end) { int c, i, len; OnigCodePoint n; len = enclen(enc, p); n = (OnigCodePoint )(*p++); if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = *p++; n <<= 8; n += c; } return n; } extern OnigCodePoint onigenc_mbn_mbc_to_code_se(OnigIterator* it, OnigEncoding enc, OnigPosition p, OnigPosition end) { int c, i, len; OnigCodePoint n; len = enclen_se(it, enc, p); n = (OnigCodePoint )(ONIG_CHARAT(p++)); if (len == 1) return n; for (i = 1; i < len; i++) { if (p >= end) break; c = ONIG_CHARAT(p++); n <<= 8; n += c; } return n; } extern int onigenc_mbn_mbc_case_fold(OnigEncoding enc, OnigCaseFoldType flag ARG_UNUSED, const UChar** pp, const UChar* end ARG_UNUSED, UChar* lower) { int len; const UChar *p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*p); (*pp)++; return 1; } else { int i; len = enclen(enc, p); for (i = 0; i < len; i++) { *lower++ = *p++; } (*pp) += len; return len; /* return byte length of converted to lower char */ } } extern int onigenc_mbn_mbc_case_fold_se(OnigIterator* it, OnigEncoding enc, OnigCaseFoldType flag ARG_UNUSED, OnigPosition* pp, OnigPosition end ARG_UNUSED, UChar* lower) { int len; OnigPosition p = *pp; const UChar c = ONIG_CHARAT(*pp); if (ONIGENC_IS_MBC_ASCII_SE(c)) { *lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); (*pp)++; return 1; } else { int i; len = enclen_se(it, enc, p); for (i = 0; i < len; i++) { *lower++ = ONIG_CHARAT(p++); } (*pp) += len; return len; /* return byte length of converted to lower char */ } } #if 0 extern int onigenc_mbn_is_mbc_ambiguous(OnigEncoding enc, OnigCaseFoldType flag, const UChar** pp, const UChar* end) { const UChar* p = *pp; if (ONIGENC_IS_MBC_ASCII(p)) { (*pp)++; return ONIGENC_IS_ASCII_CODE_CASE_AMBIG(*p); } (*pp) += enclen(enc, p); return FALSE; } #endif extern int onigenc_mb2_code_to_mbclen(OnigCodePoint code) { if ((code & 0xff00) != 0) return 2; else return 1; } extern int onigenc_mb4_code_to_mbclen(OnigCodePoint code) { if ((code & 0xff000000) != 0) return 4; else if ((code & 0xff0000) != 0) return 3; else if ((code & 0xff00) != 0) return 2; else return 1; } extern int onigenc_mb2_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf) { UChar *p = buf; if ((code & 0xff00) != 0) { *p++ = (UChar )((code >> 8) & 0xff); } *p++ = (UChar )(code & 0xff); #if 1 if (enclen(enc, buf) != (p - buf)) return ONIGERR_INVALID_CODE_POINT_VALUE; #endif return (int )(p - buf); } extern int onigenc_mb4_code_to_mbc(OnigEncoding enc, OnigCodePoint code, UChar *buf) { UChar *p = buf; if ((code & 0xff000000) != 0) { *p++ = (UChar )((code >> 24) & 0xff); } if ((code & 0xff0000) != 0 || p != buf) { *p++ = (UChar )((code >> 16) & 0xff); } if ((code & 0xff00) != 0 || p != buf) { *p++ = (UChar )((code >> 8) & 0xff); } *p++ = (UChar )(code & 0xff); #if 1 if (enclen(enc, buf) != (p - buf)) return ONIGERR_INVALID_CODE_POINT_VALUE; #endif return (int )(p - buf); } extern int onigenc_minimum_property_name_to_ctype(OnigEncoding enc, UChar* p, UChar* end) { static const PosixBracketEntryType PBS[] = { { (UChar* )"Alnum", ONIGENC_CTYPE_ALNUM, 5 }, { (UChar* )"Alpha", ONIGENC_CTYPE_ALPHA, 5 }, { (UChar* )"Blank", ONIGENC_CTYPE_BLANK, 5 }, { (UChar* )"Cntrl", ONIGENC_CTYPE_CNTRL, 5 }, { (UChar* )"Digit", ONIGENC_CTYPE_DIGIT, 5 }, { (UChar* )"Graph", ONIGENC_CTYPE_GRAPH, 5 }, { (UChar* )"Lower", ONIGENC_CTYPE_LOWER, 5 }, { (UChar* )"Print", ONIGENC_CTYPE_PRINT, 5 }, { (UChar* )"Punct", ONIGENC_CTYPE_PUNCT, 5 }, { (UChar* )"Space", ONIGENC_CTYPE_SPACE, 5 }, { (UChar* )"Upper", ONIGENC_CTYPE_UPPER, 5 }, { (UChar* )"XDigit", ONIGENC_CTYPE_XDIGIT, 6 }, { (UChar* )"ASCII", ONIGENC_CTYPE_ASCII, 5 }, { (UChar* )"Word", ONIGENC_CTYPE_WORD, 4 }, { (UChar* )NULL, -1, 0 } }; const PosixBracketEntryType *pb; int len; len = onigenc_strlen(enc, p, end); for (pb = PBS; IS_NOT_NULL(pb->name); pb++) { if (len == pb->len && onigenc_with_ascii_strnicmp(enc, p, end, pb->name, pb->len) == 0) return pb->ctype; } return ONIGERR_INVALID_CHAR_PROPERTY_NAME; } extern int onigenc_mb2_is_code_ctype(OnigEncoding enc, OnigCodePoint code, unsigned int ctype) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { if (CTYPE_IS_WORD_GRAPH_PRINT(ctype)) { return (ONIGENC_CODE_TO_MBCLEN(enc, code) > 1 ? TRUE : FALSE); } } return FALSE; } extern int onigenc_mb4_is_code_ctype(OnigEncoding enc, OnigCodePoint code, unsigned int ctype) { if (code < 128) return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype); else { if (CTYPE_IS_WORD_GRAPH_PRINT(ctype)) { return (ONIGENC_CODE_TO_MBCLEN(enc, code) > 1 ? TRUE : FALSE); } } return FALSE; } extern int onigenc_with_ascii_strncmp(OnigEncoding enc, const UChar* p, const UChar* end, const UChar* sascii /* ascii */, int n) { int x, c; while (n-- > 0) { if (p >= end) return (int )(*sascii); c = (int )ONIGENC_MBC_TO_CODE(enc, p, end); x = *sascii - c; if (x) return x; sascii++; p += enclen(enc, p); } return 0; } extern int onigenc_with_ascii_strnicmp(OnigEncoding enc, const UChar* p, const UChar* end, const UChar* sascii /* ascii */, int n) { int x, c; while (n-- > 0) { if (p >= end) return (int )(*sascii); c = (int )ONIGENC_MBC_TO_CODE(enc, p, end); if (ONIGENC_IS_ASCII_CODE(c)) c = ONIGENC_ASCII_CODE_TO_LOWER_CASE(c); x = ONIGENC_ASCII_CODE_TO_LOWER_CASE(*sascii) - c; if (x) return x; sascii++; p += enclen(enc, p); } return 0; } /* Property management */ static int resize_property_list(int new_size, const OnigCodePoint*** plist, int* psize) { size_t size; const OnigCodePoint **list = *plist; size = sizeof(OnigCodePoint*) * new_size; if (IS_NULL(list)) { list = (const OnigCodePoint** )xmalloc(size); } else { list = (const OnigCodePoint** )xrealloc((void* )list, size); } if (IS_NULL(list)) return ONIGERR_MEMORY; *plist = list; *psize = new_size; return 0; } extern int onigenc_property_list_add_property(UChar* name, const OnigCodePoint* prop, hash_table_type **table, const OnigCodePoint*** plist, int *pnum, int *psize) { #define PROP_INIT_SIZE 16 int r; if (*psize <= *pnum) { int new_size = (*psize == 0 ? PROP_INIT_SIZE : *psize * 2); r = resize_property_list(new_size, plist, psize); if (r != 0) return r; } (*plist)[*pnum] = prop; if (ONIG_IS_NULL(*table)) { *table = onig_st_init_strend_table_with_size(PROP_INIT_SIZE); if (ONIG_IS_NULL(*table)) return ONIGERR_MEMORY; } *pnum = *pnum + 1; onig_st_insert_strend(*table, name, name + strlen((char* )name), (hash_data_type )(*pnum + ONIGENC_MAX_STD_CTYPE)); return 0; } extern int onigenc_property_list_init(int (*f)(void)) { int r; THREAD_ATOMIC_START; r = f(); THREAD_ATOMIC_END; return r; } ================================================ FILE: src/Onigmo/regenc.h ================================================ #ifndef REGENC_H #define REGENC_H /********************************************************************** regenc.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #ifndef PACKAGE /* PACKAGE is defined in config.h */ #include "config.h" #endif #ifdef ONIG_ESCAPE_UCHAR_COLLISION #undef ONIG_ESCAPE_UCHAR_COLLISION #endif #include "oniguruma.h" typedef struct { OnigCodePoint from; OnigCodePoint to; } OnigPairCaseFoldCodes; #ifndef NULL #define NULL ((void* )0) #endif #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef ARG_UNUSED #if defined(__GNUC__) # define ARG_UNUSED __attribute__ ((unused)) #else # define ARG_UNUSED #endif #endif #define ONIG_IS_NULL(p) (((void*)(p)) == (void*)0) #define ONIG_IS_NOT_NULL(p) (((void*)(p)) != (void*)0) #define ONIG_CHECK_NULL_RETURN(p) if (ONIG_IS_NULL(p)) return NULL #define ONIG_CHECK_NULL_RETURN_VAL(p,val) if (ONIG_IS_NULL(p)) return (val) #define enclen(enc,p) ONIGENC_MBC_ENC_LEN(enc,p) #define enclen_se(it,enc,p) ONIGENC_MBC_ENC_LEN_SE(it,enc,p) /* character types bit flag */ #define BIT_CTYPE_NEWLINE (1<< ONIGENC_CTYPE_NEWLINE) #define BIT_CTYPE_ALPHA (1<< ONIGENC_CTYPE_ALPHA) #define BIT_CTYPE_BLANK (1<< ONIGENC_CTYPE_BLANK) #define BIT_CTYPE_CNTRL (1<< ONIGENC_CTYPE_CNTRL) #define BIT_CTYPE_DIGIT (1<< ONIGENC_CTYPE_DIGIT) #define BIT_CTYPE_GRAPH (1<< ONIGENC_CTYPE_GRAPH) #define BIT_CTYPE_LOWER (1<< ONIGENC_CTYPE_LOWER) #define BIT_CTYPE_PRINT (1<< ONIGENC_CTYPE_PRINT) #define BIT_CTYPE_PUNCT (1<< ONIGENC_CTYPE_PUNCT) #define BIT_CTYPE_SPACE (1<< ONIGENC_CTYPE_SPACE) #define BIT_CTYPE_UPPER (1<< ONIGENC_CTYPE_UPPER) #define BIT_CTYPE_XDIGIT (1<< ONIGENC_CTYPE_XDIGIT) #define BIT_CTYPE_WORD (1<< ONIGENC_CTYPE_WORD) #define BIT_CTYPE_ALNUM (1<< ONIGENC_CTYPE_ALNUM) #define BIT_CTYPE_ASCII (1<< ONIGENC_CTYPE_ASCII) #define CTYPE_TO_BIT(ctype) (1<<(ctype)) #define CTYPE_IS_WORD_GRAPH_PRINT(ctype) \ ((ctype) == ONIGENC_CTYPE_WORD || (ctype) == ONIGENC_CTYPE_GRAPH ||\ (ctype) == ONIGENC_CTYPE_PRINT) typedef struct { const UChar *name; int ctype; short int len; } PosixBracketEntryType; #define USE_CRNL_AS_LINE_TERMINATOR #define USE_UNICODE_PROPERTIES /* #define USE_UNICODE_CASE_FOLD_TURKISH_AZERI */ #define USE_UNICODE_ALL_LINE_TERMINATORS /* see Unicode.org UTS #18 */ #define ONIG_ENCODING_INIT_DEFAULT ONIG_ENCODING_ASCII /* for encoding system implementation (internal) */ ONIG_EXTERN int onigenc_ascii_apply_all_case_fold P_((OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg)); ONIG_EXTERN int onigenc_ascii_get_case_fold_codes_by_str P_((OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[])); ONIG_EXTERN int onigenc_apply_all_case_fold_with_map P_((int map_size, const OnigPairCaseFoldCodes map[], int ess_tsett_flag, OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg)); ONIG_EXTERN int onigenc_get_case_fold_codes_by_str_with_map P_((int map_size, const OnigPairCaseFoldCodes map[], int ess_tsett_flag, OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[])); ONIG_EXTERN int onigenc_not_support_get_ctype_code_range P_((OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[])); ONIG_EXTERN int onigenc_is_mbc_newline_0x0a P_((const UChar* p, const UChar* end)); ONIG_EXTERN int onigenc_is_mbc_newline_0x0a_se P_((OnigIterator* it, OnigPosition p, OnigPosition end)); /* methods for single byte encoding */ ONIG_EXTERN int onigenc_ascii_mbc_case_fold P_((OnigCaseFoldType flag, const UChar** p, const UChar* end, UChar* lower)); ONIG_EXTERN int onigenc_ascii_mbc_case_fold_se P_((OnigIterator* it, OnigCaseFoldType flag, OnigPosition* p, OnigPosition end, UChar* lower)); ONIG_EXTERN int onigenc_single_byte_mbc_enc_len P_((const UChar* p)); ONIG_EXTERN int onigenc_single_byte_mbc_enc_len_se P_((OnigIterator* it, OnigPosition p)); ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code P_((const UChar* p, const UChar* end)); ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code_se P_((OnigIterator* it, OnigPosition p, OnigPosition end)); ONIG_EXTERN int onigenc_single_byte_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_single_byte_code_to_mbc P_((OnigCodePoint code, UChar *buf)); ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s)); ONIG_EXTERN OnigPosition onigenc_single_byte_left_adjust_char_head_se P_((OnigIterator* it, OnigPosition start, OnigPosition s)); ONIG_EXTERN int onigenc_always_true_is_allowed_reverse_match P_((const UChar* s, const UChar* end)); ONIG_EXTERN int onigenc_always_false_is_allowed_reverse_match P_((const UChar* s, const UChar* end)); ONIG_EXTERN int onigenc_ascii_is_code_ctype P_((OnigCodePoint code, unsigned int ctype)); /* methods for multi byte encoding */ ONIG_EXTERN OnigCodePoint onigenc_mbn_mbc_to_code P_((OnigEncoding enc, const UChar* p, const UChar* end)); ONIG_EXTERN OnigCodePoint onigenc_mbn_mbc_to_code_se P_((OnigIterator* it, OnigEncoding enc, OnigPosition p, OnigPosition end)); ONIG_EXTERN int onigenc_mbn_mbc_case_fold P_((OnigEncoding enc, OnigCaseFoldType flag, const UChar** p, const UChar* end, UChar* lower)); ONIG_EXTERN int onigenc_mbn_mbc_case_fold_se P_((OnigIterator* it, OnigEncoding enc, OnigCaseFoldType flag, OnigPosition* p, OnigPosition end, UChar* lower)); ONIG_EXTERN int onigenc_mb2_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb2_code_to_mbc P_((OnigEncoding enc, OnigCodePoint code, UChar *buf)); ONIG_EXTERN int onigenc_minimum_property_name_to_ctype P_((OnigEncoding enc, UChar* p, UChar* end)); ONIG_EXTERN int onigenc_unicode_property_name_to_ctype P_((OnigEncoding enc, UChar* p, UChar* end)); ONIG_EXTERN int onigenc_mb2_is_code_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); ONIG_EXTERN int onigenc_mb4_code_to_mbclen P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_mb4_code_to_mbc P_((OnigEncoding enc, OnigCodePoint code, UChar *buf)); ONIG_EXTERN int onigenc_mb4_is_code_ctype P_((OnigEncoding enc, OnigCodePoint code, unsigned int ctype)); /* in enc/unicode.c */ ONIG_EXTERN const OnigCodePoint* onigenc_unicode_code_script P_((OnigCodePoint code)); ONIG_EXTERN int onigenc_unicode_is_code_ctype P_((OnigCodePoint code, unsigned int ctype)); ONIG_EXTERN int onigenc_utf16_32_get_ctype_code_range P_((OnigCtype ctype, OnigCodePoint *sb_out, const OnigCodePoint* ranges[])); ONIG_EXTERN int onigenc_unicode_ctype_code_range P_((int ctype, const OnigCodePoint* ranges[])); ONIG_EXTERN int onigenc_unicode_get_case_fold_codes_by_str P_((OnigEncoding enc, OnigCaseFoldType flag, const OnigUChar* p, const OnigUChar* end, OnigCaseFoldCodeItem items[])); ONIG_EXTERN int onigenc_unicode_mbc_case_fold P_((OnigEncoding enc, OnigCaseFoldType flag, const UChar** pp, const UChar* end, UChar* fold)); ONIG_EXTERN int onigenc_unicode_mbc_case_fold_se P_((OnigIterator* it, OnigEncoding enc, OnigCaseFoldType flag, OnigPosition* pp, OnigPosition end, UChar* fold)); ONIG_EXTERN int onigenc_unicode_apply_all_case_fold P_((OnigCaseFoldType flag, OnigApplyAllCaseFoldFunc f, void* arg)); #define UTF16_IS_SURROGATE_FIRST(c) (((c) & 0xfc) == 0xd8) #define UTF16_IS_SURROGATE_SECOND(c) (((c) & 0xfc) == 0xdc) #define ONIGENC_ISO_8859_1_TO_LOWER_CASE(c) \ OnigEncISO_8859_1_ToLowerCaseTable[c] #define ONIGENC_ISO_8859_1_TO_UPPER_CASE(c) \ OnigEncISO_8859_1_ToUpperCaseTable[c] ONIG_EXTERN const UChar OnigEncISO_8859_1_ToLowerCaseTable[]; ONIG_EXTERN const UChar OnigEncISO_8859_1_ToUpperCaseTable[]; ONIG_EXTERN int onigenc_with_ascii_strncmp P_((OnigEncoding enc, const UChar* p, const UChar* end, const UChar* sascii /* ascii */, int n)); ONIG_EXTERN int onigenc_with_ascii_strnicmp P_((OnigEncoding enc, const UChar* p, const UChar* end, const UChar* sascii /* ascii */, int n)); ONIG_EXTERN UChar* onigenc_step P_((OnigEncoding enc, const UChar* p, const UChar* end, int n)); /* defined in regexec.c, but used in enc/xxx.c */ extern int onig_is_in_code_range P_((const UChar* p, OnigCodePoint code)); ONIG_EXTERN OnigEncoding OnigEncDefaultCharEncoding; ONIG_EXTERN const UChar OnigEncAsciiToLowerCaseTable[]; ONIG_EXTERN const UChar OnigEncAsciiToUpperCaseTable[]; ONIG_EXTERN const unsigned short OnigEncAsciiCtypeTable[]; #define ONIGENC_IS_ASCII_CODE(code) ((code) < 0x80) #define ONIGENC_ASCII_CODE_TO_LOWER_CASE(c) OnigEncAsciiToLowerCaseTable[c] #define ONIGENC_ASCII_CODE_TO_UPPER_CASE(c) OnigEncAsciiToUpperCaseTable[c] #define ONIGENC_IS_ASCII_CODE_CTYPE(code,ctype) \ ((OnigEncAsciiCtypeTable[code] & CTYPE_TO_BIT(ctype)) != 0) #define ONIGENC_IS_ASCII_CODE_CASE_AMBIG(code) \ (ONIGENC_IS_ASCII_CODE_CTYPE(code, ONIGENC_CTYPE_UPPER) ||\ ONIGENC_IS_ASCII_CODE_CTYPE(code, ONIGENC_CTYPE_LOWER)) /* Check if the code is in the range. (from <= code && code <= to) */ #define ONIGENC_IS_IN_RANGE(code, from, to) \ ((OnigCodePoint )((code) - (from)) <= (OnigCodePoint )((to) - (from))) #endif /* REGENC_H */ ================================================ FILE: src/Onigmo/regerror.c ================================================ /********************************************************************** regerror.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" #include /* for vsnprintf() */ #ifdef HAVE_STDARG_PROTOTYPES #include #define va_init_list(a,b) va_start(a,b) #else #include #define va_init_list(a,b) va_start(a) #endif extern UChar* onig_error_code_to_format(OnigPosition code) { const char *p; if (code >= 0) return (UChar* )0; switch (code) { case ONIG_MISMATCH: p = "mismatch"; break; case ONIG_NO_SUPPORT_CONFIG: p = "no support in this configuration"; break; case ONIGERR_MEMORY: p = "failed to allocate memory"; break; case ONIGERR_MATCH_STACK_LIMIT_OVER: p = "match-stack limit over"; break; case ONIGERR_TYPE_BUG: p = "undefined type (bug)"; break; case ONIGERR_PARSER_BUG: p = "internal parser error (bug)"; break; case ONIGERR_STACK_BUG: p = "stack error (bug)"; break; case ONIGERR_UNDEFINED_BYTECODE: p = "undefined bytecode (bug)"; break; case ONIGERR_UNEXPECTED_BYTECODE: p = "unexpected bytecode (bug)"; break; case ONIGERR_DEFAULT_ENCODING_IS_NOT_SET: p = "default multibyte-encoding is not set"; break; case ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR: p = "can't convert to wide-char on specified multibyte-encoding"; break; case ONIGERR_INVALID_ARGUMENT: p = "invalid argument"; break; case ONIGERR_END_PATTERN_AT_LEFT_BRACE: p = "end pattern at left brace"; break; case ONIGERR_END_PATTERN_AT_LEFT_BRACKET: p = "end pattern at left bracket"; break; case ONIGERR_EMPTY_CHAR_CLASS: p = "empty char-class"; break; case ONIGERR_PREMATURE_END_OF_CHAR_CLASS: p = "premature end of char-class"; break; case ONIGERR_END_PATTERN_AT_ESCAPE: p = "end pattern at escape"; break; case ONIGERR_END_PATTERN_AT_META: p = "end pattern at meta"; break; case ONIGERR_END_PATTERN_AT_CONTROL: p = "end pattern at control"; break; case ONIGERR_META_CODE_SYNTAX: p = "invalid meta-code syntax"; break; case ONIGERR_CONTROL_CODE_SYNTAX: p = "invalid control-code syntax"; break; case ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE: p = "char-class value at end of range"; break; case ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE: p = "char-class value at start of range"; break; case ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS: p = "unmatched range specifier in char-class"; break; case ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED: p = "target of repeat operator is not specified"; break; case ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID: p = "target of repeat operator is invalid"; break; case ONIGERR_NESTED_REPEAT_OPERATOR: p = "nested repeat operator"; break; case ONIGERR_UNMATCHED_CLOSE_PARENTHESIS: p = "unmatched close parenthesis"; break; case ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS: p = "end pattern with unmatched parenthesis"; break; case ONIGERR_END_PATTERN_IN_GROUP: p = "end pattern in group"; break; case ONIGERR_UNDEFINED_GROUP_OPTION: p = "undefined group option"; break; case ONIGERR_INVALID_POSIX_BRACKET_TYPE: p = "invalid POSIX bracket type"; break; case ONIGERR_INVALID_LOOK_BEHIND_PATTERN: p = "invalid pattern in look-behind"; break; case ONIGERR_INVALID_REPEAT_RANGE_PATTERN: p = "invalid repeat range {lower,upper}"; break; case ONIGERR_INVALID_CONDITION_PATTERN: p = "invalid conditional pattern"; break; case ONIGERR_TOO_BIG_NUMBER: p = "too big number"; break; case ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE: p = "too big number for repeat range"; break; case ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE: p = "upper is smaller than lower in repeat range"; break; case ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS: p = "empty range in char class"; break; case ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE: p = "mismatch multibyte code length in char-class range"; break; case ONIGERR_TOO_MANY_MULTI_BYTE_RANGES: p = "too many multibyte code ranges are specified"; break; case ONIGERR_TOO_SHORT_MULTI_BYTE_STRING: p = "too short multibyte code string"; break; case ONIGERR_TOO_BIG_BACKREF_NUMBER: p = "too big backref number"; break; case ONIGERR_INVALID_BACKREF: #ifdef USE_NAMED_GROUP p = "invalid backref number/name"; break; #else p = "invalid backref number"; break; #endif case ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED: p = "numbered backref/call is not allowed. (use name)"; break; case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE: p = "too big wide-char value"; break; case ONIGERR_TOO_SHORT_DIGITS: p = "too short digits"; break; case ONIGERR_TOO_LONG_WIDE_CHAR_VALUE: p = "too long wide-char value"; break; case ONIGERR_INVALID_CODE_POINT_VALUE: p = "invalid code point value"; break; case ONIGERR_EMPTY_GROUP_NAME: p = "group name is empty"; break; case ONIGERR_INVALID_GROUP_NAME: p = "invalid group name <%n>"; break; case ONIGERR_INVALID_CHAR_IN_GROUP_NAME: #ifdef USE_NAMED_GROUP p = "invalid char in group name <%n>"; break; #else p = "invalid char in group number <%n>"; break; #endif case ONIGERR_UNDEFINED_NAME_REFERENCE: p = "undefined name <%n> reference"; break; case ONIGERR_UNDEFINED_GROUP_REFERENCE: p = "undefined group <%n> reference"; break; case ONIGERR_MULTIPLEX_DEFINED_NAME: p = "multiplex defined name <%n>"; break; case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL: p = "multiplex definition name <%n> call"; break; case ONIGERR_NEVER_ENDING_RECURSION: p = "never ending recursion"; break; case ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY: p = "group number is too big for capture history"; break; case ONIGERR_INVALID_CHAR_PROPERTY_NAME: p = "invalid character property name {%n}"; break; case ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION: p = "not supported encoding combination"; break; case ONIGERR_INVALID_COMBINATION_OF_OPTIONS: p = "invalid combination of options"; break; case ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT: p = "over thread pass limit count"; break; default: p = "undefined error code"; break; } return (UChar* )p; } static void sprint_byte(char* s, unsigned int v) { sprintf(s, "%02x", (v & 0377)); } static void sprint_byte_with_x(char* s, unsigned int v) { sprintf(s, "\\x%02x", (v & 0377)); } static int to_ascii(OnigEncoding enc, UChar *s, UChar *end, UChar buf[], int buf_size, int *is_over) { int len; UChar *p; OnigCodePoint code; if (ONIGENC_MBC_MINLEN(enc) > 1) { p = s; len = 0; while (p < end) { code = ONIGENC_MBC_TO_CODE(enc, p, end); if (code >= 0x80) { if (code > 0xffff && len + 10 <= buf_size) { sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 24)); sprint_byte((char*)(&(buf[len+4])), (unsigned int)(code >> 16)); sprint_byte((char*)(&(buf[len+6])), (unsigned int)(code >> 8)); sprint_byte((char*)(&(buf[len+8])), (unsigned int)code); len += 10; } else if (len + 6 <= buf_size) { sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 8)); sprint_byte((char*)(&(buf[len+4])), (unsigned int)code); len += 6; } else { break; } } else { buf[len++] = (UChar )code; } p += enclen(enc, p); if (len >= buf_size) break; } *is_over = ((p < end) ? 1 : 0); } else { len = (int )MIN((end - s), buf_size); xmemcpy(buf, s, (size_t )len); *is_over = ((buf_size < (end - s)) ? 1 : 0); } return len; } /* for ONIG_MAX_ERROR_MESSAGE_LEN */ #define MAX_ERROR_PAR_LEN 30 extern int #ifdef HAVE_STDARG_PROTOTYPES onig_error_code_to_str(UChar* s, OnigPosition code, ...) #else onig_error_code_to_str(s, code, va_alist) UChar* s; OnigPosition code; va_dcl #endif { UChar *p, *q; OnigErrorInfo* einfo; size_t len; int is_over; UChar parbuf[MAX_ERROR_PAR_LEN]; va_list vargs; va_init_list(vargs, code); switch (code) { case ONIGERR_UNDEFINED_NAME_REFERENCE: case ONIGERR_UNDEFINED_GROUP_REFERENCE: case ONIGERR_MULTIPLEX_DEFINED_NAME: case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL: case ONIGERR_INVALID_GROUP_NAME: case ONIGERR_INVALID_CHAR_IN_GROUP_NAME: case ONIGERR_INVALID_CHAR_PROPERTY_NAME: einfo = va_arg(vargs, OnigErrorInfo*); len = to_ascii(einfo->enc, einfo->par, einfo->par_end, parbuf, MAX_ERROR_PAR_LEN - 3, &is_over); q = onig_error_code_to_format(code); p = s; while (*q != '\0') { if (*q == '%') { q++; if (*q == 'n') { /* '%n': name */ xmemcpy(p, parbuf, len); p += len; if (is_over != 0) { xmemcpy(p, "...", 3); p += 3; } q++; } else goto normal_char; } else { normal_char: *p++ = *q++; } } *p = '\0'; len = p - s; break; default: q = onig_error_code_to_format(code); len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, q); xmemcpy(s, q, len); s[len] = '\0'; break; } va_end(vargs); return (int )len; } void #ifdef HAVE_STDARG_PROTOTYPES onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, ...) #else onig_snprintf_with_pattern(buf, bufsize, enc, pat, pat_end, fmt, va_alist) UChar buf[]; int bufsize; OnigEncoding enc; UChar* pat; UChar* pat_end; const UChar *fmt; va_dcl #endif { size_t need; int n, len; UChar *p, *s, *bp; UChar bs[6]; va_list args; va_init_list(args, fmt); n = xvsnprintf((char* )buf, bufsize, (const char* )fmt, args); va_end(args); need = (pat_end - pat) * 4 + 4; if (n + need < (size_t )bufsize) { strcat((char* )buf, ": /"); s = buf + onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, buf); p = pat; while (p < pat_end) { if (*p == '\\') { *s++ = *p++; len = enclen(enc, p); while (len-- > 0) *s++ = *p++; } else if (*p == '/') { *s++ = (unsigned char )'\\'; *s++ = *p++; } else if (ONIGENC_IS_MBC_HEAD(enc, p)) { len = enclen(enc, p); if (ONIGENC_MBC_MINLEN(enc) == 1) { while (len-- > 0) *s++ = *p++; } else { /* for UTF16 */ int blen; while (len-- > 0) { sprint_byte_with_x((char* )bs, (unsigned int )(*p++)); blen = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs); bp = bs; while (blen-- > 0) *s++ = *bp++; } } } else if (!ONIGENC_IS_CODE_PRINT(enc, *p) && !ONIGENC_IS_CODE_SPACE(enc, *p)) { sprint_byte_with_x((char* )bs, (unsigned int )(*p++)); len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs); bp = bs; while (len-- > 0) *s++ = *bp++; } else { *s++ = *p++; } } *s++ = '/'; *s = '\0'; } } ================================================ FILE: src/Onigmo/regexec.c ================================================ /********************************************************************** regexec.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ #include "regint.h" //#define USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE #ifdef USE_CRNL_AS_LINE_TERMINATOR #define ONIGENC_IS_MBC_CRNL_SE(it,enc,p,end) \ (ONIGENC_MBC_TO_CODE_SE(it,enc,p,end) == 13 && \ ONIGENC_MBC_TO_CODE_SE(it,enc,(p+enclen_se(it,enc,p)),end) == 10) #define ONIGENC_IS_MBC_NEWLINE_EX_SE(it, enc,p,start,end,option,check_prev) \ is_mbc_newline_ex_se((it), (enc),(p),(start),(end),(option),(check_prev)) static int is_mbc_newline_ex_se(OnigIterator* it, OnigEncoding enc, OnigPosition p, OnigPosition start, OnigPosition end, OnigOptionType option, int check_prev) { if (IS_NEWLINE_CRLF(option)) { if (ONIGENC_MBC_TO_CODE_SE(it, enc, p, end) == 0x0a) { if (check_prev) { OnigPosition prev = onigenc_get_prev_char_head_se(it, enc, start, p); if ((ONIG_IS_NOT_BADPOS(prev)) && ONIGENC_MBC_TO_CODE_SE(it, enc, prev, end) == 0x0d) return 0; else return 1; } else return 1; } else { OnigPosition pnext = p + enclen_se(it, enc, p); if (pnext < end && ONIGENC_MBC_TO_CODE_SE(it, enc, p, end) == 0x0d && ONIGENC_MBC_TO_CODE_SE(it, enc, pnext, end) == 0x0a) return 1; if (ONIGENC_IS_MBC_NEWLINE_SE(it, enc, p, end)) return 1; return 0; } } else { return ONIGENC_IS_MBC_NEWLINE_SE(it, enc, p, end); } } #else /* USE_CRNL_AS_LINE_TERMINATOR */ #define ONIGENC_IS_MBC_NEWLINE_EX_SE(it, enc,p,start,end,option,check_prev) \ ONIGENC_IS_MBC_NEWLINE_SE((it), (enc), (p), (end)) #endif /* USE_CRNL_AS_LINE_TERMINATOR */ #ifdef USE_CAPTURE_HISTORY static void history_tree_free(OnigCaptureTreeNode* node); static void history_tree_clear(OnigCaptureTreeNode* node) { int i; if (IS_NOT_NULL(node)) { for (i = 0; i < node->num_childs; i++) { if (IS_NOT_NULL(node->childs[i])) { history_tree_free(node->childs[i]); } } for (i = 0; i < node->allocated; i++) { node->childs[i] = (OnigCaptureTreeNode* )0; } node->num_childs = 0; node->beg = ONIG_REGION_NOTPOS; node->end = ONIG_REGION_NOTPOS; node->group = -1; xfree(node->childs); node->childs = (OnigCaptureTreeNode** )0; } } static void history_tree_free(OnigCaptureTreeNode* node) { history_tree_clear(node); xfree(node); } static void history_root_free(OnigRegion* r) { if (IS_NOT_NULL(r->history_root)) { history_tree_free(r->history_root); r->history_root = (OnigCaptureTreeNode* )0; } } static OnigCaptureTreeNode* history_node_new(void) { OnigCaptureTreeNode* node; node = (OnigCaptureTreeNode* )xmalloc(sizeof(OnigCaptureTreeNode)); CHECK_NULL_RETURN(node); node->childs = (OnigCaptureTreeNode** )0; node->allocated = 0; node->num_childs = 0; node->group = -1; node->beg = ONIG_REGION_NOTPOS; node->end = ONIG_REGION_NOTPOS; return node; } static int history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child) { #define HISTORY_TREE_INIT_ALLOC_SIZE 8 if (parent->num_childs >= parent->allocated) { int n, i; if (IS_NULL(parent->childs)) { n = HISTORY_TREE_INIT_ALLOC_SIZE; parent->childs = (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n); CHECK_NULL_RETURN_MEMERR(parent->childs); } else { OnigCaptureTreeNode** tmp; n = parent->allocated * 2; tmp = (OnigCaptureTreeNode** )xrealloc(parent->childs, sizeof(OnigCaptureTreeNode*) * n); if (tmp == 0) { history_tree_clear(parent); return ONIGERR_MEMORY; } parent->childs = tmp; } for (i = parent->allocated; i < n; i++) { parent->childs[i] = (OnigCaptureTreeNode* )0; } parent->allocated = n; } parent->childs[parent->num_childs] = child; parent->num_childs++; return 0; } static OnigCaptureTreeNode* history_tree_clone(OnigCaptureTreeNode* node) { int i, r; OnigCaptureTreeNode *clone, *child; clone = history_node_new(); CHECK_NULL_RETURN(clone); clone->beg = node->beg; clone->end = node->end; for (i = 0; i < node->num_childs; i++) { child = history_tree_clone(node->childs[i]); if (IS_NULL(child)) { history_tree_free(clone); return (OnigCaptureTreeNode* )0; } r = history_tree_add_child(clone, child); if (r != 0) { history_tree_free(child); history_tree_free(clone); return (OnigCaptureTreeNode* )0; } } return clone; } extern OnigCaptureTreeNode* onig_get_capture_tree(OnigRegion* region) { return region->history_root; } #endif /* USE_CAPTURE_HISTORY */ extern void onig_region_clear(OnigRegion* region) { int i; for (i = 0; i < region->num_regs; i++) { region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; } #ifdef USE_CAPTURE_HISTORY history_root_free(region); #endif } extern int onig_region_resize(OnigRegion* region, int n) { region->num_regs = n; if (n < ONIG_NREGION) n = ONIG_NREGION; if (region->allocated == 0) { region->beg = (OnigPosition* )xmalloc(n * sizeof(OnigPosition)); if (region->beg == 0) return ONIGERR_MEMORY; region->end = (OnigPosition* )xmalloc(n * sizeof(OnigPosition)); if (region->end == 0) { xfree(region->beg); return ONIGERR_MEMORY; } region->allocated = n; } else if (region->allocated < n) { OnigPosition *tmp; region->allocated = 0; tmp = (OnigPosition* )xrealloc(region->beg, n * sizeof(OnigPosition)); if (tmp == 0) { xfree(region->beg); xfree(region->end); return ONIGERR_MEMORY; } region->beg = tmp; tmp = (OnigPosition* )xrealloc(region->end, n * sizeof(OnigPosition)); if (tmp == 0) { xfree(region->beg); xfree(region->end); return ONIGERR_MEMORY; } region->end = tmp; region->allocated = n; } return 0; } static int onig_region_resize_clear(OnigRegion* region, int n) { int r; r = onig_region_resize(region, n); if (r != 0) return r; onig_region_clear(region); return 0; } extern int onig_region_set(OnigRegion* region, int at, int beg, int end) { if (at < 0) return ONIGERR_INVALID_ARGUMENT; if (at >= region->allocated) { int r = onig_region_resize(region, at + 1); if (r < 0) return r; } region->beg[at] = beg; region->end[at] = end; return 0; } extern void onig_region_init(OnigRegion* region) { region->num_regs = 0; region->allocated = 0; region->beg = (OnigPosition* )0; region->end = (OnigPosition* )0; region->history_root = (OnigCaptureTreeNode* )0; } extern OnigRegion* onig_region_new(void) { OnigRegion* r; r = (OnigRegion* )xmalloc(sizeof(OnigRegion)); if (r) onig_region_init(r); return r; } extern void onig_region_free(OnigRegion* r, int free_self) { if (r) { if (r->allocated > 0) { if (r->beg) xfree(r->beg); if (r->end) xfree(r->end); r->allocated = 0; } #ifdef USE_CAPTURE_HISTORY history_root_free(r); #endif if (free_self) xfree(r); } } extern void onig_region_copy(OnigRegion* to, OnigRegion* from) { #define RREGC_SIZE (sizeof(int) * from->num_regs) int i, r; if (to == from) return; r = onig_region_resize(to, from->num_regs); if (r) return; for (i = 0; i < from->num_regs; i++) { to->beg[i] = from->beg[i]; to->end[i] = from->end[i]; } to->num_regs = from->num_regs; #ifdef USE_CAPTURE_HISTORY history_root_free(to); if (IS_NOT_NULL(from->history_root)) { to->history_root = history_tree_clone(from->history_root); } #endif } /** stack **/ #define INVALID_STACK_INDEX -1 /* stack type */ /* used by normal-POP */ #define STK_ALT 0x0001 #define STK_LOOK_BEHIND_NOT 0x0002 #define STK_POS_NOT 0x0003 /* handled by normal-POP */ #define STK_MEM_START 0x0100 #define STK_MEM_END 0x8200 #define STK_REPEAT_INC 0x0300 #define STK_STATE_CHECK_MARK 0x1000 /* avoided by normal-POP */ #define STK_NULL_CHECK_START 0x3000 #define STK_NULL_CHECK_END 0x5000 /* for recursive call */ #define STK_MEM_END_MARK 0x8400 #define STK_POS 0x0500 /* used when POP-POS */ #define STK_STOP_BT 0x0600 /* mark for "(?>...)" */ #define STK_REPEAT 0x0700 #define STK_CALL_FRAME 0x0800 #define STK_RETURN 0x0900 #define STK_VOID 0x0a00 /* for fill a blank */ /* stack type check mask */ #define STK_MASK_POP_USED 0x00ff #define STK_MASK_TO_VOID_TARGET 0x10ff #define STK_MASK_MEM_END_OR_MARK 0x8000 /* MEM_END or MEM_END_MARK */ #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE #define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\ (msa).stack_p = (void* )0;\ (msa).options = (arg_option);\ (msa).region = (arg_region);\ (msa).start = (arg_start);\ (msa).gpos = (arg_gpos);\ (msa).best_len = ONIG_MISMATCH;\ } while(0) #else #define MATCH_ARG_INIT(msa, arg_option, arg_region, arg_start, arg_gpos) do {\ (msa).stack_p = (void* )0;\ (msa).options = (arg_option);\ (msa).region = (arg_region);\ (msa).start = (arg_start);\ (msa).gpos = (arg_gpos);\ } while(0) #endif #ifdef USE_COMBINATION_EXPLOSION_CHECK #define STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE 16 #define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) do { \ if ((state_num) > 0 && str_len >= STATE_CHECK_STRING_THRESHOLD_LEN) {\ unsigned int size = (unsigned int )(((str_len) + 1) * (state_num) + 7) >> 3;\ offset = ((offset) * (state_num)) >> 3;\ if (size > 0 && offset < size && size < STATE_CHECK_BUFF_MAX_SIZE) {\ if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {\ (msa).state_check_buff = (void* )xmalloc(size);\ CHECK_NULL_RETURN_MEMERR((msa).state_check_buff);\ }\ else \ (msa).state_check_buff = (void* )xalloca(size);\ xmemset(((char* )((msa).state_check_buff)+(offset)), 0, \ (size_t )(size - (offset))); \ (msa).state_check_buff_size = size;\ }\ else {\ (msa).state_check_buff = (void* )0;\ (msa).state_check_buff_size = 0;\ }\ }\ else {\ (msa).state_check_buff = (void* )0;\ (msa).state_check_buff_size = 0;\ }\ } while(0) #define MATCH_ARG_FREE(msa) do {\ if ((msa).stack_p) xfree((msa).stack_p);\ if ((msa).state_check_buff_size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) { \ if ((msa).state_check_buff) xfree((msa).state_check_buff);\ }\ } while(0) #else /* USE_COMBINATION_EXPLOSION_CHECK */ #define STATE_CHECK_BUFF_INIT(msa, str_len, offset, state_num) #define MATCH_ARG_FREE(msa) if ((msa).stack_p) xfree((msa).stack_p) #endif /* USE_COMBINATION_EXPLOSION_CHECK */ #define STACK_INIT(alloc_addr, ptr_num, stack_num) do {\ if (msa->stack_p) {\ alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num));\ stk_alloc = (OnigStackType* )(msa->stack_p);\ stk_base = stk_alloc;\ stk = stk_base;\ stk_end = stk_base + msa->stack_n;\ }\ else {\ alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num)\ + sizeof(OnigStackType) * (stack_num));\ stk_alloc = (OnigStackType* )(alloc_addr + sizeof(OnigStackIndex) * (ptr_num));\ stk_base = stk_alloc;\ stk = stk_base;\ stk_end = stk_base + (stack_num);\ }\ } while(0) #define STACK_SAVE do{\ if (stk_base != stk_alloc) {\ msa->stack_p = stk_base;\ msa->stack_n = stk_end - stk_base; /* TODO: check overflow */\ };\ } while(0) static unsigned int MatchStackLimitSize = DEFAULT_MATCH_STACK_LIMIT_SIZE; extern unsigned int onig_get_match_stack_limit_size(void) { return MatchStackLimitSize; } extern int onig_set_match_stack_limit_size(unsigned int size) { MatchStackLimitSize = size; return 0; } static int stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end, OnigStackType** arg_stk, OnigStackType* stk_alloc, OnigMatchArg* msa) { size_t n; OnigStackType *x, *stk_base, *stk_end, *stk; stk_base = *arg_stk_base; stk_end = *arg_stk_end; stk = *arg_stk; n = stk_end - stk_base; if (stk_base == stk_alloc && IS_NULL(msa->stack_p)) { x = (OnigStackType* )xmalloc(sizeof(OnigStackType) * n * 2); if (IS_NULL(x)) { STACK_SAVE; return ONIGERR_MEMORY; } xmemcpy(x, stk_base, n * sizeof(OnigStackType)); n *= 2; } else { unsigned int limit_size = MatchStackLimitSize; n *= 2; if (limit_size != 0 && n > limit_size) { if ((unsigned int )(stk_end - stk_base) == limit_size) return ONIGERR_MATCH_STACK_LIMIT_OVER; else n = limit_size; } x = (OnigStackType* )xrealloc(stk_base, sizeof(OnigStackType) * n); if (IS_NULL(x)) { STACK_SAVE; return ONIGERR_MEMORY; } } *arg_stk = x + (stk - stk_base); *arg_stk_base = x; *arg_stk_end = x + n; return 0; } #define STACK_ENSURE(n) do {\ if (stk_end - stk < (n)) {\ int r = stack_double(&stk_base, &stk_end, &stk, stk_alloc, msa);\ if (r != 0) { STACK_SAVE; return r; } \ }\ } while(0) #define STACK_AT(index) (stk_base + (index)) #define GET_STACK_INDEX(stk) ((stk) - stk_base) #define STACK_PUSH_TYPE(stack_type) do {\ STACK_ENSURE(1);\ stk->type = (stack_type);\ STACK_INC;\ } while(0) #define IS_TO_VOID_TARGET(stk) (((stk)->type & STK_MASK_TO_VOID_TARGET) != 0) #ifdef USE_COMBINATION_EXPLOSION_CHECK #define STATE_CHECK_POS(s,snum) \ (((s) - str) * num_comb_exp_check + ((snum) - 1)) #define STATE_CHECK_VAL(v,snum) do {\ if (state_check_buff != NULL) {\ int x = STATE_CHECK_POS(s,snum);\ (v) = state_check_buff[x/8] & (1<<(x%8));\ }\ else (v) = 0;\ } while(0) #define ELSE_IF_STATE_CHECK_MARK(stk) \ else if ((stk)->type == STK_STATE_CHECK_MARK) { \ int x = STATE_CHECK_POS(stk->u.state.pstr, stk->u.state.state_check);\ state_check_buff[x/8] |= (1<<(x%8)); \ } #define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\ STACK_ENSURE(1);\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ stk->u.state.pstr = (s);\ stk->u.state.pstr_prev = (sprev);\ stk->u.state.state_check = 0;\ stk->u.state.pkeep = (keep);\ STACK_INC;\ } while(0) #define STACK_PUSH_ENSURED(stack_type,pat) do {\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ stk->u.state.state_check = 0;\ STACK_INC;\ } while(0) #define STACK_PUSH_ALT_WITH_STATE_CHECK(pat,s,sprev,snum,keep) do {\ STACK_ENSURE(1);\ stk->type = STK_ALT;\ stk->u.state.pcode = (pat);\ stk->u.state.pstr = (s);\ stk->u.state.pstr_prev = (sprev);\ stk->u.state.state_check = ((state_check_buff != NULL) ? (snum) : 0);\ stk->u.state.pkeep = (keep);\ STACK_INC;\ } while(0) #define STACK_PUSH_STATE_CHECK(s,snum) do {\ if (state_check_buff != NULL) {\ STACK_ENSURE(1);\ stk->type = STK_STATE_CHECK_MARK;\ stk->u.state.pstr = (s);\ stk->u.state.state_check = (snum);\ STACK_INC;\ }\ } while(0) #else /* USE_COMBINATION_EXPLOSION_CHECK */ #define ELSE_IF_STATE_CHECK_MARK(stk) #define STACK_PUSH(stack_type,pat,s,sprev,keep) do {\ STACK_ENSURE(1);\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ stk->u.state.pstr = (s);\ stk->u.state.pstr_prev = (sprev);\ stk->u.state.pkeep = (keep);\ STACK_INC;\ } while(0) #define STACK_PUSH_ENSURED(stack_type,pat) do {\ stk->type = (stack_type);\ stk->u.state.pcode = (pat);\ STACK_INC;\ } while(0) #endif /* USE_COMBINATION_EXPLOSION_CHECK */ #define STACK_PUSH_ALT(pat,s,sprev,keep) STACK_PUSH(STK_ALT,pat,s,sprev,keep) #define STACK_PUSH_POS(s,sprev,keep) STACK_PUSH(STK_POS,NULL_UCHARP,s,sprev,keep) #define STACK_PUSH_POS_NOT(pat,s,sprev,keep) STACK_PUSH(STK_POS_NOT,pat,s,sprev,keep) #define STACK_PUSH_STOP_BT STACK_PUSH_TYPE(STK_STOP_BT) #define STACK_PUSH_LOOK_BEHIND_NOT(pat,s,sprev,keep) \ STACK_PUSH(STK_LOOK_BEHIND_NOT,pat,s,sprev,keep) #define STACK_PUSH_REPEAT(id, pat) do {\ STACK_ENSURE(1);\ stk->type = STK_REPEAT;\ stk->u.repeat.num = (id);\ stk->u.repeat.pcode = (pat);\ stk->u.repeat.count = 0;\ STACK_INC;\ } while(0) #define STACK_PUSH_REPEAT_INC(sindex) do {\ STACK_ENSURE(1);\ stk->type = STK_REPEAT_INC;\ stk->u.repeat_inc.si = (sindex);\ STACK_INC;\ } while(0) #define STACK_PUSH_MEM_START(mnum, s) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_START;\ stk->u.mem.num = (mnum);\ stk->u.mem.pstr = (s);\ stk->u.mem.start = mem_start_stk[mnum];\ stk->u.mem.end = mem_end_stk[mnum];\ mem_start_stk[mnum] = GET_STACK_INDEX(stk);\ mem_end_stk[mnum] = INVALID_STACK_INDEX;\ STACK_INC;\ } while(0) #define STACK_PUSH_MEM_END(mnum, s) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_END;\ stk->u.mem.num = (mnum);\ stk->u.mem.pstr = (s);\ stk->u.mem.start = mem_start_stk[mnum];\ stk->u.mem.end = mem_end_stk[mnum];\ mem_end_stk[mnum] = GET_STACK_INDEX(stk);\ STACK_INC;\ } while(0) #define STACK_PUSH_MEM_END_MARK(mnum) do {\ STACK_ENSURE(1);\ stk->type = STK_MEM_END_MARK;\ stk->u.mem.num = (mnum);\ STACK_INC;\ } while(0) #define STACK_GET_MEM_START(mnum, k) do {\ int level = 0;\ k = stk;\ while (k > stk_base) {\ k--;\ if ((k->type & STK_MASK_MEM_END_OR_MARK) != 0 \ && k->u.mem.num == (mnum)) {\ level++;\ }\ else if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\ if (level == 0) break;\ level--;\ }\ }\ } while(0) #define STACK_GET_MEM_RANGE(k, mnum, start, end) do {\ int level = 0;\ while (k < stk) {\ if (k->type == STK_MEM_START && k->u.mem.num == (mnum)) {\ if (level == 0) (start) = k->u.mem.pstr;\ level++;\ }\ else if (k->type == STK_MEM_END && k->u.mem.num == (mnum)) {\ level--;\ if (level == 0) {\ (end) = k->u.mem.pstr;\ break;\ }\ }\ k++;\ }\ } while(0) #define STACK_PUSH_NULL_CHECK_START(cnum, s) do {\ STACK_ENSURE(1);\ stk->type = STK_NULL_CHECK_START;\ stk->u.null_check.num = (cnum);\ stk->u.null_check.pstr = (s);\ STACK_INC;\ } while(0) #define STACK_PUSH_NULL_CHECK_END(cnum) do {\ STACK_ENSURE(1);\ stk->type = STK_NULL_CHECK_END;\ stk->u.null_check.num = (cnum);\ STACK_INC;\ } while(0) #define STACK_PUSH_CALL_FRAME(pat) do {\ STACK_ENSURE(1);\ stk->type = STK_CALL_FRAME;\ stk->u.call_frame.ret_addr = (pat);\ STACK_INC;\ } while(0) #define STACK_PUSH_RETURN do {\ STACK_ENSURE(1);\ stk->type = STK_RETURN;\ STACK_INC;\ } while(0) #ifdef ONIG_DEBUG #define STACK_BASE_CHECK(p, at) \ if ((p) < stk_base) {\ fprintf(stderr, "at %s\n", at);\ goto stack_error;\ } #else #define STACK_BASE_CHECK(p, at) #endif #define STACK_POP_ONE do {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP_ONE"); \ } while(0) #define STACK_POP do {\ switch (pop_level) {\ case STACK_POP_LEVEL_FREE:\ while (1) {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP"); \ if ((stk->type & STK_MASK_POP_USED) != 0) break;\ ELSE_IF_STATE_CHECK_MARK(stk);\ }\ break;\ case STACK_POP_LEVEL_MEM_START:\ while (1) {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP 2"); \ if ((stk->type & STK_MASK_POP_USED) != 0) break;\ else if (stk->type == STK_MEM_START) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ ELSE_IF_STATE_CHECK_MARK(stk);\ }\ break;\ default:\ while (1) {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP 3"); \ if ((stk->type & STK_MASK_POP_USED) != 0) break;\ else if (stk->type == STK_MEM_START) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ else if (stk->type == STK_REPEAT_INC) {\ STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\ }\ else if (stk->type == STK_MEM_END) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ ELSE_IF_STATE_CHECK_MARK(stk);\ }\ break;\ }\ } while(0) #define STACK_POP_TIL_POS_NOT do {\ while (1) {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP_TIL_POS_NOT"); \ if (stk->type == STK_POS_NOT) break;\ else if (stk->type == STK_MEM_START) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ else if (stk->type == STK_REPEAT_INC) {\ STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\ }\ else if (stk->type == STK_MEM_END) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ ELSE_IF_STATE_CHECK_MARK(stk);\ }\ } while(0) #define STACK_POP_TIL_LOOK_BEHIND_NOT do {\ while (1) {\ stk--;\ STACK_BASE_CHECK(stk, "STACK_POP_TIL_LOOK_BEHIND_NOT"); \ if (stk->type == STK_LOOK_BEHIND_NOT) break;\ else if (stk->type == STK_MEM_START) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ else if (stk->type == STK_REPEAT_INC) {\ STACK_AT(stk->u.repeat_inc.si)->u.repeat.count--;\ }\ else if (stk->type == STK_MEM_END) {\ mem_start_stk[stk->u.mem.num] = stk->u.mem.start;\ mem_end_stk[stk->u.mem.num] = stk->u.mem.end;\ }\ ELSE_IF_STATE_CHECK_MARK(stk);\ }\ } while(0) #define STACK_POS_END(k) do {\ k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_POS_END"); \ if (IS_TO_VOID_TARGET(k)) {\ k->type = STK_VOID;\ }\ else if (k->type == STK_POS) {\ k->type = STK_VOID;\ break;\ }\ }\ } while(0) #define STACK_STOP_BT_END do {\ OnigStackType *k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_STOP_BT_END"); \ if (IS_TO_VOID_TARGET(k)) {\ k->type = STK_VOID;\ }\ else if (k->type == STK_STOP_BT) {\ k->type = STK_VOID;\ break;\ }\ }\ } while(0) #define STACK_NULL_CHECK(isnull,id,s) do {\ OnigStackType* k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_NULL_CHECK"); \ if (k->type == STK_NULL_CHECK_START) {\ if (k->u.null_check.num == (id)) {\ (isnull) = (k->u.null_check.pstr == (s));\ break;\ }\ }\ }\ } while(0) #define STACK_NULL_CHECK_REC(isnull,id,s) do {\ int level = 0;\ OnigStackType* k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_NULL_CHECK_REC"); \ if (k->type == STK_NULL_CHECK_START) {\ if (k->u.null_check.num == (id)) {\ if (level == 0) {\ (isnull) = (k->u.null_check.pstr == (s));\ break;\ }\ else level--;\ }\ }\ else if (k->type == STK_NULL_CHECK_END) {\ level++;\ }\ }\ } while(0) #define STACK_NULL_CHECK_MEMST(isnull,id,s,reg) do {\ OnigStackType* k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST"); \ if (k->type == STK_NULL_CHECK_START) {\ if (k->u.null_check.num == (id)) {\ if (k->u.null_check.pstr != (s)) {\ (isnull) = 0;\ break;\ }\ else {\ OnigPosition endp;\ (isnull) = 1;\ while (k < stk) {\ if (k->type == STK_MEM_START) {\ if (k->u.mem.end == INVALID_STACK_INDEX) {\ (isnull) = 0; break;\ }\ if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\ endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\ else\ endp = k->u.mem.end;\ if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\ (isnull) = 0; break;\ }\ else if (endp != s) {\ (isnull) = -1; /* empty, but position changed */ \ }\ }\ k++;\ }\ break;\ }\ }\ }\ }\ } while(0) #define STACK_NULL_CHECK_MEMST_REC(isnull,id,s,reg) do {\ int level = 0;\ OnigStackType* k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_NULL_CHECK_MEMST_REC"); \ if (k->type == STK_NULL_CHECK_START) {\ if (k->u.null_check.num == (id)) {\ if (level == 0) {\ if (k->u.null_check.pstr != (s)) {\ (isnull) = 0;\ break;\ }\ else {\ OnigPosition endp;\ (isnull) = 1;\ while (k < stk) {\ if (k->type == STK_MEM_START) {\ if (k->u.mem.end == INVALID_STACK_INDEX) {\ (isnull) = 0; break;\ }\ if (BIT_STATUS_AT(reg->bt_mem_end, k->u.mem.num))\ endp = STACK_AT(k->u.mem.end)->u.mem.pstr;\ else\ endp = k->u.mem.end;\ if (STACK_AT(k->u.mem.start)->u.mem.pstr != endp) {\ (isnull) = 0; break;\ }\ else if (endp != s) {\ (isnull) = -1; /* empty, but position changed */ \ }\ }\ k++;\ }\ break;\ }\ }\ else {\ level--;\ }\ }\ }\ else if (k->type == STK_NULL_CHECK_END) {\ if (k->u.null_check.num == (id)) level++;\ }\ }\ } while(0) #define STACK_GET_REPEAT(id, k) do {\ int level = 0;\ k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_GET_REPEAT"); \ if (k->type == STK_REPEAT) {\ if (level == 0) {\ if (k->u.repeat.num == (id)) {\ break;\ }\ }\ }\ else if (k->type == STK_CALL_FRAME) level--;\ else if (k->type == STK_RETURN) level++;\ }\ } while(0) #define STACK_RETURN(addr) do {\ int level = 0;\ OnigStackType* k = stk;\ while (1) {\ k--;\ STACK_BASE_CHECK(k, "STACK_RETURN"); \ if (k->type == STK_CALL_FRAME) {\ if (level == 0) {\ (addr) = k->u.call_frame.ret_addr;\ break;\ }\ else level--;\ }\ else if (k->type == STK_RETURN)\ level++;\ }\ } while(0) #define STRING_CMP_SE(it,s1,s2,len) do {\ while (len-- > 0) {\ if (ONIG_CHARAT(s1++) != ONIG_CHARAT(s2++)) goto fail;\ }\ } while(0) #define STRING_CMP_IC_SE(it, case_fold_flag,s1,ps2,len) do {\ if (string_cmp_ic_se(it, encode, case_fold_flag, s1, ps2, len) == 0) \ goto fail; \ } while(0) static int string_cmp_ic_se(OnigIterator* it, OnigEncoding enc, int case_fold_flag, OnigPosition s1, OnigPosition* ps2, OnigPosition mblen) { UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN]; UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN]; UChar* p1, *p2; OnigPosition end1, s2, end2; int len1, len2; s2 = *ps2; end1 = s1 + mblen; end2 = s2 + mblen; while (s1 < end1) { len1 = ONIGENC_MBC_CASE_FOLD_SE(it, enc, case_fold_flag, &s1, end1, buf1); len2 = ONIGENC_MBC_CASE_FOLD_SE(it, enc, case_fold_flag, &s2, end2, buf2); if (len1 != len2) return 0; p1 = buf1; p2 = buf2; while (len1-- > 0) { if (*p1 != *p2) return 0; p1++; p2++; } } *ps2 = s2; return 1; } #define STRING_CMP_VALUE_SE(it, s1,s2,len,is_fail) do {\ is_fail = 0;\ while (len-- > 0) {\ if (ONIG_CHARAT(s1++) != ONIG_CHARAT(s2++)) {\ is_fail = 1; break;\ }\ }\ } while(0) #define STRING_CMP_VALUE_IC_SE(it, case_fold_flag,s1,ps2,len,is_fail) do {\ if (string_cmp_ic_se(it, encode, case_fold_flag, s1, ps2, len) == 0) \ is_fail = 1; \ else \ is_fail = 0; \ } while(0) #define IS_EMPTY_STR (str == end) #define ON_STR_BEGIN(s) ((s) == str) #define ON_STR_END(s) ((s) == end) #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE #define DATA_ENSURE_CHECK1 (s < right_range) #define DATA_ENSURE_CHECK(n) (s + (n) <= right_range) #define DATA_ENSURE(n) if (s + (n) > right_range) goto fail #else #define DATA_ENSURE_CHECK1 (s < end) #define DATA_ENSURE_CHECK(n) (s + (n) <= end) #define DATA_ENSURE(n) if (s + (n) > end) goto fail #endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */ #ifdef USE_CAPTURE_HISTORY static int make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp, OnigStackType* stk_top, OnigPosition str, regex_t* reg) { int n, r; OnigCaptureTreeNode* child; OnigStackType* k = *kp; while (k < stk_top) { if (k->type == STK_MEM_START) { n = k->u.mem.num; if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP && BIT_STATUS_AT(reg->capture_history, n) != 0) { child = history_node_new(); CHECK_NULL_RETURN_MEMERR(child); child->group = n; child->beg = k->u.mem.pstr - str; r = history_tree_add_child(node, child); if (r != 0) { history_tree_free(child); return r; } *kp = (k + 1); r = make_capture_history_tree(child, kp, stk_top, str, reg); if (r != 0) return r; k = *kp; child->end = k->u.mem.pstr - str; } } else if (k->type == STK_MEM_END) { if (k->u.mem.num == node->group) { node->end = k->u.mem.pstr - str; *kp = k; return 0; } } k++; } return 1; /* 1: root node ending. */ } #endif /* USE_CAPTURE_HISTORY */ #ifdef USE_BACKREF_WITH_LEVEL static int mem_is_in_memp(int mem, int num, UChar* memp) { int i; MemNumType m; for (i = 0; i < num; i++) { GET_MEMNUM_INC(m, memp); if (mem == (int )m) return 1; } return 0; } static int backref_match_at_nested_level(OnigIterator* it, regex_t* reg , OnigStackType* top, OnigStackType* stk_base , int ignore_case, int case_fold_flag , int nest, int mem_num, UChar* memp, OnigPosition* s, OnigPosition send) { OnigPosition ss, p, pstart, pend = ONIG_BADPOS; int level; OnigStackType* k; level = 0; k = top; k--; while (k >= stk_base) { if (k->type == STK_CALL_FRAME) { level--; } else if (k->type == STK_RETURN) { level++; } else if (level == nest) { if (k->type == STK_MEM_START) { if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) { pstart = k->u.mem.pstr; if (pend != ONIG_BADPOS) { if (pend - pstart > send - *s) return 0; /* or goto next_mem; */ p = pstart; ss = *s; if (ignore_case != 0) { if (string_cmp_ic_se(it, reg->enc, case_fold_flag, pstart, &ss, pend - pstart) == 0) return 0; /* or goto next_mem; */ } else { while (p < pend) { if (ONIG_CHARAT(p++) != ONIG_CHARAT(ss++)) return 0; /* or goto next_mem; */ } } *s = ss; return 1; } } } else if (k->type == STK_MEM_END) { if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) { pend = k->u.mem.pstr; } } } k--; } return 0; } #endif /* USE_BACKREF_WITH_LEVEL */ #ifdef ONIG_DEBUG_STATISTICS #define USE_TIMEOFDAY #ifdef USE_TIMEOFDAY #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif static struct timeval ts, te; #define GETTIME(t) gettimeofday(&(t), (struct timezone* )0) #define TIMEDIFF(te,ts) (((te).tv_usec - (ts).tv_usec) + \ (((te).tv_sec - (ts).tv_sec)*1000000)) #else /* USE_TIMEOFDAY */ #ifdef HAVE_SYS_TIMES_H #include #endif static struct tms ts, te; #define GETTIME(t) times(&(t)) #define TIMEDIFF(te,ts) ((te).tms_utime - (ts).tms_utime) #endif /* USE_TIMEOFDAY */ static int OpCounter[256]; static int OpPrevCounter[256]; static unsigned long OpTime[256]; static int OpCurr = OP_FINISH; static int OpPrevTarget = OP_FAIL; static int MaxStackDepth = 0; #define MOP_IN(opcode) do {\ if (opcode == OpPrevTarget) OpPrevCounter[OpCurr]++;\ OpCurr = opcode;\ OpCounter[opcode]++;\ GETTIME(ts);\ } while(0) #define MOP_OUT do {\ GETTIME(te);\ OpTime[OpCurr] += TIMEDIFF(te, ts);\ } while(0) extern void onig_statistics_init(void) { int i; for (i = 0; i < 256; i++) { OpCounter[i] = OpPrevCounter[i] = 0; OpTime[i] = 0; } MaxStackDepth = 0; } extern void onig_print_statistics(FILE* f) { int i; fprintf(f, " count prev time\n"); for (i = 0; OnigOpInfo[i].opcode >= 0; i++) { fprintf(f, "%8d: %8d: %10ld: %s\n", OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name); } fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth); } #define STACK_INC do {\ stk++;\ if (stk - stk_base > MaxStackDepth) \ MaxStackDepth = stk - stk_base;\ } while(0) #else /* ONIG_DEBUG_STATISTICS */ #define STACK_INC stk++ #define MOP_IN(opcode) #define MOP_OUT #endif /* ONIG_DEBUG_STATISTICS */ /* matching region of POSIX API */ typedef int regoff_t; typedef struct { regoff_t rm_so; regoff_t rm_eo; } posix_regmatch_t; /* match data(str - end) from position (sstart). */ /* if sstart == str then set sprev to NULL. */ static OnigPosition match_at(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE const OnigPosition right_range, #endif const OnigPosition sstart, OnigPosition sprev, OnigMatchArg* msa) { static UChar FinishCode[] = { OP_FINISH }; int i, num_mem, pop_level; OnigPosition n, best_len; LengthType tlen, tlen2; MemNumType mem; RelAddrType addr; OnigOptionType option = reg->options; OnigEncoding encode = reg->enc; OnigCaseFoldType case_fold_flag = reg->case_fold_flag; OnigPosition s, q, sbegin; UChar *p = reg->p; OnigPosition pkeep; char *alloca_base; OnigStackType *stk_alloc, *stk_base, *stk, *stk_end; OnigStackType *stkp; /* used as any purpose. */ OnigStackIndex si; OnigStackIndex *repeat_stk; OnigStackIndex *mem_start_stk, *mem_end_stk; #ifdef USE_COMBINATION_EXPLOSION_CHECK int scv; unsigned char* state_check_buff = msa->state_check_buff; int num_comb_exp_check = reg->num_comb_exp_check; #endif #ifdef USE_SUBEXP_CALL /* Stack #0 is used to store the pattern itself and used for (?R), \g<0>, etc. */ n = reg->num_repeat + (reg->num_mem + 1) * 2; STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE); pop_level = reg->stack_pop_level; num_mem = reg->num_mem; repeat_stk = (OnigStackIndex* )alloca_base; mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat); mem_end_stk = mem_start_stk + (num_mem + 1); for (i = 0; i <= num_mem; i++) { mem_start_stk[i] = mem_end_stk[i] = INVALID_STACK_INDEX; } #else /* USE_SUBEXP_CALL */ /* Stack #0 not is used. */ n = reg->num_repeat + reg->num_mem * 2; STACK_INIT(alloca_base, n, INIT_MATCH_STACK_SIZE); pop_level = reg->stack_pop_level; num_mem = reg->num_mem; repeat_stk = (OnigStackIndex* )alloca_base; mem_start_stk = (OnigStackIndex* )(repeat_stk + reg->num_repeat); mem_end_stk = mem_start_stk + num_mem; mem_start_stk--; /* for index start from 1, mem_start_stk[1]..mem_start_stk[num_mem] */ mem_end_stk--; /* for index start from 1, mem_end_stk[1]..mem_end_stk[num_mem] */ for (i = 1; i <= num_mem; i++) { mem_start_stk[i] = mem_end_stk[i] = INVALID_STACK_INDEX; } #endif /* USE_SUBEXP_CALL */ #ifdef ONIG_DEBUG_MATCH fprintf(stderr, "match_at: ptr: %p, str: %d, end: %d, start: %d, sprev: %d\n", it->ptr, (int )str, (int )end, (int )sstart, (int )sprev); fprintf(stderr, "size: %d, start offset: %d\n", (int )(end - str), (int )(sstart - str)); #endif STACK_PUSH_ENSURED(STK_ALT, FinishCode); /* bottom stack */ best_len = ONIG_MISMATCH; s = sstart; pkeep = sstart; while (1) { #ifdef ONIG_DEBUG_MATCH if (ONIG_IS_NOT_BADPOS(s)) { OnigPosition q; UChar *bp, buf[50]; int len; fprintf(stderr, "%4d> \"", (int )(s - str)); bp = buf; if (*p != OP_FINISH) { /* s may not be a valid pointer if OP_FINISH. */ for (i = 0, q = s; i < 7 && q < end; i++) { len = enclen_se(it, encode, q); while (len-- > 0) *bp++ = ONIG_CHARAT(q++); } } if (q < end) { xmemcpy(bp, "...\"", 4); bp += 4; } else { xmemcpy(bp, "\"", 1); bp += 1; } *bp = 0; fputs((char* )buf, stderr); for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr); onig_print_compiled_byte_code(stderr, p, NULL, encode); fprintf(stderr, "\n"); } #endif sbegin = s; switch (*p++) { case OP_END: MOP_IN(OP_END); n = s - sstart; if (n > best_len) { OnigRegion* region; #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE if (IS_FIND_LONGEST(option)) { if (n > msa->best_len) { msa->best_len = n; msa->best_s = sstart; } else goto end_best_len; } #endif best_len = n; region = msa->region; if (region) { #ifdef USE_POSIX_API_REGION_OPTION if (IS_POSIX_REGION(msa->options)) { posix_regmatch_t* rmt = (posix_regmatch_t* )region; rmt[0].rm_so = (regoff_t )(((pkeep > s) ? s : pkeep) - str); rmt[0].rm_eo = (regoff_t )(s - str); for (i = 1; i <= num_mem; i++) { if (mem_end_stk[i] != INVALID_STACK_INDEX) { if (BIT_STATUS_AT(reg->bt_mem_start, i)) rmt[i].rm_so = (regoff_t )(STACK_AT(mem_start_stk[i])->u.mem.pstr - str); else rmt[i].rm_so = (regoff_t )((OnigPosition)mem_start_stk[i] - str); rmt[i].rm_eo = (regoff_t )((BIT_STATUS_AT(reg->bt_mem_end, i) ? STACK_AT(mem_end_stk[i])->u.mem.pstr : (OnigPosition)mem_end_stk[i]) - str); } else { rmt[i].rm_so = rmt[i].rm_eo = ONIG_REGION_NOTPOS; } } } else { #endif /* USE_POSIX_API_REGION_OPTION */ region->beg[0] = ((pkeep > s) ? s : pkeep) - str; region->end[0] = s - str; for (i = 1; i <= num_mem; i++) { if (mem_end_stk[i] != INVALID_STACK_INDEX) { if (BIT_STATUS_AT(reg->bt_mem_start, i)) region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str; else region->beg[i] = (OnigPosition)mem_start_stk[i] - str; region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i) ? STACK_AT(mem_end_stk[i])->u.mem.pstr : (OnigPosition)mem_end_stk[i]) - str; } else { region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS; } } #ifdef USE_CAPTURE_HISTORY if (reg->capture_history != 0) { int r; OnigCaptureTreeNode* node; if (IS_NULL(region->history_root)) { region->history_root = node = history_node_new(); CHECK_NULL_RETURN_MEMERR(node); } else { node = region->history_root; history_tree_clear(node); } node->group = 0; node->beg = ((pkeep > s) ? s : pkeep) - str; node->end = s - str; stkp = stk_base; r = make_capture_history_tree(region->history_root, &stkp, stk, str, reg); if (r < 0) { best_len = r; /* error code */ goto finish; } } #endif /* USE_CAPTURE_HISTORY */ #ifdef USE_POSIX_API_REGION_OPTION } /* else IS_POSIX_REGION() */ #endif } /* if (region) */ } /* n > best_len */ #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE end_best_len: #endif MOP_OUT; if (IS_FIND_CONDITION(option)) { if (IS_FIND_NOT_EMPTY(option) && s == sstart) { best_len = ONIG_MISMATCH; goto fail; /* for retry */ } if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) { goto fail; /* for retry */ } } /* default behavior: return first-matching result. */ goto finish; break; case OP_EXACT1: MOP_IN(OP_EXACT1); #if 0 DATA_ENSURE(1); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; #endif if (*p != ONIG_CHARAT(s++)) goto fail; DATA_ENSURE(0); p++; MOP_OUT; break; case OP_EXACT1_IC: MOP_IN(OP_EXACT1_IC); { int len; UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN]; DATA_ENSURE(1); len = ONIGENC_MBC_CASE_FOLD_SE(it, encode, /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */ case_fold_flag, &s, end, lowbuf); DATA_ENSURE(0); q = lowbuf; while (len-- > 0) { if (*p != *q) { goto fail; } p++; q++; } } MOP_OUT; break; case OP_EXACT2: MOP_IN(OP_EXACT2); DATA_ENSURE(2); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; sprev = s; p++; s++; MOP_OUT; continue; break; case OP_EXACT3: MOP_IN(OP_EXACT3); DATA_ENSURE(3); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; sprev = s; p++; s++; MOP_OUT; continue; break; case OP_EXACT4: MOP_IN(OP_EXACT4); DATA_ENSURE(4); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; sprev = s; p++; s++; MOP_OUT; continue; break; case OP_EXACT5: MOP_IN(OP_EXACT5); DATA_ENSURE(5); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; sprev = s; p++; s++; MOP_OUT; continue; break; case OP_EXACTN: MOP_IN(OP_EXACTN); GET_LENGTH_INC(tlen, p); DATA_ENSURE(tlen); while (tlen-- > 0) { if (*p++ != ONIG_CHARAT(s++)) goto fail; } sprev = s - 1; MOP_OUT; continue; break; case OP_EXACTN_IC: MOP_IN(OP_EXACTN_IC); { int len; UChar *q, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN]; GET_LENGTH_INC(tlen, p); endp = p + tlen; while (p < endp) { sprev = s; DATA_ENSURE(1); len = ONIGENC_MBC_CASE_FOLD_SE(it, encode, /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */ case_fold_flag, &s, end, lowbuf); DATA_ENSURE(0); q = lowbuf; while (len-- > 0) { if (*p != *q) goto fail; p++; q++; } } } MOP_OUT; continue; break; case OP_EXACTMB2N1: MOP_IN(OP_EXACTMB2N1); DATA_ENSURE(2); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; MOP_OUT; break; case OP_EXACTMB2N2: MOP_IN(OP_EXACTMB2N2); DATA_ENSURE(4); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; sprev = s; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; MOP_OUT; continue; break; case OP_EXACTMB2N3: MOP_IN(OP_EXACTMB2N3); DATA_ENSURE(6); if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; sprev = s; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; MOP_OUT; continue; break; case OP_EXACTMB2N: MOP_IN(OP_EXACTMB2N); GET_LENGTH_INC(tlen, p); DATA_ENSURE(tlen * 2); while (tlen-- > 0) { if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; } sprev = s - 2; MOP_OUT; continue; break; case OP_EXACTMB3N: MOP_IN(OP_EXACTMB3N); GET_LENGTH_INC(tlen, p); DATA_ENSURE(tlen * 3); while (tlen-- > 0) { if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; } sprev = s - 3; MOP_OUT; continue; break; case OP_EXACTMBN: MOP_IN(OP_EXACTMBN); GET_LENGTH_INC(tlen, p); /* mb-len */ GET_LENGTH_INC(tlen2, p); /* string len */ tlen2 *= tlen; DATA_ENSURE(tlen2); while (tlen2-- > 0) { if (*p != ONIG_CHARAT(s)) goto fail; p++; s++; } sprev = s - tlen; MOP_OUT; continue; break; case OP_CCLASS: MOP_IN(OP_CCLASS); DATA_ENSURE(1); if (BITSET_AT(((BitSetRef )p), ONIG_CHARAT(s)) == 0) goto fail; p += SIZE_BITSET; s += enclen_se(it, encode, s); /* OP_CCLASS can match mb-code. \D, \S */ MOP_OUT; break; case OP_CCLASS_MB: MOP_IN(OP_CCLASS_MB); if (! ONIGENC_IS_MBC_HEAD_SE(it, encode, s)) goto fail; cclass_mb: GET_LENGTH_INC(tlen, p); { OnigCodePoint code; OnigPosition ss; int mb_len; DATA_ENSURE(1); mb_len = enclen_se(it, encode, s); DATA_ENSURE(mb_len); ss = s; s += mb_len; code = ONIGENC_MBC_TO_CODE_SE(it, encode, ss, s); #ifdef PLATFORM_UNALIGNED_WORD_ACCESS if (! onig_is_in_code_range(p, code)) goto fail; #else UChar* q = p; ALIGNMENT_RIGHT(q); if (! onig_is_in_code_range(q, code)) goto fail; #endif } p += tlen; MOP_OUT; break; case OP_CCLASS_MIX: MOP_IN(OP_CCLASS_MIX); DATA_ENSURE(1); if (ONIGENC_IS_MBC_HEAD_SE(it, encode, s)) { p += SIZE_BITSET; goto cclass_mb; } else { if (BITSET_AT(((BitSetRef )p), ONIG_CHARAT(s)) == 0) goto fail; p += SIZE_BITSET; GET_LENGTH_INC(tlen, p); p += tlen; s++; } MOP_OUT; break; case OP_CCLASS_NOT: MOP_IN(OP_CCLASS_NOT); DATA_ENSURE(1); if (BITSET_AT(((BitSetRef )p), ONIG_CHARAT(s)) != 0) goto fail; p += SIZE_BITSET; s += enclen_se(it, encode, s); MOP_OUT; break; case OP_CCLASS_MB_NOT: MOP_IN(OP_CCLASS_MB_NOT); DATA_ENSURE(1); if (! ONIGENC_IS_MBC_HEAD_SE(it, encode, s)) { s++; GET_LENGTH_INC(tlen, p); p += tlen; goto cc_mb_not_success; } cclass_mb_not: GET_LENGTH_INC(tlen, p); { OnigCodePoint code; OnigPosition ss; int mb_len = enclen_se(it, encode, s); if (! DATA_ENSURE_CHECK(mb_len)) { DATA_ENSURE(1); s = end; p += tlen; goto cc_mb_not_success; } ss = s; s += mb_len; code = ONIGENC_MBC_TO_CODE_SE(it, encode, ss, s); #ifdef PLATFORM_UNALIGNED_WORD_ACCESS if (onig_is_in_code_range(p, code)) goto fail; #else UChar* q = p; ALIGNMENT_RIGHT(q); if (onig_is_in_code_range(q, code)) goto fail; #endif } p += tlen; cc_mb_not_success: MOP_OUT; break; case OP_CCLASS_MIX_NOT: MOP_IN(OP_CCLASS_MIX_NOT); DATA_ENSURE(1); if (ONIGENC_IS_MBC_HEAD_SE(it, encode, s)) { p += SIZE_BITSET; goto cclass_mb_not; } else { if (BITSET_AT(((BitSetRef )p), ONIG_CHARAT(s)) != 0) goto fail; p += SIZE_BITSET; GET_LENGTH_INC(tlen, p); p += tlen; s++; } MOP_OUT; break; case OP_CCLASS_NODE: MOP_IN(OP_CCLASS_NODE); { OnigCodePoint code; void *node; int mb_len; OnigPosition ss; DATA_ENSURE(1); GET_POINTER_INC(node, p); mb_len = enclen_se(it, encode, s); ss = s; s += mb_len; DATA_ENSURE(0); code = ONIGENC_MBC_TO_CODE_SE(it, encode, ss, s); if (onig_is_code_in_cc_len(mb_len, code, node) == 0) goto fail; } MOP_OUT; break; case OP_ANYCHAR: MOP_IN(OP_ANYCHAR); DATA_ENSURE(1); n = enclen_se(it, encode, s); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 0)) goto fail; s += n; MOP_OUT; break; case OP_ANYCHAR_ML: MOP_IN(OP_ANYCHAR_ML); DATA_ENSURE(1); n = enclen_se(it, encode, s); DATA_ENSURE(n); s += n; MOP_OUT; break; case OP_ANYCHAR_STAR: MOP_IN(OP_ANYCHAR_STAR); while (DATA_ENSURE_CHECK1) { STACK_PUSH_ALT(p, s, sprev, pkeep); n = enclen_se(it, encode, s); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 0)) goto fail; sprev = s; s += n; } MOP_OUT; break; case OP_ANYCHAR_ML_STAR: MOP_IN(OP_ANYCHAR_ML_STAR); while (DATA_ENSURE_CHECK1) { STACK_PUSH_ALT(p, s, sprev, pkeep); n = enclen_se(it, encode, s); if (n > 1) { DATA_ENSURE(n); sprev = s; s += n; } else { sprev = s; s++; } } MOP_OUT; break; case OP_ANYCHAR_STAR_PEEK_NEXT: MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT); while (DATA_ENSURE_CHECK1) { if (*p == ONIG_CHARAT(s)) { STACK_PUSH_ALT(p + 1, s, sprev, pkeep); } n = enclen_se(it, encode, s); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 0)) goto fail; sprev = s; s += n; } p++; MOP_OUT; break; case OP_ANYCHAR_ML_STAR_PEEK_NEXT:MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT); while (DATA_ENSURE_CHECK1) { if (*p == ONIG_CHARAT(s)) { STACK_PUSH_ALT(p + 1, s, sprev, pkeep); } n = enclen_se(it, encode, s); if (n > 1) { DATA_ENSURE(n); sprev = s; s += n; } else { sprev = s; s++; } } p++; MOP_OUT; break; #ifdef USE_COMBINATION_EXPLOSION_CHECK case OP_STATE_CHECK_ANYCHAR_STAR: MOP_IN(OP_STATE_CHECK_ANYCHAR_STAR); GET_STATE_CHECK_NUM_INC(mem, p); while (DATA_ENSURE_CHECK1) { STATE_CHECK_VAL(scv, mem); if (scv) goto fail; STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep); n = enclen_se(it, encode, s); DATA_ENSURE(n); if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 0)) goto fail; sprev = s; s += n; } MOP_OUT; break; case OP_STATE_CHECK_ANYCHAR_ML_STAR: MOP_IN(OP_STATE_CHECK_ANYCHAR_ML_STAR); GET_STATE_CHECK_NUM_INC(mem, p); while (DATA_ENSURE_CHECK1) { STATE_CHECK_VAL(scv, mem); if (scv) goto fail; STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep); n = enclen_se(it, encode, s); if (n > 1) { DATA_ENSURE(n); sprev = s; s += n; } else { sprev = s; s++; } } MOP_OUT; break; #endif /* USE_COMBINATION_EXPLOSION_CHECK */ case OP_WORD: MOP_IN(OP_WORD); DATA_ENSURE(1); if (! ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)) goto fail; s += enclen_se(it, encode, s); MOP_OUT; break; case OP_ASCII_WORD: MOP_IN(OP_ASCII_WORD); DATA_ENSURE(1); if (! ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) goto fail; s += enclen_se(it, encode, s); MOP_OUT; break; case OP_NOT_WORD: MOP_IN(OP_NOT_WORD); DATA_ENSURE(1); if (ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)) goto fail; s += enclen_se(it, encode, s); MOP_OUT; break; case OP_NOT_ASCII_WORD: MOP_IN(OP_NOT_ASCII_WORD); DATA_ENSURE(1); if (ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) goto fail; s += enclen_se(it, encode, s); MOP_OUT; break; case OP_WORD_BOUND: MOP_IN(OP_WORD_BOUND); if (ON_STR_BEGIN(s)) { DATA_ENSURE(1); if (! ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)) goto fail; } else if (ON_STR_END(s)) { if (! ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)) goto fail; } else { if (ONIGENC_IS_MBC_WORD_SE(it, encode, s, end) == ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)) goto fail; } MOP_OUT; continue; break; case OP_ASCII_WORD_BOUND: MOP_IN(OP_ASCII_WORD_BOUND); if (ON_STR_BEGIN(s)) { DATA_ENSURE(1); if (! ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) goto fail; } else if (ON_STR_END(s)) { if (! ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) goto fail; } else { if (ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end) == ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) goto fail; } MOP_OUT; continue; break; case OP_NOT_WORD_BOUND: MOP_IN(OP_NOT_WORD_BOUND); if (ON_STR_BEGIN(s)) { if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)) goto fail; } else if (ON_STR_END(s)) { if (ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)) goto fail; } else { if (ONIGENC_IS_MBC_WORD_SE(it, encode, s, end) != ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)) goto fail; } MOP_OUT; continue; break; case OP_NOT_ASCII_WORD_BOUND: MOP_IN(OP_NOT_ASCII_WORD_BOUND); if (ON_STR_BEGIN(s)) { if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) goto fail; } else if (ON_STR_END(s)) { if (ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) goto fail; } else { if (ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end) != ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) goto fail; } MOP_OUT; continue; break; #ifdef USE_WORD_BEGIN_END case OP_WORD_BEGIN: MOP_IN(OP_WORD_BEGIN); if (DATA_ENSURE_CHECK1 /*&& ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)*/) { if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end) || !ONIGENC_IS_MBC_WORD_SE(it, encode, s, end)) { MOP_OUT; continue; } else if (ONIGENC_SCRIPT_SE(it, encode, sprev, end) != ONIGENC_SCRIPT_SE(it, encode, s, end)) { if (!ONIGENC_IS_MBC_SINGLEBYTE_SE(it, encode, sprev, end) || !ONIGENC_IS_MBC_SINGLEBYTE_SE(it, encode, s, end)) { MOP_OUT; continue; } } } goto fail; break; case OP_ASCII_WORD_BEGIN: MOP_IN(OP_ASCII_WORD_BEGIN); if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) { if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) { MOP_OUT; continue; } } goto fail; break; case OP_WORD_END: MOP_IN(OP_WORD_END); if (!ON_STR_BEGIN(s) /*&& ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)*/) { if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD_SE(it, encode, s, end) || !ONIGENC_IS_MBC_WORD_SE(it, encode, sprev, end)) { MOP_OUT; continue; } else if (ONIGENC_SCRIPT_SE(it, encode, s, end) != ONIGENC_SCRIPT_SE(it, encode, sprev, end)) { if (!ONIGENC_IS_MBC_SINGLEBYTE_SE(it, encode, s, end) || !ONIGENC_IS_MBC_SINGLEBYTE_SE(it, encode, sprev, end)) { MOP_OUT; continue; } } } goto fail; break; case OP_ASCII_WORD_END: MOP_IN(OP_ASCII_WORD_END); if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, sprev, end)) { if (ON_STR_END(s) || !ONIGENC_IS_MBC_ASCII_WORD_SE(it, encode, s, end)) { MOP_OUT; continue; } } goto fail; break; #endif case OP_BEGIN_BUF: MOP_IN(OP_BEGIN_BUF); if (! ON_STR_BEGIN(s)) goto fail; MOP_OUT; continue; break; case OP_END_BUF: MOP_IN(OP_END_BUF); if (! ON_STR_END(s)) goto fail; MOP_OUT; continue; break; case OP_BEGIN_LINE: MOP_IN(OP_BEGIN_LINE); op_begin_line: if (ON_STR_BEGIN(s)) { if (IS_NOTBOL(msa->options)) goto fail; MOP_OUT; continue; } else if (ONIGENC_IS_MBC_NEWLINE_SE(it, encode, sprev, end) #ifdef USE_CRNL_AS_LINE_TERMINATOR && !(IS_NEWLINE_CRLF(option) && ONIGENC_IS_MBC_CRNL_SE(it,encode, sprev, end)) #endif /*&& !ON_STR_END(s)*/) { MOP_OUT; continue; } goto fail; break; case OP_END_LINE: MOP_IN(OP_END_LINE); if (ON_STR_END(s)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, sprev, str, end, option, 1)) { #endif if (IS_NOTEOL(msa->options)) goto fail; MOP_OUT; continue; #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE } #endif } else if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 1)) { MOP_OUT; continue; } goto fail; break; case OP_SEMI_END_BUF: MOP_IN(OP_SEMI_END_BUF); if (ON_STR_END(s)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, sprev, str, end, option, 1)) { #endif if (IS_NOTEOL(msa->options)) goto fail; MOP_OUT; continue; #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE } #endif } else if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, encode, s, str, end, option, 1)) { OnigPosition ss = s + enclen_se(it, encode, s); if (ON_STR_END(ss)) { MOP_OUT; continue; } #ifdef USE_CRNL_AS_LINE_TERMINATOR else if (IS_NEWLINE_CRLF(option) && ONIGENC_IS_MBC_CRNL_SE(it, encode, s, end)) { ss += enclen_se(it, encode, ss); if (ON_STR_END(ss)) { MOP_OUT; continue; } } #endif } goto fail; break; case OP_BEGIN_POSITION: MOP_IN(OP_BEGIN_POSITION); if (s != msa->gpos) goto fail; MOP_OUT; continue; break; case OP_BEGIN_POS_OR_LINE: MOP_IN(OP_BEGIN_POS_OR_LINE); if (s != msa->gpos) goto op_begin_line; MOP_OUT; continue; break; case OP_MEMORY_START_PUSH: MOP_IN(OP_MEMORY_START_PUSH); GET_MEMNUM_INC(mem, p); STACK_PUSH_MEM_START(mem, s); MOP_OUT; continue; break; case OP_MEMORY_START: MOP_IN(OP_MEMORY_START); GET_MEMNUM_INC(mem, p); mem_start_stk[mem] = (OnigStackIndex)(s); MOP_OUT; continue; break; case OP_MEMORY_END_PUSH: MOP_IN(OP_MEMORY_END_PUSH); GET_MEMNUM_INC(mem, p); STACK_PUSH_MEM_END(mem, s); MOP_OUT; continue; break; case OP_MEMORY_END: MOP_IN(OP_MEMORY_END); GET_MEMNUM_INC(mem, p); mem_end_stk[mem] = (OnigStackIndex)(s); MOP_OUT; continue; break; case OP_KEEP: MOP_IN(OP_KEEP); pkeep = s; MOP_OUT; continue; break; #ifdef USE_SUBEXP_CALL case OP_MEMORY_END_PUSH_REC: MOP_IN(OP_MEMORY_END_PUSH_REC); GET_MEMNUM_INC(mem, p); STACK_GET_MEM_START(mem, stkp); /* should be before push mem-end. */ STACK_PUSH_MEM_END(mem, s); mem_start_stk[mem] = GET_STACK_INDEX(stkp); MOP_OUT; continue; break; case OP_MEMORY_END_REC: MOP_IN(OP_MEMORY_END_REC); GET_MEMNUM_INC(mem, p); mem_end_stk[mem] = (OnigStackIndex)s; STACK_GET_MEM_START(mem, stkp); if (BIT_STATUS_AT(reg->bt_mem_start, mem)) mem_start_stk[mem] = GET_STACK_INDEX(stkp); else mem_start_stk[mem] = (OnigStackIndex )(stkp->u.mem.pstr); STACK_PUSH_MEM_END_MARK(mem); MOP_OUT; continue; break; #endif case OP_BACKREF1: MOP_IN(OP_BACKREF1); mem = 1; goto backref; break; case OP_BACKREF2: MOP_IN(OP_BACKREF2); mem = 2; goto backref; break; case OP_BACKREFN: MOP_IN(OP_BACKREFN); GET_MEMNUM_INC(mem, p); backref: { int len; OnigPosition pstart, pend; /* if you want to remove following line, you should check in parse and compile time. */ if (mem > num_mem) goto fail; if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail; if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail; if (BIT_STATUS_AT(reg->bt_mem_start, mem)) pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr; else pstart = (OnigPosition)mem_start_stk[mem]; pend = (BIT_STATUS_AT(reg->bt_mem_end, mem) ? STACK_AT(mem_end_stk[mem])->u.mem.pstr : (OnigPosition)mem_end_stk[mem]); n = pend - pstart; DATA_ENSURE(n); sprev = s; STRING_CMP_SE(it, pstart, s, n); while (sprev + (len = enclen_se(it, encode, sprev)) < s) sprev += len; MOP_OUT; continue; } break; case OP_BACKREFN_IC: MOP_IN(OP_BACKREFN_IC); GET_MEMNUM_INC(mem, p); { int len; OnigPosition pstart, pend; /* if you want to remove following line, you should check in parse and compile time. */ if (mem > num_mem) goto fail; if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail; if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail; if (BIT_STATUS_AT(reg->bt_mem_start, mem)) pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr; else pstart = (OnigPosition)(mem_start_stk[mem]); pend = (BIT_STATUS_AT(reg->bt_mem_end, mem) ? STACK_AT(mem_end_stk[mem])->u.mem.pstr : (OnigPosition)(mem_end_stk[mem])); n = pend - pstart; DATA_ENSURE(n); sprev = s; STRING_CMP_IC_SE(it, case_fold_flag, pstart, &s, n); while (sprev + (len = enclen_se(it, encode, sprev)) < s) sprev += len; MOP_OUT; continue; } break; case OP_BACKREF_MULTI: MOP_IN(OP_BACKREF_MULTI); { int len, is_fail; OnigPosition pstart, pend, swork; GET_LENGTH_INC(tlen, p); for (i = 0; i < tlen; i++) { GET_MEMNUM_INC(mem, p); if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue; if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue; if (BIT_STATUS_AT(reg->bt_mem_start, mem)) pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr; else pstart = (OnigPosition)(mem_start_stk[mem]); pend = (BIT_STATUS_AT(reg->bt_mem_end, mem) ? STACK_AT(mem_end_stk[mem])->u.mem.pstr : (OnigPosition)(mem_end_stk[mem])); n = pend - pstart; DATA_ENSURE(n); sprev = s; swork = s; STRING_CMP_VALUE_SE(it, pstart, swork, n, is_fail); if (is_fail) continue; s = swork; while (sprev + (len = enclen_se(it, encode, sprev)) < s) sprev += len; p += (SIZE_MEMNUM * (tlen - i - 1)); break; /* success */ } if (i == tlen) goto fail; MOP_OUT; continue; } break; case OP_BACKREF_MULTI_IC: MOP_IN(OP_BACKREF_MULTI_IC); { int len, is_fail; OnigPosition pstart, pend, swork; GET_LENGTH_INC(tlen, p); for (i = 0; i < tlen; i++) { GET_MEMNUM_INC(mem, p); if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue; if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue; if (BIT_STATUS_AT(reg->bt_mem_start, mem)) pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr; else pstart = (OnigPosition)(mem_start_stk[mem]); pend = (BIT_STATUS_AT(reg->bt_mem_end, mem) ? STACK_AT(mem_end_stk[mem])->u.mem.pstr : (OnigPosition)(mem_end_stk[mem])); n = pend - pstart; DATA_ENSURE(n); sprev = s; swork = s; STRING_CMP_VALUE_IC_SE(it, case_fold_flag, pstart, &swork, n, is_fail); if (is_fail) continue; s = swork; while (sprev + (len = enclen_se(it, encode, sprev)) < s) sprev += len; p += (SIZE_MEMNUM * (tlen - i - 1)); break; /* success */ } if (i == tlen) goto fail; MOP_OUT; continue; } break; #ifdef USE_BACKREF_WITH_LEVEL case OP_BACKREF_WITH_LEVEL: { int len; OnigOptionType ic; LengthType level; GET_OPTION_INC(ic, p); GET_LENGTH_INC(level, p); GET_LENGTH_INC(tlen, p); sprev = s; if (backref_match_at_nested_level(it, reg, stk, stk_base, ic , case_fold_flag, (int )level, (int )tlen, p, &s, end)) { while (sprev + (len = enclen_se(it, encode, sprev)) < s) sprev += len; p += (SIZE_MEMNUM * tlen); } else goto fail; MOP_OUT; continue; } break; #endif #if 0 /* no need: IS_DYNAMIC_OPTION() == 0 */ case OP_SET_OPTION_PUSH: MOP_IN(OP_SET_OPTION_PUSH); GET_OPTION_INC(option, p); STACK_PUSH_ALT(p, s, sprev, pkeep); p += SIZE_OP_SET_OPTION + SIZE_OP_FAIL; MOP_OUT; continue; break; case OP_SET_OPTION: MOP_IN(OP_SET_OPTION); GET_OPTION_INC(option, p); MOP_OUT; continue; break; #endif case OP_NULL_CHECK_START: MOP_IN(OP_NULL_CHECK_START); GET_MEMNUM_INC(mem, p); /* mem: null check id */ STACK_PUSH_NULL_CHECK_START(mem, s); MOP_OUT; continue; break; case OP_NULL_CHECK_END: MOP_IN(OP_NULL_CHECK_END); { int isnull; GET_MEMNUM_INC(mem, p); /* mem: null check id */ STACK_NULL_CHECK(isnull, mem, s); if (isnull) { #ifdef ONIG_DEBUG_MATCH fprintf(stderr, "NULL_CHECK_END: skip id:%d, s:%d, ptr: %p)\n", (int )mem, (int )s, it->ptr); #endif null_check_found: /* empty loop founded, skip next instruction */ switch (*p++) { case OP_JUMP: case OP_PUSH: p += SIZE_RELADDR; break; case OP_REPEAT_INC: case OP_REPEAT_INC_NG: case OP_REPEAT_INC_SG: case OP_REPEAT_INC_NG_SG: p += SIZE_MEMNUM; break; default: goto unexpected_bytecode_error; break; } } } MOP_OUT; continue; break; #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT case OP_NULL_CHECK_END_MEMST: MOP_IN(OP_NULL_CHECK_END_MEMST); { int isnull; GET_MEMNUM_INC(mem, p); /* mem: null check id */ STACK_NULL_CHECK_MEMST(isnull, mem, s, reg); if (isnull) { #ifdef ONIG_DEBUG_MATCH fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%d, ptr: %p)\n", (int )mem, (int )s, it->ptr); #endif if (isnull == -1) goto fail; goto null_check_found; } } MOP_OUT; continue; break; #endif #ifdef USE_SUBEXP_CALL case OP_NULL_CHECK_END_MEMST_PUSH: MOP_IN(OP_NULL_CHECK_END_MEMST_PUSH); { int isnull; GET_MEMNUM_INC(mem, p); /* mem: null check id */ #ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg); #else STACK_NULL_CHECK_REC(isnull, mem, s); #endif if (isnull) { #ifdef ONIG_DEBUG_MATCH fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip id:%d, s:%d ptr: %p)\n", (int )mem, (int )s, it->ptr); #endif if (isnull == -1) goto fail; goto null_check_found; } else { STACK_PUSH_NULL_CHECK_END(mem); } } MOP_OUT; continue; break; #endif case OP_JUMP: MOP_IN(OP_JUMP); GET_RELADDR_INC(addr, p); p += addr; MOP_OUT; CHECK_INTERRUPT_IN_MATCH_AT; continue; break; case OP_PUSH: MOP_IN(OP_PUSH); GET_RELADDR_INC(addr, p); STACK_PUSH_ALT(p + addr, s, sprev, pkeep); MOP_OUT; continue; break; #ifdef USE_COMBINATION_EXPLOSION_CHECK case OP_STATE_CHECK_PUSH: MOP_IN(OP_STATE_CHECK_PUSH); GET_STATE_CHECK_NUM_INC(mem, p); STATE_CHECK_VAL(scv, mem); if (scv) goto fail; GET_RELADDR_INC(addr, p); STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep); MOP_OUT; continue; break; case OP_STATE_CHECK_PUSH_OR_JUMP: MOP_IN(OP_STATE_CHECK_PUSH_OR_JUMP); GET_STATE_CHECK_NUM_INC(mem, p); GET_RELADDR_INC(addr, p); STATE_CHECK_VAL(scv, mem); if (scv) { p += addr; } else { STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep); } MOP_OUT; continue; break; case OP_STATE_CHECK: MOP_IN(OP_STATE_CHECK); GET_STATE_CHECK_NUM_INC(mem, p); STATE_CHECK_VAL(scv, mem); if (scv) goto fail; STACK_PUSH_STATE_CHECK(s, mem); MOP_OUT; continue; break; #endif /* USE_COMBINATION_EXPLOSION_CHECK */ case OP_POP: MOP_IN(OP_POP); STACK_POP_ONE; MOP_OUT; continue; break; case OP_PUSH_OR_JUMP_EXACT1: MOP_IN(OP_PUSH_OR_JUMP_EXACT1); GET_RELADDR_INC(addr, p); if (*p == ONIG_CHARAT(s) && DATA_ENSURE_CHECK1) { p++; STACK_PUSH_ALT(p + addr, s, sprev, pkeep); MOP_OUT; continue; } p += (addr + 1); MOP_OUT; continue; break; case OP_PUSH_IF_PEEK_NEXT: MOP_IN(OP_PUSH_IF_PEEK_NEXT); GET_RELADDR_INC(addr, p); if (*p == ONIG_CHARAT(s)) { p++; STACK_PUSH_ALT(p + addr, s, sprev, pkeep); MOP_OUT; continue; } p++; MOP_OUT; continue; break; case OP_REPEAT: MOP_IN(OP_REPEAT); { GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ GET_RELADDR_INC(addr, p); STACK_ENSURE(1); repeat_stk[mem] = GET_STACK_INDEX(stk); STACK_PUSH_REPEAT(mem, p); if (reg->repeat_range[mem].lower == 0) { STACK_PUSH_ALT(p + addr, s, sprev, pkeep); } } MOP_OUT; continue; break; case OP_REPEAT_NG: MOP_IN(OP_REPEAT_NG); { GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ GET_RELADDR_INC(addr, p); STACK_ENSURE(1); repeat_stk[mem] = GET_STACK_INDEX(stk); STACK_PUSH_REPEAT(mem, p); if (reg->repeat_range[mem].lower == 0) { STACK_PUSH_ALT(p, s, sprev, pkeep); p += addr; } } MOP_OUT; continue; break; case OP_REPEAT_INC: MOP_IN(OP_REPEAT_INC); GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ si = repeat_stk[mem]; stkp = STACK_AT(si); repeat_inc: stkp->u.repeat.count++; if (stkp->u.repeat.count >= reg->repeat_range[mem].upper) { /* end of repeat. Nothing to do. */ } else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { STACK_PUSH_ALT(p, s, sprev, pkeep); p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */ } else { p = stkp->u.repeat.pcode; } STACK_PUSH_REPEAT_INC(si); MOP_OUT; CHECK_INTERRUPT_IN_MATCH_AT; continue; break; case OP_REPEAT_INC_SG: MOP_IN(OP_REPEAT_INC_SG); GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ STACK_GET_REPEAT(mem, stkp); si = GET_STACK_INDEX(stkp); goto repeat_inc; break; case OP_REPEAT_INC_NG: MOP_IN(OP_REPEAT_INC_NG); GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ si = repeat_stk[mem]; stkp = STACK_AT(si); repeat_inc_ng: stkp->u.repeat.count++; if (stkp->u.repeat.count < reg->repeat_range[mem].upper) { if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) { UChar* pcode = stkp->u.repeat.pcode; STACK_PUSH_REPEAT_INC(si); STACK_PUSH_ALT(pcode, s, sprev, pkeep); } else { p = stkp->u.repeat.pcode; STACK_PUSH_REPEAT_INC(si); } } else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) { STACK_PUSH_REPEAT_INC(si); } MOP_OUT; CHECK_INTERRUPT_IN_MATCH_AT; continue; break; case OP_REPEAT_INC_NG_SG: MOP_IN(OP_REPEAT_INC_NG_SG); GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */ STACK_GET_REPEAT(mem, stkp); si = GET_STACK_INDEX(stkp); goto repeat_inc_ng; break; case OP_PUSH_POS: MOP_IN(OP_PUSH_POS); STACK_PUSH_POS(s, sprev, pkeep); MOP_OUT; continue; break; case OP_POP_POS: MOP_IN(OP_POP_POS); { STACK_POS_END(stkp); s = stkp->u.state.pstr; sprev = stkp->u.state.pstr_prev; } MOP_OUT; continue; break; case OP_PUSH_POS_NOT: MOP_IN(OP_PUSH_POS_NOT); GET_RELADDR_INC(addr, p); STACK_PUSH_POS_NOT(p + addr, s, sprev, pkeep); MOP_OUT; continue; break; case OP_FAIL_POS: MOP_IN(OP_FAIL_POS); STACK_POP_TIL_POS_NOT; goto fail; break; case OP_PUSH_STOP_BT: MOP_IN(OP_PUSH_STOP_BT); STACK_PUSH_STOP_BT; MOP_OUT; continue; break; case OP_POP_STOP_BT: MOP_IN(OP_POP_STOP_BT); STACK_STOP_BT_END; MOP_OUT; continue; break; case OP_LOOK_BEHIND: MOP_IN(OP_LOOK_BEHIND); GET_LENGTH_INC(tlen, p); s = ONIGENC_STEP_BACK_SE(it, encode, str, s, (int )tlen); if (ONIG_IS_BADPOS(s)) goto fail; sprev = onigenc_get_prev_char_head_se(it, encode, str, s); MOP_OUT; continue; break; case OP_PUSH_LOOK_BEHIND_NOT: MOP_IN(OP_PUSH_LOOK_BEHIND_NOT); GET_RELADDR_INC(addr, p); GET_LENGTH_INC(tlen, p); q = ONIGENC_STEP_BACK_SE(it, encode, str, s, (int )tlen); if (ONIG_IS_BADPOS(q)) { /* too short case -> success. ex. /(?p + addr; MOP_OUT; continue; break; case OP_RETURN: MOP_IN(OP_RETURN); STACK_RETURN(p); STACK_PUSH_RETURN; MOP_OUT; continue; break; #endif case OP_CONDITION: MOP_IN(OP_CONDITION); GET_MEMNUM_INC(mem, p); GET_RELADDR_INC(addr, p); if ((mem > num_mem) || (mem_end_stk[mem] == INVALID_STACK_INDEX) || (mem_start_stk[mem] == INVALID_STACK_INDEX)) { p += addr; } MOP_OUT; continue; break; case OP_FINISH: goto finish; break; fail: MOP_OUT; /* fall */ case OP_FAIL: MOP_IN(OP_FAIL); STACK_POP; p = stk->u.state.pcode; s = stk->u.state.pstr; sprev = stk->u.state.pstr_prev; pkeep = stk->u.state.pkeep; #ifdef USE_COMBINATION_EXPLOSION_CHECK if (stk->u.state.state_check != 0) { stk->type = STK_STATE_CHECK_MARK; stk++; } #endif MOP_OUT; continue; break; default: goto bytecode_error; } /* end of switch */ sprev = sbegin; } /* end of while(1) */ finish: STACK_SAVE; return best_len; #ifdef ONIG_DEBUG stack_error: STACK_SAVE; return ONIGERR_STACK_BUG; #endif bytecode_error: STACK_SAVE; return ONIGERR_UNDEFINED_BYTECODE; unexpected_bytecode_error: STACK_SAVE; return ONIGERR_UNEXPECTED_BYTECODE; } static int memcmp_se(OnigIterator* it, UChar* target, UChar* target_end, OnigPosition p) { int r = 0; while (target < target_end) { if (*target != ONIG_CHARAT(p++)) { r = 1; break; } target++; } return r; } static OnigPosition slow_search_se(OnigIterator* it, OnigEncoding enc, UChar* target, UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { UChar* t; OnigPosition p, s, end; end = text_end; end -= target_end - target - 1; if (end > text_range) end = text_range; s = text; if (enc->max_enc_len == enc->min_enc_len) { int n = enc->max_enc_len; while (s < end) { if (ONIG_CHARAT(s) == *target) { p = s + 1; t = target + 1; if (target_end == t || memcmp_se(it, t, target_end, p) == 0) return s; } s += n; } return ONIG_BADPOS; } while (s < end) { if (ONIG_CHARAT(s) == *target) { p = s + 1; t = target + 1; if (target_end == t || memcmp_se(it, t, target_end, p) == 0) return s; } s += enclen_se(it, enc, s); } return ONIG_BADPOS; } static int str_lower_case_match_se(OnigIterator* it, OnigEncoding enc, int case_fold_flag, const UChar* t, const UChar* tend, OnigPosition p, OnigPosition end) { int lowlen; UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN]; while (t < tend) { lowlen = ONIGENC_MBC_CASE_FOLD_SE(it, enc, case_fold_flag, &p, end, lowbuf); q = lowbuf; while (lowlen > 0) { if (*t++ != *q++) return 0; lowlen--; } } return 1; } static OnigPosition slow_search_ic_se(OnigIterator* it, OnigEncoding enc, int case_fold_flag, UChar* target, UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { OnigPosition s, end; end = text_end; end -= target_end - target - 1; if (end > text_range) end = text_range; s = text; while (s < end) { if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, s, text_end)) return s; s += enclen_se(it, enc, s); } return ONIG_BADPOS; } static OnigPosition slow_search_backward_se(OnigIterator* it, OnigEncoding enc, UChar* target, UChar* target_end, OnigPosition text, OnigPosition adjust_text, OnigPosition text_end, OnigPosition text_start) { UChar* t; OnigPosition p, s; s = text_end; s -= (target_end - target); if (s > text_start) s = text_start; else s = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, adjust_text, s); while (s >= text) { if (ONIG_CHARAT(s) == *target) { p = s + 1; t = target + 1; while (t < target_end) { if (*t != ONIG_CHARAT(p++)) break; t++; } if (t == target_end) return s; } s = onigenc_get_prev_char_head_se(it, enc, adjust_text, s); } return ONIG_BADPOS; } static OnigPosition slow_search_backward_ic_se(OnigIterator* it, OnigEncoding enc, int case_fold_flag, UChar* target, UChar* target_end, OnigPosition text, OnigPosition adjust_text, OnigPosition text_end, OnigPosition text_start) { OnigPosition s; s = text_end; s -= (target_end - target); if (s > text_start) s = text_start; else s = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, enc, adjust_text, s); while (s >= text) { if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, s, text_end)) return s; s = onigenc_get_prev_char_head_se(it, enc, adjust_text, s); } return ONIG_BADPOS; } #ifndef USE_SUNDAY_QUICK_SEARCH /* Boyer-Moore-Horspool search applied to a multibyte string */ static OnigPosition bm_search_notrev_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { const UChar *t; OnigPosition s, se, p, end; const UChar *tail; ptrdiff_t skip, tlen1; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_notrev_se: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif tail = target_end - 1; tlen1 = tail - target; end = text_range; if (end + tlen1 > text_end) end = text_end - tlen1; s = text; if (IS_NULL(reg->int_map)) { while (s < end) { p = se = s + tlen1; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return s; p--; t--; } skip = reg->map[ONIG_CHARAT(se)]; p = s; do { s += enclen_se(it, reg->enc, s); } while ((s - p) < skip && s < end); } } else { while (s < end) { p = se = s + tlen1; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return s; p--; t--; } skip = reg->int_map[*se]; p = s; do { s += enclen_se(it, reg->enc, s); } while ((s - p) < skip && s < end); } } return ONIG_BADPOS; } /* Boyer-Moore-Horspool search */ static OnigPosition bm_search_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { const UChar *t; OnigPosition s, p, end; const UChar *tail; end = text_range + (target_end - target) - 1; if (end > text_end) end = text_end; tail = target_end - 1; s = text + (target_end - target) - 1; if (IS_NULL(reg->int_map)) { while (s < end) { p = s; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return p; p--; t--; } s += reg->map[ONIG_CHARAT(s)]; } } else { /* see int_map[] */ while (s < end) { p = s; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return p; p--; t--; } s += reg->int_map[*s]; } } return ONIG_BADPOS; } /* Boyer-Moore-Horspool search applied to a multibyte string (ignore case) */ static OnigPosition bm_search_notrev_ic(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { OnigPosition s, se, t, end; const UChar *tail; ptrdiff_t skip, tlen1; OnigEncoding enc = reg->enc; int case_fold_flag = reg->case_fold_flag; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_notrev_ic: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif tail = target_end - 1; tlen1 = tail - target; end = text_range; if (end + tlen1 > text_end) end = text_end - tlen1; s = text; if (IS_NULL(reg->int_map)) { while (s < end) { se = s + tlen1; if (str_lower_case_match(enc, case_fold_flag, target, target_end, s, se + 1)) return s; skip = reg->map[ONIG_CHARAT(se)]; t = s; do { s += enclen_se(it, reg->enc, s); } while ((s - t) < skip && s < end); } } else { while (s < end) { se = s + tlen1; if (str_lower_case_match(enc, case_fold_flag, target, target_end, s, se + 1)) return s; skip = reg->int_map[ONIG_CHARAT(se)]; t = s; do { s += enclen_se(it, reg->enc, s); } while ((s - t) < skip && s < end); } } return ONIG_BADPOS; } /* Boyer-Moore-Horspool search (ignore case) */ static OnigPosition bm_search_ic_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { OnigPosition s, p, end; const UChar *tail; OnigEncoding enc = reg->enc; int case_fold_flag = reg->case_fold_flag; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_ic_se: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif end = text_range + (target_end - target) - 1; if (end > text_end) end = text_end; tail = target_end - 1; s = text + (target_end - target) - 1; if (IS_NULL(reg->int_map)) { while (s < end) { p = s - (target_end - target) + 1; if (str_lower_case_match(enc, case_fold_flag, target, target_end, p, s + 1)) return p; s += reg->map[ONIG_CHARAT(s)]; } } else { /* see int_map[] */ while (s < end) { p = s - (target_end - target) + 1; if (str_lower_case_match(enc, case_fold_flag, target, target_end, p, s + 1)) return p; s += reg->int_map[ONIG_CHARAT(s)]; } } return ONIG_BADPOS; } #else /* USE_SUNDAY_QUICK_SEARCH */ /* Sunday's quick search applied to a multibyte string */ static OnigPosition bm_search_notrev_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { const UChar *t; OnigPosition s, se, p, end; const UChar *tail; ptrdiff_t skip, tlen1; OnigEncoding enc = reg->enc; int (*mbc_enc_len_se)(OnigIterator* it, OnigPosition p) = enc->mbc_enc_len_se; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_notrev_se: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif tail = target_end - 1; tlen1 = tail - target; end = text_range; if (end + tlen1 > text_end) end = text_end - tlen1; s = text; if (IS_NULL(reg->int_map)) { while (s < end) { p = se = s + tlen1; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return s; p--; t--; } if (s + 1 >= end) break; skip = reg->map[ONIG_CHARAT(se + 1)]; p = s; do { s += mbc_enc_len_se(it, s); } while ((s - p) < skip && s < end); } } else { while (s < end) { p = se = s + tlen1; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return s; p--; t--; } if (s + 1 >= end) break; skip = reg->int_map[ONIG_CHARAT(se + 1)]; p = s; do { s += mbc_enc_len_se(it, s); } while ((s - p) < skip && s < end); } } return ONIG_BADPOS; } /* Sunday's quick search */ static OnigPosition bm_search_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { const UChar *t; OnigPosition s, p, end; const UChar *tail; ptrdiff_t tlen1; tail = target_end - 1; tlen1 = tail - target; end = text_range + tlen1; if (end > text_end) end = text_end; s = text + tlen1; if (IS_NULL(reg->int_map)) { while (s < end) { p = s; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return p; p--; t--; } if (s + 1 >= end) break; s += reg->map[ONIG_CHARAT(s + 1)]; } } else { /* see int_map[] */ while (s < end) { p = s; t = tail; while (ONIG_CHARAT(p) == *t) { if (t == target) return p; p--; t--; } if (s + 1 >= end) break; s += reg->int_map[ONIG_CHARAT(s + 1)]; } } return ONIG_BADPOS; } /* Sunday's quick search applied to a multibyte string (ignore case) */ static OnigPosition bm_search_notrev_ic_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, const OnigPosition text_end, OnigPosition text_range) { OnigPosition t; OnigPosition s, se, end; const UChar *tail; ptrdiff_t skip, tlen1; OnigEncoding enc = reg->enc; int (*mbc_enc_len_se)(OnigIterator* it, OnigPosition p) = enc->mbc_enc_len_se; int case_fold_flag = reg->case_fold_flag; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_notrev_ic: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif tail = target_end - 1; tlen1 = tail - target; end = text_range; if (end + tlen1 > text_end) end = text_end - tlen1; s = text; if (IS_NULL(reg->int_map)) { while (s < end) { se = s + tlen1; if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, s, se + 1)) return s; if (s + 1 >= end) break; skip = reg->map[ONIG_CHARAT(se + 1)]; t = s; do { s += mbc_enc_len_se(it, s); } while ((s - t) < skip && s < end); } } else { while (s < end) { se = s + tlen1; if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, s, se + 1)) return s; if (s + 1 >= end) break; skip = reg->int_map[ONIG_CHARAT(se + 1)]; t = s; do { s += mbc_enc_len_se(it, s); } while ((s - t) < skip && s < end); } } return ONIG_BADPOS; } /* Sunday's quick search (ignore case) */ static OnigPosition bm_search_ic_se(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition text_end, OnigPosition text_range) { OnigPosition s, p, end; const UChar *tail; ptrdiff_t tlen1; OnigEncoding enc = reg->enc; int case_fold_flag = reg->case_fold_flag; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "bm_search_ic_se: text: %d, text_end: %d, text_range: %d\n", (int )text, (int )text_end, (int )text_range); #endif tail = target_end - 1; tlen1 = tail - target; end = text_range + tlen1; if (end > text_end) end = text_end; s = text + tlen1; if (IS_NULL(reg->int_map)) { while (s < end) { p = s - tlen1; if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, p, s + 1)) return p; if (s + 1 >= end) break; s += reg->map[ONIG_CHARAT(s + 1)]; } } else { /* see int_map[] */ while (s < end) { p = s - tlen1; if (str_lower_case_match_se(it, enc, case_fold_flag, target, target_end, p, s + 1)) return p; if (s + 1 >= end) break; s += reg->int_map[ONIG_CHARAT(s + 1)]; } } return ONIG_BADPOS; } #endif /* USE_SUNDAY_QUICK_SEARCH */ static int set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED, int** skip) { int i, len; if (IS_NULL(*skip)) { *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE); if (IS_NULL(*skip)) return ONIGERR_MEMORY; } len = (int )(end - s); for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*skip)[i] = len; for (i = len - 1; i > 0; i--) (*skip)[s[i]] = i; return 0; } static OnigPosition bm_search_backward(OnigIterator* it, regex_t* reg, const UChar* target, const UChar* target_end, OnigPosition text, OnigPosition adjust_text, OnigPosition text_end, OnigPosition text_start) { const UChar *t; OnigPosition s, p; s = text_end - (target_end - target); if (text_start < s) s = text_start; else s = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, reg->enc, adjust_text, s); while (s >= text) { p = s; t = target; while (t < target_end && ONIG_CHARAT(p) == *t) { p++; t++; } if (t == target_end) return s; s -= reg->int_map_backward[ONIG_CHARAT(s)]; s = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, reg->enc, adjust_text, s); } return ONIG_BADPOS; } static OnigPosition map_search_se(OnigIterator* it, OnigEncoding enc, UChar map[], OnigPosition text, OnigPosition text_range) { OnigPosition s = text; while (s < text_range) { if (map[ONIG_CHARAT(s)]) return s; s += enclen_se(it, enc, s); } return ONIG_BADPOS; } static OnigPosition map_search_backward(OnigIterator* it, OnigEncoding enc, UChar map[], OnigPosition text, OnigPosition adjust_text, OnigPosition text_start) { OnigPosition s = text_start; while (s >= text) { if (map[ONIG_CHARAT(s)]) return s; s = onigenc_get_prev_char_head_se(it, enc, adjust_text, s); } return ONIG_BADPOS; } extern OnigPosition onig_match(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition at, OnigRegion* region, OnigOptionType option) { return onig_match_gpos(it, reg, str, end, at, at, region, option); } extern OnigPosition onig_match_gpos(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition global_pos, OnigPosition at, OnigRegion* region, OnigOptionType option) { OnigPosition r; OnigPosition prev; OnigMatchArg msa; #if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM) start: THREAD_ATOMIC_START; if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) { ONIG_STATE_INC(reg); if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_chain_reduce(reg); ONIG_STATE_INC(reg); } } else { int n; THREAD_ATOMIC_END; n = 0; while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) { if (++n > THREAD_PASS_LIMIT_COUNT) return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT; THREAD_PASS; } goto start; } THREAD_ATOMIC_END; #endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */ MATCH_ARG_INIT(msa, option, region, at, global_pos); #ifdef USE_COMBINATION_EXPLOSION_CHECK { int offset = at - str; STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check); } #endif if (region #ifdef USE_POSIX_API_REGION_OPTION && !IS_POSIX_REGION(option) #endif ) { r = onig_region_resize_clear(region, reg->num_mem + 1); } else r = 0; if (r == 0) { prev = onigenc_get_prev_char_head_se(it, reg->enc, str, at); r = match_at(it, reg, str, end, #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE end, #endif at, prev, &msa); } MATCH_ARG_FREE(msa); ONIG_STATE_DEC_THREAD(reg); return r; } static int forward_search_range(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition s, OnigPosition range, OnigPosition* low, OnigPosition* high, OnigPosition* low_prev) { OnigPosition p, pprev = ONIG_BADPOS; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "forward_search_range: ptr: %p, str: %d, end: %d, s: %d, range: %d\n", it->ptr, (int )str, (int )end, (int )s, (int )range); #endif p = s; if (reg->dmin > 0) { if (ONIGENC_IS_SINGLEBYTE(reg->enc)) { p += reg->dmin; } else { OnigPosition q = p + reg->dmin; while (p < q) p += enclen_se(it, reg->enc, p); } } retry: switch (reg->optimize) { case ONIG_OPTIMIZE_EXACT: p = slow_search_se(it, reg->enc, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_IC: p = slow_search_ic_se(it, reg->enc, reg->case_fold_flag, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_BM: p = bm_search_se(it, reg, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_BM_NOT_REV: p = bm_search_notrev_se(it, reg, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_BM_IC: p = bm_search_ic_se(it, reg, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC: p = bm_search_notrev_ic_se(it, reg, reg->exact, reg->exact_end, p, end, range); break; case ONIG_OPTIMIZE_MAP: p = map_search_se(it, reg->enc, reg->map, p, range); break; } if (ONIG_IS_NOT_BADPOS(p) && p < range) { if (p - reg->dmin < s) { retry_gate: pprev = p; p += enclen_se(it, reg->enc, p); goto retry; } if (reg->sub_anchor) { OnigPosition prev; switch (reg->sub_anchor) { case ANCHOR_BEGIN_LINE: if (!ON_STR_BEGIN(p)) { prev = onigenc_get_prev_char_head_se(it, reg->enc, (ONIG_IS_NOT_BADPOS(pprev) ? pprev : str), p); if (!ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, prev, str, end, reg->options, 0)) goto retry_gate; } break; case ANCHOR_END_LINE: if (ON_STR_END(p)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE prev = onigenc_get_prev_char_head_se(it, reg->enc, (ONIG_IS_NOT_BADPOS(pprev) ? pprev : str), p); if (prev && ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, prev, str, end, reg->options, 1)) goto retry_gate; #endif } else if (! ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, p, str, end, reg->options, 1)) goto retry_gate; break; } } if (reg->dmax == 0) { *low = p; if (low_prev) { if (*low > s) *low_prev = onigenc_get_prev_char_head_se(it, reg->enc, s, p); else *low_prev = onigenc_get_prev_char_head_se(it, reg->enc, (ONIG_IS_NOT_BADPOS(pprev) ? pprev : str), p); } } else { if (reg->dmax != ONIG_INFINITE_DISTANCE) { *low = p - reg->dmax; if (*low > s) { *low = onigenc_get_right_adjust_char_head_with_prev_se(it, reg->enc, s, *low, low_prev); if (low_prev && ONIG_IS_BADPOS(*low_prev)) *low_prev = onigenc_get_prev_char_head_se(it, reg->enc, (ONIG_IS_NOT_BADPOS(pprev) ? pprev : s), *low); } else { if (low_prev) *low_prev = onigenc_get_prev_char_head_se(it, reg->enc, (ONIG_IS_NOT_BADPOS(pprev) ? pprev : str), *low); } } } /* no needs to adjust *high, *high is used as range check only */ *high = p - reg->dmin; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "forward_search_range success: low: %d, high: %d, dmin: %d, dmax: %d\n", (int )(*low - str), (int )(*high - str), reg->dmin, reg->dmax); #endif return 1; /* success */ } return 0; /* fail */ } static int set_bm_backward_skip P_((UChar* s, UChar* end, OnigEncoding enc, int** skip)); #define BM_BACKWARD_SEARCH_LENGTH_THRESHOLD 100 static int backward_search_range_se(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition s, OnigPosition range, OnigPosition adjrange, OnigPosition* low, OnigPosition* high) { int r; OnigPosition p; range += reg->dmin; p = s; retry: switch (reg->optimize) { case ONIG_OPTIMIZE_EXACT: exact_method: p = slow_search_backward_se(it, reg->enc, reg->exact, reg->exact_end, range, adjrange, end, p); break; case ONIG_OPTIMIZE_EXACT_IC: case ONIG_OPTIMIZE_EXACT_BM_IC: case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC: p = slow_search_backward_ic_se(it, reg->enc, reg->case_fold_flag, reg->exact, reg->exact_end, range, adjrange, end, p); break; case ONIG_OPTIMIZE_EXACT_BM: case ONIG_OPTIMIZE_EXACT_BM_NOT_REV: if (IS_NULL(reg->int_map_backward)) { if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD) goto exact_method; r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc, &(reg->int_map_backward)); if (r) return r; } p = bm_search_backward(it, reg, reg->exact, reg->exact_end, range, adjrange, end, p); break; case ONIG_OPTIMIZE_MAP: p = map_search_backward(it, reg->enc, reg->map, range, adjrange, p); break; } if (ONIG_IS_NOT_BADPOS(p)) { if (reg->sub_anchor) { OnigPosition prev; switch (reg->sub_anchor) { case ANCHOR_BEGIN_LINE: if (!ON_STR_BEGIN(p)) { prev = onigenc_get_prev_char_head_se(it, reg->enc, str, p); if (!ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, prev, str, end, reg->options, 0)) { p = prev; goto retry; } } break; case ANCHOR_END_LINE: if (ON_STR_END(p)) { #ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE prev = onigenc_get_prev_char_head_se(it, reg->enc, adjrange, p); if (ONIG_IS_BADPOS(prev)) goto fail; if (ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, prev, str, end, reg->options, 1)) { p = prev; goto retry; } #endif } else if (! ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, p, str, end, reg->options, 1)) { p = onigenc_get_prev_char_head_se(it, reg->enc, adjrange, p); if (ONIG_IS_BADPOS(p)) goto fail; goto retry; } break; } } /* no needs to adjust *high, *high is used as range check only */ if (reg->dmax != ONIG_INFINITE_DISTANCE) { *low = p - reg->dmax; *high = p - reg->dmin; *high = onigenc_get_right_adjust_char_head_se(it, reg->enc, adjrange, *high); } #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "backward_search_range_se: low: %d, high: %d\n", (int )(*low), (int )(*high)); #endif return 1; /* success */ } fail: #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "backward_search_range_se: fail.\n"); #endif return 0; /* fail */ } extern OnigPosition onig_search(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition start, OnigPosition range, OnigRegion* region, OnigOptionType option) { return onig_search_gpos(it, reg, str, end, start, start, range, region, option); } extern OnigPosition onig_search_gpos(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end, OnigPosition global_pos, OnigPosition start, OnigPosition range, OnigRegion* region, OnigOptionType option) { OnigPosition r; OnigPosition s, prev; OnigMatchArg msa; #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE OnigPosition orig_start = start; OnigPosition orig_range = range; #endif #if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM) start: THREAD_ATOMIC_START; if (ONIG_STATE(reg) >= ONIG_STATE_NORMAL) { ONIG_STATE_INC(reg); if (IS_NOT_NULL(reg->chain) && ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_chain_reduce(reg); ONIG_STATE_INC(reg); } } else { int n; THREAD_ATOMIC_END; n = 0; while (ONIG_STATE(reg) < ONIG_STATE_NORMAL) { if (++n > THREAD_PASS_LIMIT_COUNT) return ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT; THREAD_PASS; } goto start; } THREAD_ATOMIC_END; #endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */ #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "onig_search (entry point): ptr: %p, str: %d , end: %d, start: %d, range: %d\n", it->ptr, (int )str, (int )end, (int )start, (int )range); #endif if (region #ifdef USE_POSIX_API_REGION_OPTION && !IS_POSIX_REGION(option) #endif ) { r = onig_region_resize_clear(region, reg->num_mem + 1); if (r) goto finish_no_msa; } if (start > end || start < str) goto mismatch_no_msa; #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE #define MATCH_AND_RETURN_CHECK(upper_range) \ r = match_at(it, reg, str, end, (upper_range), s, prev, &msa); \ if (r != ONIG_MISMATCH) {\ if (r >= 0) {\ if (! IS_FIND_LONGEST(reg->options)) {\ goto match;\ }\ }\ else goto finish; /* error */ \ } #else #define MATCH_AND_RETURN_CHECK(upper_range) \ r = match_at(it, reg, str, end, (upper_range), s, prev, &msa); \ if (r != ONIG_MISMATCH) {\ if (r >= 0) {\ goto match;\ }\ else goto finish; /* error */ \ } #endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */ #else #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE #define MATCH_AND_RETURN_CHECK(none) \ r = match_at(it, reg, str, end, s, prev, &msa);\ if (r != ONIG_MISMATCH) {\ if (r >= 0) {\ if (! IS_FIND_LONGEST(reg->options)) {\ goto match;\ }\ }\ else goto finish; /* error */ \ } #else #define MATCH_AND_RETURN_CHECK(none) \ r = match_at(it, reg, str, end, s, prev, &msa);\ if (r != ONIG_MISMATCH) {\ if (r >= 0) {\ goto match;\ }\ else goto finish; /* error */ \ } #endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */ #endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */ /* anchor optimize: resume search range */ if (reg->anchor != 0 && str < end) { OnigPosition min_semi_end, max_semi_end; if (reg->anchor & ANCHOR_BEGIN_POSITION) { /* search start-position only */ begin_position: if (range > start) range = start + 1; else range = start; } else if (reg->anchor & ANCHOR_BEGIN_BUF) { /* search str-position only */ if (range > start) { if (start != str) goto mismatch_no_msa; range = str + 1; } else { if (range <= str) { start = str; range = str; } else goto mismatch_no_msa; } } else if (reg->anchor & ANCHOR_END_BUF) { min_semi_end = max_semi_end = end; end_buf: if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin) goto mismatch_no_msa; if (range > start) { if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) { start = min_semi_end - reg->anchor_dmax; if (start < end) start = onigenc_get_right_adjust_char_head_se(it, reg->enc, str, start); } if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) { range = max_semi_end - reg->anchor_dmin + 1; } if (start > range) goto mismatch_no_msa; /* If start == range, match with empty at end. Backward search is used. */ } else { if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) { range = min_semi_end - reg->anchor_dmax; } if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) { start = max_semi_end - reg->anchor_dmin; start = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, reg->enc, str, start); } if (range > start) goto mismatch_no_msa; } } else if (reg->anchor & ANCHOR_SEMI_END_BUF) { OnigPosition pre_end = ONIGENC_STEP_BACK_SE(it, reg->enc, str, end, 1); max_semi_end = end; if (ONIGENC_IS_MBC_NEWLINE_SE(it, reg->enc, pre_end, end)) { min_semi_end = pre_end; #ifdef USE_CRNL_AS_LINE_TERMINATOR pre_end = ONIGENC_STEP_BACK_SE(it, reg->enc, str, pre_end, 1); if (ONIG_IS_NOT_BADPOS(pre_end) && IS_NEWLINE_CRLF(reg->options) && ONIGENC_IS_MBC_CRNL_SE(it, reg->enc, pre_end, end)) { min_semi_end = pre_end; } #endif if (min_semi_end > str && start <= min_semi_end) { goto end_buf; } } else { min_semi_end = end; goto end_buf; } } else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) { if (! (reg->anchor & ANCHOR_LOOK_BEHIND)) { goto begin_position; } } } else if (str == end) { /* empty string */ static OnigPosition address_for_empty_string = 0; #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "onig_search: empty string.\n"); #endif if (reg->threshold_len == 0) { start = end = str = address_for_empty_string; s = start; prev = ONIG_BADPOS; MATCH_ARG_INIT(msa, option, region, start, start); #ifdef USE_COMBINATION_EXPLOSION_CHECK msa.state_check_buff = (void* )0; msa.state_check_buff_size = 0; /* NO NEED, for valgrind */ #endif MATCH_AND_RETURN_CHECK(end); goto mismatch; } goto mismatch_no_msa; } #ifdef ONIG_DEBUG_SEARCH fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n", (int )end, (int )start, (int )range); #endif MATCH_ARG_INIT(msa, option, region, start, global_pos); #ifdef USE_COMBINATION_EXPLOSION_CHECK { int offset = (MIN(start, range) - str); STATE_CHECK_BUFF_INIT(msa, end - str, offset, reg->num_comb_exp_check); } #endif s = start; if (range > start) { /* forward search */ if (s > str) prev = onigenc_get_prev_char_head_se(it, reg->enc, str, s); else prev = ONIG_BADPOS; if (reg->optimize != ONIG_OPTIMIZE_NONE) { OnigPosition sch_range, low, high, low_prev; sch_range = range; if (reg->dmax != 0) { if (reg->dmax == ONIG_INFINITE_DISTANCE) sch_range = end; else { sch_range += reg->dmax; if (sch_range > end) sch_range = end; } } if ((end - start) < reg->threshold_len) goto mismatch; if (reg->dmax != ONIG_INFINITE_DISTANCE) { do { if (! forward_search_range(it, reg, str, end, s, sch_range, &low, &high, &low_prev)) goto mismatch; if (s < low) { s = low; prev = low_prev; } while (s <= high) { MATCH_AND_RETURN_CHECK(orig_range); prev = s; s += enclen_se(it, reg->enc, s); } } while (s < range); goto mismatch; } else { /* check only. */ if (! forward_search_range(it, reg, str, end, s, sch_range, &low, &high, (OnigPosition* )NULL)) goto mismatch; if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) { do { if ((reg->anchor & ANCHOR_BEGIN_POSITION) == 0) msa.gpos = s; /* move \G position */ MATCH_AND_RETURN_CHECK(orig_range); prev = s; s += enclen_se(it, reg->enc, s); if ((reg->anchor & ANCHOR_LOOK_BEHIND) == 0) { while (!ONIGENC_IS_MBC_NEWLINE_EX_SE(it, reg->enc, prev, str, end, reg->options, 0) && s < range) { prev = s; s += enclen_se(it, reg->enc, s); } } } while (s < range); goto mismatch; } } } do { MATCH_AND_RETURN_CHECK(orig_range); prev = s; s += enclen_se(it, reg->enc, s); } while (s < range); if (s == range) { /* because empty match with /$/. */ MATCH_AND_RETURN_CHECK(orig_range); } } else { /* backward search */ #ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE if (orig_start < end) orig_start += enclen_se(it, reg->enc, orig_start); /* is upper range */ #endif if (reg->optimize != ONIG_OPTIMIZE_NONE) { OnigPosition low, high, adjrange, sch_start; if (range < end) adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, reg->enc, str, range); else adjrange = end; if (reg->dmax != ONIG_INFINITE_DISTANCE && (end - range) >= reg->threshold_len) { do { sch_start = s + reg->dmax; if (sch_start > end) sch_start = end; if (backward_search_range_se(it, reg, str, end, sch_start, range, adjrange, &low, &high) <= 0) goto mismatch; if (s > high) s = high; while (s >= low) { prev = onigenc_get_prev_char_head_se(it, reg->enc, str, s); MATCH_AND_RETURN_CHECK(orig_start); s = prev; } } while (s >= range); goto mismatch; } else { /* check only. */ if ((end - range) < reg->threshold_len) goto mismatch; sch_start = s; if (reg->dmax != 0) { if (reg->dmax == ONIG_INFINITE_DISTANCE) sch_start = end; else { sch_start += reg->dmax; if (sch_start > end) sch_start = end; else sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD_SE(it, reg->enc, start, sch_start); } } if (backward_search_range_se(it, reg, str, end, sch_start, range, adjrange, &low, &high) <= 0) goto mismatch; } } do { prev = onigenc_get_prev_char_head_se(it, reg->enc, str, s); MATCH_AND_RETURN_CHECK(orig_start); s = prev; } while (s >= range); } mismatch: #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE if (IS_FIND_LONGEST(reg->options)) { if (msa.best_len >= 0) { s = msa.best_s; goto match; } } #endif r = ONIG_MISMATCH; finish: MATCH_ARG_FREE(msa); ONIG_STATE_DEC_THREAD(reg); /* If result is mismatch and no FIND_NOT_EMPTY option, then the region is not set in match_at(). */ if (IS_FIND_NOT_EMPTY(reg->options) && region #ifdef USE_POSIX_API_REGION_OPTION && !IS_POSIX_REGION(option) #endif ) { onig_region_clear(region); } #ifdef ONIG_DEBUG if (r != ONIG_MISMATCH) fprintf(stderr, "onig_search: error %d\n", r); #endif return r; mismatch_no_msa: r = ONIG_MISMATCH; finish_no_msa: ONIG_STATE_DEC_THREAD(reg); #ifdef ONIG_DEBUG if (r != ONIG_MISMATCH) fprintf(stderr, "onig_search: error %d\n", r); #endif return r; match: ONIG_STATE_DEC_THREAD(reg); MATCH_ARG_FREE(msa); return s - str; } extern OnigEncoding onig_get_encoding(regex_t* reg) { return reg->enc; } extern OnigOptionType onig_get_options(regex_t* reg) { return reg->options; } extern OnigCaseFoldType onig_get_case_fold_flag(regex_t* reg) { return reg->case_fold_flag; } extern OnigSyntaxType* onig_get_syntax(regex_t* reg) { return reg->syntax; } extern int onig_number_of_captures(regex_t* reg) { return reg->num_mem; } extern int onig_number_of_capture_histories(regex_t* reg) { #ifdef USE_CAPTURE_HISTORY int i, n; n = 0; for (i = 0; i <= ONIG_MAX_CAPTURE_HISTORY_GROUP; i++) { if (BIT_STATUS_AT(reg->capture_history, i) != 0) n++; } return n; #else return 0; #endif } extern void onig_copy_encoding(OnigEncoding to, OnigEncoding from) { *to = *from; } extern UChar onig_default_charat (OnigPosition pos, const void* ptr) { return ptr ? *((const UChar*)(ptr) + pos) : '\0'; } ================================================ FILE: src/Onigmo/regext.c ================================================ /********************************************************************** regext.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" static void conv_ext0be32(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = '\0'; *conv++ = '\0'; *conv++ = '\0'; *conv++ = *s++; } } static void conv_ext0le32(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = *s++; *conv++ = '\0'; *conv++ = '\0'; *conv++ = '\0'; } } static void conv_ext0be(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = '\0'; *conv++ = *s++; } } static void conv_ext0le(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = *s++; *conv++ = '\0'; } } static void conv_swap4bytes(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = s[3]; *conv++ = s[2]; *conv++ = s[1]; *conv++ = s[0]; s += 4; } } static void conv_swap2bytes(const UChar* s, const UChar* end, UChar* conv) { while (s < end) { *conv++ = s[1]; *conv++ = s[0]; s += 2; } } static int conv_encoding(OnigEncoding from, OnigEncoding to, const UChar* s, const UChar* end, UChar** conv, UChar** conv_end) { ptrdiff_t len = end - s; if (to == ONIG_ENCODING_UTF16_BE) { if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { *conv = (UChar* )xmalloc(len * 2); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + (len * 2); conv_ext0be(s, end, *conv); return 0; } else if (from == ONIG_ENCODING_UTF16_LE) { swap16: *conv = (UChar* )xmalloc(len); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + len; conv_swap2bytes(s, end, *conv); return 0; } } else if (to == ONIG_ENCODING_UTF16_LE) { if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { *conv = (UChar* )xmalloc(len * 2); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + (len * 2); conv_ext0le(s, end, *conv); return 0; } else if (from == ONIG_ENCODING_UTF16_BE) { goto swap16; } } if (to == ONIG_ENCODING_UTF32_BE) { if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { *conv = (UChar* )xmalloc(len * 4); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + (len * 4); conv_ext0be32(s, end, *conv); return 0; } else if (from == ONIG_ENCODING_UTF32_LE) { swap32: *conv = (UChar* )xmalloc(len); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + len; conv_swap4bytes(s, end, *conv); return 0; } } else if (to == ONIG_ENCODING_UTF32_LE) { if (from == ONIG_ENCODING_ASCII || from == ONIG_ENCODING_ISO_8859_1) { *conv = (UChar* )xmalloc(len * 4); CHECK_NULL_RETURN_MEMERR(*conv); *conv_end = *conv + (len * 4); conv_ext0le32(s, end, *conv); return 0; } else if (from == ONIG_ENCODING_UTF32_BE) { goto swap32; } } return ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION; } extern int onig_new_deluxe(regex_t** reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo) { int r; UChar *cpat, *cpat_end; if (IS_NOT_NULL(einfo)) einfo->par = (UChar* )NULL; if (ci->pattern_enc != ci->target_enc) { r = conv_encoding(ci->pattern_enc, ci->target_enc, pattern, pattern_end, &cpat, &cpat_end); if (r) return r; } else { cpat = (UChar* )pattern; cpat_end = (UChar* )pattern_end; } *reg = (regex_t* )xmalloc(sizeof(regex_t)); if (IS_NULL(*reg)) { r = ONIGERR_MEMORY; goto err2; } r = onig_reg_init(*reg, ci->option, ci->case_fold_flag, ci->target_enc, ci->syntax); if (r) goto err; r = onig_compile(*reg, cpat, cpat_end, einfo); if (r) { err: onig_free(*reg); *reg = NULL; } err2: if (cpat != pattern) xfree(cpat); return r; } #ifdef USE_RECOMPILE_API extern int onig_recompile_deluxe(regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigCompileInfo* ci, OnigErrorInfo* einfo) { int r; regex_t *new_reg; r = onig_new_deluxe(&new_reg, pattern, pattern_end, ci, einfo); if (r) return r; if (ONIG_STATE(reg) == ONIG_STATE_NORMAL) { onig_transfer(reg, new_reg); } else { onig_chain_link_add(reg, new_reg); } return 0; } #endif ================================================ FILE: src/Onigmo/reggnu.c ================================================ /********************************************************************** reggnu.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" #ifndef ONIGGNU_H #include "oniggnu.h" #endif extern void re_free_registers(OnigRegion* r) { /* 0: don't free self */ onig_region_free(r, 0); } extern int re_adjust_startpos(regex_t* reg, const char* string, int size, int startpos, int range) { if (startpos > 0 && ONIGENC_MBC_MAXLEN(reg->enc) != 1 && startpos < size) { UChar *p; UChar *s = (UChar* )string + startpos; if (range > 0) { p = onigenc_get_right_adjust_char_head(reg->enc, (UChar* )string, s); } else { p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, (UChar* )string, s); } return (int )(p - (UChar* )string); } return startpos; } extern int re_match(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition size, OnigPosition pos, struct re_registers* regs) { return (int )onig_match(it, reg, str, (str + size), (str + pos), regs, ONIG_OPTION_NONE); } extern int re_search(OnigIterator* it, regex_t* bufp, OnigPosition str, OnigPosition size, OnigPosition startpos, OnigPosition range, struct re_registers* regs) { return (int )onig_search(it, bufp, str, (str + size), (str + startpos), (str + startpos + range), regs, ONIG_OPTION_NONE); } extern int re_compile_pattern(const char* pattern, int size, regex_t* reg, char* ebuf) { int r; OnigErrorInfo einfo; r = onig_compile(reg, (UChar* )pattern, (UChar* )(pattern + size), &einfo); if (r != ONIG_NORMAL) { if (IS_NOT_NULL(ebuf)) (void )onig_error_code_to_str((UChar* )ebuf, r, &einfo); } return r; } #ifdef USE_RECOMPILE_API extern int re_recompile_pattern(const char* pattern, int size, regex_t* reg, char* ebuf) { int r; OnigErrorInfo einfo; OnigEncoding enc; /* I think encoding and options should be arguments of this function. But this is adapted to present re.c. (2002/11/29) */ enc = OnigEncDefaultCharEncoding; r = onig_recompile(reg, (UChar* )pattern, (UChar* )(pattern + size), reg->options, enc, OnigDefaultSyntax, &einfo); if (r != ONIG_NORMAL) { if (IS_NOT_NULL(ebuf)) (void )onig_error_code_to_str((UChar* )ebuf, r, &einfo); } return r; } #endif extern void re_free_pattern(regex_t* reg) { onig_free(reg); } extern int re_alloc_pattern(regex_t** reg) { *reg = (regex_t* )xmalloc(sizeof(regex_t)); if (IS_NULL(*reg)) return ONIGERR_MEMORY; return onig_reg_init(*reg, ONIG_OPTION_DEFAULT, ONIGENC_CASE_FOLD_DEFAULT, OnigEncDefaultCharEncoding, OnigDefaultSyntax); } extern void re_set_casetable(const char* table) { onigenc_set_default_caseconv_table((UChar* )table); } extern void re_mbcinit(int mb_code) { OnigEncoding enc; switch (mb_code) { case RE_MBCTYPE_ASCII: enc = ONIG_ENCODING_ASCII; break; case RE_MBCTYPE_EUC: enc = ONIG_ENCODING_EUC_JP; break; case RE_MBCTYPE_SJIS: enc = ONIG_ENCODING_SJIS; break; case RE_MBCTYPE_UTF8: enc = ONIG_ENCODING_UTF8; break; default: return ; break; } onigenc_set_default_encoding(enc); } ================================================ FILE: src/Onigmo/regint.h ================================================ #ifndef REGINT_H #define REGINT_H /********************************************************************** regint.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011-2012 K.Takata * 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. */ /* for debug */ /* #define ONIG_DEBUG_PARSE_TREE */ /* #define ONIG_DEBUG_COMPILE */ /* #define ONIG_DEBUG_SEARCH */ /* #define ONIG_DEBUG_MATCH */ /* #define ONIG_DONT_OPTIMIZE */ /* for byte-code statistical data. */ /* #define ONIG_DEBUG_STATISTICS */ #if defined(ONIG_DEBUG_PARSE_TREE) || defined(ONIG_DEBUG_MATCH) || \ defined(ONIG_DEBUG_SEARCH) || defined(ONIG_DEBUG_COMPILE) || \ defined(ONIG_DEBUG_STATISTICS) #ifndef ONIG_DEBUG #define ONIG_DEBUG #endif #endif #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ defined(__mc68020__) #define PLATFORM_UNALIGNED_WORD_ACCESS #endif /* config */ /* spec. config */ #define USE_NAMED_GROUP #define USE_SUBEXP_CALL #define USE_PERL_SUBEXP_CALL #define USE_CAPITAL_P_NAMED_GROUP #define USE_BACKREF_WITH_LEVEL /* \k, \k */ #define USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT /* /(?:()|())*\2/ */ #define USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE /* /\n$/ =~ "\n" */ #define USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR /* #define USE_RECOMPILE_API */ /* !!! moved to regenc.h. */ /* #define USE_CRNL_AS_LINE_TERMINATOR */ #define USE_NO_INVALID_QUANTIFIER /* internal config */ #define USE_PARSE_TREE_NODE_RECYCLE #define USE_OP_PUSH_OR_JUMP_EXACT #define USE_QTFR_PEEK_NEXT #define USE_ST_LIBRARY #define USE_SHARED_CCLASS_TABLE #define USE_SUNDAY_QUICK_SEARCH #define USE_SHARED_UNICODE_TABLE #define INIT_MATCH_STACK_SIZE 160 #define DEFAULT_MATCH_STACK_LIMIT_SIZE 0 /* unlimited */ /* check config */ #if defined(USE_PERL_SUBEXP_CALL) || defined(USE_CAPITAL_P_NAMED_GROUP) #if !defined(USE_NAMED_GROUP) || !defined(USE_SUBEXP_CALL) #error USE_NAMED_GROUP and USE_SUBEXP_CALL must be defined. #endif #endif #if defined(__GNUC__) # define ARG_UNUSED __attribute__ ((unused)) #else # define ARG_UNUSED #endif /* */ /* escape other system UChar definition */ #include "config.h" #ifdef ONIG_ESCAPE_UCHAR_COLLISION #undef ONIG_ESCAPE_UCHAR_COLLISION #endif #define USE_WORD_BEGIN_END /* "\<", "\>" */ #define USE_CAPTURE_HISTORY #define USE_VARIABLE_META_CHARS #define USE_POSIX_API_REGION_OPTION #define USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE /* #define USE_COMBINATION_EXPLOSION_CHECK */ /* (X*)* */ /* #define USE_MULTI_THREAD_SYSTEM */ #define THREAD_SYSTEM_INIT /* depend on thread system */ #define THREAD_SYSTEM_END /* depend on thread system */ #define THREAD_ATOMIC_START /* depend on thread system */ #define THREAD_ATOMIC_END /* depend on thread system */ #define THREAD_PASS /* depend on thread system */ #define xmalloc malloc #define xrealloc realloc #define xcalloc calloc #define xfree free #define CHECK_INTERRUPT_IN_MATCH_AT #define st_init_table onig_st_init_table #define st_init_table_with_size onig_st_init_table_with_size #define st_init_numtable onig_st_init_numtable #define st_init_numtable_with_size onig_st_init_numtable_with_size #define st_init_strtable onig_st_init_strtable #define st_init_strtable_with_size onig_st_init_strtable_with_size #define st_delete onig_st_delete #define st_delete_safe onig_st_delete_safe #define st_insert onig_st_insert #define st_lookup onig_st_lookup #define st_foreach onig_st_foreach #define st_add_direct onig_st_add_direct #define st_free_table onig_st_free_table #define st_cleanup_safe onig_st_cleanup_safe #define st_copy onig_st_copy #define st_nothing_key_clone onig_st_nothing_key_clone #define st_nothing_key_free onig_st_nothing_key_free /* */ #define onig_st_is_member st_is_member #define STATE_CHECK_STRING_THRESHOLD_LEN 7 #define STATE_CHECK_BUFF_MAX_SIZE 0x4000 #define THREAD_PASS_LIMIT_COUNT 8 #define xmemset memset #define xmemcpy memcpy #define xmemmove memmove #if defined(_WIN32) && !defined(__GNUC__) #define xalloca _alloca #define xvsnprintf _vsnprintf #else #define xalloca alloca #define xvsnprintf vsnprintf #endif #if defined(USE_RECOMPILE_API) && defined(USE_MULTI_THREAD_SYSTEM) #define ONIG_STATE_INC(reg) (reg)->state++ #define ONIG_STATE_DEC(reg) (reg)->state-- #define ONIG_STATE_INC_THREAD(reg) do {\ THREAD_ATOMIC_START;\ (reg)->state++;\ THREAD_ATOMIC_END;\ } while(0) #define ONIG_STATE_DEC_THREAD(reg) do {\ THREAD_ATOMIC_START;\ (reg)->state--;\ THREAD_ATOMIC_END;\ } while(0) #else #define ONIG_STATE_INC(reg) /* Nothing */ #define ONIG_STATE_DEC(reg) /* Nothing */ #define ONIG_STATE_INC_THREAD(reg) /* Nothing */ #define ONIG_STATE_DEC_THREAD(reg) /* Nothing */ #endif /* USE_RECOMPILE_API && USE_MULTI_THREAD_SYSTEM */ #ifdef HAVE_STDLIB_H #include #endif #if defined(HAVE_ALLOCA_H) && (defined(_AIX) || !defined(__GNUC__)) #include #endif #ifdef HAVE_STRING_H # include #else # include #endif #include #ifdef HAVE_SYS_TYPES_H #ifndef __BORLANDC__ #include #endif #endif #ifdef HAVE_STDINT_H # include #endif #ifdef STDC_HEADERS # include #endif #ifdef __BORLANDC__ #include #endif #ifdef ONIG_DEBUG # include #endif #ifdef _WIN32 #if defined(_MSC_VER) && (_MSC_VER < 1300) #ifndef _INTPTR_T_DEFINED #define _INTPTR_T_DEFINED typedef int intptr_t; #endif #ifndef _UINTPTR_T_DEFINED #define _UINTPTR_T_DEFINED typedef unsigned int uintptr_t; #endif #endif #endif /* _WIN32 */ #include "regenc.h" #ifdef MIN #undef MIN #endif #ifdef MAX #undef MAX #endif #define MIN(a,b) (((a)>(b))?(b):(a)) #define MAX(a,b) (((a)<(b))?(b):(a)) #define IS_NULL(p) (((void*)(p)) == (void*)0) #define IS_NOT_NULL(p) (((void*)(p)) != (void*)0) #define CHECK_NULL_RETURN(p) if (IS_NULL(p)) return NULL #define CHECK_NULL_RETURN_MEMERR(p) if (IS_NULL(p)) return ONIGERR_MEMORY #define NULL_UCHARP ((UChar* )0) #define ONIG_LAST_CODE_POINT (~((OnigCodePoint )0)) #ifdef PLATFORM_UNALIGNED_WORD_ACCESS #define PLATFORM_GET_INC(val,p,type) do{\ val = *(type* )p;\ (p) += sizeof(type);\ } while(0) #else #define PLATFORM_GET_INC(val,p,type) do{\ xmemcpy(&val, (p), sizeof(type));\ (p) += sizeof(type);\ } while(0) /* sizeof(OnigCodePoint) */ #define WORD_ALIGNMENT_SIZE SIZEOF_LONG #define GET_ALIGNMENT_PAD_SIZE(addr,pad_size) do {\ (pad_size) = WORD_ALIGNMENT_SIZE \ - ((uintptr_t )(addr) % WORD_ALIGNMENT_SIZE);\ if ((pad_size) == WORD_ALIGNMENT_SIZE) (pad_size) = 0;\ } while (0) #define ALIGNMENT_RIGHT(addr) do {\ (addr) += (WORD_ALIGNMENT_SIZE - 1);\ (addr) -= ((uintptr_t )(addr) % WORD_ALIGNMENT_SIZE);\ } while (0) #endif /* PLATFORM_UNALIGNED_WORD_ACCESS */ /* stack pop level */ #define STACK_POP_LEVEL_FREE 0 #define STACK_POP_LEVEL_MEM_START 1 #define STACK_POP_LEVEL_ALL 2 /* optimize flags */ #define ONIG_OPTIMIZE_NONE 0 #define ONIG_OPTIMIZE_EXACT 1 /* Slow Search */ #define ONIG_OPTIMIZE_EXACT_BM 2 /* Boyer Moore Search */ #define ONIG_OPTIMIZE_EXACT_BM_NOT_REV 3 /* BM (applied to a multibyte string) */ #define ONIG_OPTIMIZE_EXACT_IC 4 /* Slow Search (ignore case) */ #define ONIG_OPTIMIZE_MAP 5 /* char map */ #define ONIG_OPTIMIZE_EXACT_BM_IC 6 /* BM (ignore case) */ #define ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC 7 /* BM (applied to a multibyte string) (ignore case) */ /* bit status */ typedef unsigned int BitStatusType; #define BIT_STATUS_BITS_NUM (sizeof(BitStatusType) * 8) #define BIT_STATUS_CLEAR(stats) (stats) = 0 #define BIT_STATUS_ON_ALL(stats) (stats) = ~((BitStatusType )0) #define BIT_STATUS_AT(stats,n) \ ((n) < (int )BIT_STATUS_BITS_NUM ? ((stats) & (1 << n)) : ((stats) & 1)) #define BIT_STATUS_ON_AT(stats,n) do {\ if ((n) < (int )BIT_STATUS_BITS_NUM) \ (stats) |= (1 << (n));\ else\ (stats) |= 1;\ } while (0) #define BIT_STATUS_ON_AT_SIMPLE(stats,n) do {\ if ((n) < (int )BIT_STATUS_BITS_NUM)\ (stats) |= (1 << (n));\ } while (0) #define INT_MAX_LIMIT ((1UL << (SIZEOF_INT * 8 - 1)) - 1) #define DIGITVAL(code) ((code) - '0') #define ODIGITVAL(code) DIGITVAL(code) #define XDIGITVAL(enc,code) \ (ONIGENC_IS_CODE_DIGIT(enc,code) ? DIGITVAL(code) \ : (ONIGENC_IS_CODE_UPPER(enc,code) ? (code) - 'A' + 10 : (code) - 'a' + 10)) #define IS_SINGLELINE(option) ((option) & ONIG_OPTION_SINGLELINE) #define IS_MULTILINE(option) ((option) & ONIG_OPTION_MULTILINE) #define IS_IGNORECASE(option) ((option) & ONIG_OPTION_IGNORECASE) #define IS_EXTEND(option) ((option) & ONIG_OPTION_EXTEND) #define IS_FIND_LONGEST(option) ((option) & ONIG_OPTION_FIND_LONGEST) #define IS_FIND_NOT_EMPTY(option) ((option) & ONIG_OPTION_FIND_NOT_EMPTY) #define IS_FIND_CONDITION(option) ((option) & \ (ONIG_OPTION_FIND_LONGEST | ONIG_OPTION_FIND_NOT_EMPTY)) #define IS_NOTBOL(option) ((option) & ONIG_OPTION_NOTBOL) #define IS_NOTEOL(option) ((option) & ONIG_OPTION_NOTEOL) #define IS_POSIX_REGION(option) ((option) & ONIG_OPTION_POSIX_REGION) #define IS_ASCII_RANGE(option) ((option) & ONIG_OPTION_ASCII_RANGE) #define IS_POSIX_BRACKET_ALL_RANGE(option) ((option) & ONIG_OPTION_POSIX_BRACKET_ALL_RANGE) #define IS_WORD_BOUND_ALL_RANGE(option) ((option) & ONIG_OPTION_WORD_BOUND_ALL_RANGE) #define IS_NEWLINE_CRLF(option) ((option) & ONIG_OPTION_NEWLINE_CRLF) #define IS_WHOLEWORD(option) ((option) & SE_ONIG_OPTION_WHOLEWORD) /* OP_SET_OPTION is required for these options. #define IS_DYNAMIC_OPTION(option) \ (((option) & (ONIG_OPTION_MULTILINE | ONIG_OPTION_IGNORECASE)) != 0) */ /* ignore-case and multibyte status are included in compiled code. */ #define IS_DYNAMIC_OPTION(option) 0 #define DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag) \ ((case_fold_flag) & ~INTERNAL_ONIGENC_CASE_FOLD_MULTI_CHAR) #define REPEAT_INFINITE -1 #define IS_REPEAT_INFINITE(n) ((n) == REPEAT_INFINITE) /* bitset */ #define BITS_PER_BYTE 8 #define SINGLE_BYTE_SIZE (1 << BITS_PER_BYTE) #define BITS_IN_ROOM ((int )sizeof(Bits) * BITS_PER_BYTE) #define BITSET_SIZE (SINGLE_BYTE_SIZE / BITS_IN_ROOM) #ifdef PLATFORM_UNALIGNED_WORD_ACCESS typedef unsigned int Bits; #else typedef unsigned char Bits; #endif typedef Bits BitSet[BITSET_SIZE]; typedef Bits* BitSetRef; #define SIZE_BITSET (int )sizeof(BitSet) #define BITSET_CLEAR(bs) do {\ int i;\ for (i = 0; i < BITSET_SIZE; i++) { (bs)[i] = 0; } \ } while (0) #define BS_ROOM(bs,pos) (bs)[(int )(pos) / BITS_IN_ROOM] #define BS_BIT(pos) (1 << ((int )(pos) % BITS_IN_ROOM)) #define BITSET_AT(bs, pos) (BS_ROOM(bs,pos) & BS_BIT(pos)) #define BITSET_SET_BIT(bs, pos) BS_ROOM(bs,pos) |= BS_BIT(pos) #define BITSET_CLEAR_BIT(bs, pos) BS_ROOM(bs,pos) &= ~(BS_BIT(pos)) #define BITSET_INVERT_BIT(bs, pos) BS_ROOM(bs,pos) ^= BS_BIT(pos) /* bytes buffer */ typedef struct _BBuf { UChar* p; unsigned int used; unsigned int alloc; } BBuf; #define BBUF_INIT(buf,size) onig_bbuf_init((BBuf* )(buf), (size)) #define BBUF_SIZE_INC(buf,inc) do{\ (buf)->alloc += (inc);\ (buf)->p = (UChar* )xrealloc((buf)->p, (buf)->alloc);\ if (IS_NULL((buf)->p)) return(ONIGERR_MEMORY);\ } while (0) #define BBUF_EXPAND(buf,low) do{\ do { (buf)->alloc *= 2; } while ((buf)->alloc < (unsigned int )low);\ (buf)->p = (UChar* )xrealloc((buf)->p, (buf)->alloc);\ if (IS_NULL((buf)->p)) return(ONIGERR_MEMORY);\ } while (0) #define BBUF_ENSURE_SIZE(buf,size) do{\ unsigned int new_alloc = (buf)->alloc;\ while (new_alloc < (unsigned int )(size)) { new_alloc *= 2; }\ if ((buf)->alloc != new_alloc) {\ (buf)->p = (UChar* )xrealloc((buf)->p, new_alloc);\ if (IS_NULL((buf)->p)) return(ONIGERR_MEMORY);\ (buf)->alloc = new_alloc;\ }\ } while (0) #define BBUF_WRITE(buf,pos,bytes,n) do{\ int used = (pos) + (int )(n);\ if ((buf)->alloc < (unsigned int )used) BBUF_EXPAND((buf),used);\ xmemcpy((buf)->p + (pos), (bytes), (n));\ if ((buf)->used < (unsigned int )used) (buf)->used = used;\ } while (0) #define BBUF_WRITE1(buf,pos,byte) do{\ int used = (pos) + 1;\ if ((buf)->alloc < (unsigned int )used) BBUF_EXPAND((buf),used);\ (buf)->p[(pos)] = (UChar )(byte);\ if ((buf)->used < (unsigned int )used) (buf)->used = used;\ } while (0) #define BBUF_ADD(buf,bytes,n) BBUF_WRITE((buf),(buf)->used,(bytes),(n)) #define BBUF_ADD1(buf,byte) BBUF_WRITE1((buf),(buf)->used,(byte)) #define BBUF_GET_ADD_ADDRESS(buf) ((buf)->p + (buf)->used) #define BBUF_GET_OFFSET_POS(buf) ((buf)->used) /* from < to */ #define BBUF_MOVE_RIGHT(buf,from,to,n) do {\ if ((unsigned int )((to)+(n)) > (buf)->alloc) BBUF_EXPAND((buf),(to) + (n));\ xmemmove((buf)->p + (to), (buf)->p + (from), (n));\ if ((unsigned int )((to)+(n)) > (buf)->used) (buf)->used = (to) + (n);\ } while (0) /* from > to */ #define BBUF_MOVE_LEFT(buf,from,to,n) do {\ xmemmove((buf)->p + (to), (buf)->p + (from), (n));\ } while (0) /* from > to */ #define BBUF_MOVE_LEFT_REDUCE(buf,from,to) do {\ xmemmove((buf)->p + (to), (buf)->p + (from), (buf)->used - (from));\ (buf)->used -= (from - to);\ } while (0) #define BBUF_INSERT(buf,pos,bytes,n) do {\ if (pos >= (buf)->used) {\ BBUF_WRITE(buf,pos,bytes,n);\ }\ else {\ BBUF_MOVE_RIGHT((buf),(pos),(pos) + (n),((buf)->used - (pos)));\ xmemcpy((buf)->p + (pos), (bytes), (n));\ }\ } while (0) #define BBUF_GET_BYTE(buf, pos) (buf)->p[(pos)] #define ANCHOR_BEGIN_BUF (1<<0) #define ANCHOR_BEGIN_LINE (1<<1) #define ANCHOR_BEGIN_POSITION (1<<2) #define ANCHOR_END_BUF (1<<3) #define ANCHOR_SEMI_END_BUF (1<<4) #define ANCHOR_END_LINE (1<<5) #define ANCHOR_WORD_BOUND (1<<6) #define ANCHOR_NOT_WORD_BOUND (1<<7) #define ANCHOR_WORD_BEGIN (1<<8) #define ANCHOR_WORD_END (1<<9) #define ANCHOR_PREC_READ (1<<10) #define ANCHOR_PREC_READ_NOT (1<<11) #define ANCHOR_LOOK_BEHIND (1<<12) #define ANCHOR_LOOK_BEHIND_NOT (1<<13) #define ANCHOR_ANYCHAR_STAR (1<<14) /* ".*" optimize info */ #define ANCHOR_ANYCHAR_STAR_ML (1<<15) /* ".*" optimize info (multi-line) */ #define ANCHOR_KEEP (1<<16) /* operation code */ enum OpCode { OP_FINISH = 0, /* matching process terminator (no more alternative) */ OP_END = 1, /* pattern code terminator (success end) */ OP_EXACT1 = 2, /* single byte, N = 1 */ OP_EXACT2, /* single byte, N = 2 */ OP_EXACT3, /* single byte, N = 3 */ OP_EXACT4, /* single byte, N = 4 */ OP_EXACT5, /* single byte, N = 5 */ OP_EXACTN, /* single byte */ OP_EXACTMB2N1, /* mb-length = 2 N = 1 */ OP_EXACTMB2N2, /* mb-length = 2 N = 2 */ OP_EXACTMB2N3, /* mb-length = 2 N = 3 */ OP_EXACTMB2N, /* mb-length = 2 */ OP_EXACTMB3N, /* mb-length = 3 */ OP_EXACTMBN, /* other length */ OP_EXACT1_IC, /* single byte, N = 1, ignore case */ OP_EXACTN_IC, /* single byte, ignore case */ OP_CCLASS, OP_CCLASS_MB, OP_CCLASS_MIX, OP_CCLASS_NOT, OP_CCLASS_MB_NOT, OP_CCLASS_MIX_NOT, OP_CCLASS_NODE, /* pointer to CClassNode node */ OP_ANYCHAR, /* "." */ OP_ANYCHAR_ML, /* "." multi-line */ OP_ANYCHAR_STAR, /* ".*" */ OP_ANYCHAR_ML_STAR, /* ".*" multi-line */ OP_ANYCHAR_STAR_PEEK_NEXT, OP_ANYCHAR_ML_STAR_PEEK_NEXT, OP_WORD, OP_NOT_WORD, OP_WORD_BOUND, OP_NOT_WORD_BOUND, OP_WORD_BEGIN, OP_WORD_END, OP_ASCII_WORD, OP_NOT_ASCII_WORD, OP_ASCII_WORD_BOUND, OP_NOT_ASCII_WORD_BOUND, OP_ASCII_WORD_BEGIN, OP_ASCII_WORD_END, OP_BEGIN_BUF, OP_END_BUF, OP_BEGIN_LINE, OP_END_LINE, OP_SEMI_END_BUF, OP_BEGIN_POSITION, OP_BEGIN_POS_OR_LINE, /* used for implicit anchor optimization */ OP_BACKREF1, OP_BACKREF2, OP_BACKREFN, OP_BACKREFN_IC, OP_BACKREF_MULTI, OP_BACKREF_MULTI_IC, OP_BACKREF_WITH_LEVEL, /* \k, \k */ OP_MEMORY_START, OP_MEMORY_START_PUSH, /* push back-tracker to stack */ OP_MEMORY_END_PUSH, /* push back-tracker to stack */ OP_MEMORY_END_PUSH_REC, /* push back-tracker to stack */ OP_MEMORY_END, OP_MEMORY_END_REC, /* push marker to stack */ OP_KEEP, OP_FAIL, /* pop stack and move */ OP_JUMP, OP_PUSH, OP_POP, OP_PUSH_OR_JUMP_EXACT1, /* if match exact then push, else jump. */ OP_PUSH_IF_PEEK_NEXT, /* if match exact then push, else none. */ OP_REPEAT, /* {n,m} */ OP_REPEAT_NG, /* {n,m}? (non greedy) */ OP_REPEAT_INC, OP_REPEAT_INC_NG, /* non greedy */ OP_REPEAT_INC_SG, /* search and get in stack */ OP_REPEAT_INC_NG_SG, /* search and get in stack (non greedy) */ OP_NULL_CHECK_START, /* null loop checker start */ OP_NULL_CHECK_END, /* null loop checker end */ OP_NULL_CHECK_END_MEMST, /* null loop checker end (with capture status) */ OP_NULL_CHECK_END_MEMST_PUSH, /* with capture status and push check-end */ OP_PUSH_POS, /* (?=...) start */ OP_POP_POS, /* (?=...) end */ OP_PUSH_POS_NOT, /* (?!...) start */ OP_FAIL_POS, /* (?!...) end */ OP_PUSH_STOP_BT, /* (?>...) start */ OP_POP_STOP_BT, /* (?>...) end */ OP_LOOK_BEHIND, /* (?<=...) start (no needs end opcode) */ OP_PUSH_LOOK_BEHIND_NOT, /* (? */ OP_RETURN, OP_CONDITION, OP_STATE_CHECK_PUSH, /* combination explosion check and push */ OP_STATE_CHECK_PUSH_OR_JUMP, /* check ok -> push, else jump */ OP_STATE_CHECK, /* check only */ OP_STATE_CHECK_ANYCHAR_STAR, OP_STATE_CHECK_ANYCHAR_ML_STAR, /* no need: IS_DYNAMIC_OPTION() == 0 */ OP_SET_OPTION_PUSH, /* set option and push recover option */ OP_SET_OPTION /* set option */ }; typedef int RelAddrType; typedef int AbsAddrType; typedef int LengthType; typedef int RepeatNumType; typedef short int MemNumType; typedef short int StateCheckNumType; typedef void* PointerType; #define SIZE_OPCODE 1 #define SIZE_RELADDR (int )sizeof(RelAddrType) #define SIZE_ABSADDR (int )sizeof(AbsAddrType) #define SIZE_LENGTH (int )sizeof(LengthType) #define SIZE_MEMNUM (int )sizeof(MemNumType) #define SIZE_STATE_CHECK_NUM (int )sizeof(StateCheckNumType) #define SIZE_REPEATNUM (int )sizeof(RepeatNumType) #define SIZE_OPTION (int )sizeof(OnigOptionType) #define SIZE_CODE_POINT (int )sizeof(OnigCodePoint) #define SIZE_POINTER (int )sizeof(PointerType) #define GET_RELADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, RelAddrType) #define GET_ABSADDR_INC(addr,p) PLATFORM_GET_INC(addr, p, AbsAddrType) #define GET_LENGTH_INC(len,p) PLATFORM_GET_INC(len, p, LengthType) #define GET_MEMNUM_INC(num,p) PLATFORM_GET_INC(num, p, MemNumType) #define GET_REPEATNUM_INC(num,p) PLATFORM_GET_INC(num, p, RepeatNumType) #define GET_OPTION_INC(option,p) PLATFORM_GET_INC(option, p, OnigOptionType) #define GET_POINTER_INC(ptr,p) PLATFORM_GET_INC(ptr, p, PointerType) #define GET_STATE_CHECK_NUM_INC(num,p) PLATFORM_GET_INC(num, p, StateCheckNumType) /* code point's address must be aligned address. */ #define GET_CODE_POINT(code,p) code = *((OnigCodePoint* )(p)) #define GET_BYTE_INC(byte,p) do{\ byte = *(p);\ (p)++;\ } while(0) /* op-code + arg size */ #define SIZE_OP_ANYCHAR_STAR SIZE_OPCODE #define SIZE_OP_ANYCHAR_STAR_PEEK_NEXT (SIZE_OPCODE + 1) #define SIZE_OP_JUMP (SIZE_OPCODE + SIZE_RELADDR) #define SIZE_OP_PUSH (SIZE_OPCODE + SIZE_RELADDR) #define SIZE_OP_POP SIZE_OPCODE #define SIZE_OP_PUSH_OR_JUMP_EXACT1 (SIZE_OPCODE + SIZE_RELADDR + 1) #define SIZE_OP_PUSH_IF_PEEK_NEXT (SIZE_OPCODE + SIZE_RELADDR + 1) #define SIZE_OP_REPEAT_INC (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_REPEAT_INC_NG (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_PUSH_POS SIZE_OPCODE #define SIZE_OP_PUSH_POS_NOT (SIZE_OPCODE + SIZE_RELADDR) #define SIZE_OP_POP_POS SIZE_OPCODE #define SIZE_OP_FAIL_POS SIZE_OPCODE #define SIZE_OP_SET_OPTION (SIZE_OPCODE + SIZE_OPTION) #define SIZE_OP_SET_OPTION_PUSH (SIZE_OPCODE + SIZE_OPTION) #define SIZE_OP_FAIL SIZE_OPCODE #define SIZE_OP_MEMORY_START (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_MEMORY_START_PUSH (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_MEMORY_END_PUSH (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_MEMORY_END_PUSH_REC (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_MEMORY_END (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_MEMORY_END_REC (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_PUSH_STOP_BT SIZE_OPCODE #define SIZE_OP_POP_STOP_BT SIZE_OPCODE #define SIZE_OP_NULL_CHECK_START (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_NULL_CHECK_END (SIZE_OPCODE + SIZE_MEMNUM) #define SIZE_OP_LOOK_BEHIND (SIZE_OPCODE + SIZE_LENGTH) #define SIZE_OP_PUSH_LOOK_BEHIND_NOT (SIZE_OPCODE + SIZE_RELADDR + SIZE_LENGTH) #define SIZE_OP_FAIL_LOOK_BEHIND_NOT SIZE_OPCODE #define SIZE_OP_CALL (SIZE_OPCODE + SIZE_ABSADDR) #define SIZE_OP_RETURN SIZE_OPCODE #define SIZE_OP_CONDITION (SIZE_OPCODE + SIZE_MEMNUM + SIZE_RELADDR) #ifdef USE_COMBINATION_EXPLOSION_CHECK #define SIZE_OP_STATE_CHECK (SIZE_OPCODE + SIZE_STATE_CHECK_NUM) #define SIZE_OP_STATE_CHECK_PUSH (SIZE_OPCODE + SIZE_STATE_CHECK_NUM + SIZE_RELADDR) #define SIZE_OP_STATE_CHECK_PUSH_OR_JUMP (SIZE_OPCODE + SIZE_STATE_CHECK_NUM + SIZE_RELADDR) #define SIZE_OP_STATE_CHECK_ANYCHAR_STAR (SIZE_OPCODE + SIZE_STATE_CHECK_NUM) #endif #define MC_ESC(syn) (syn)->meta_char_table.esc #define MC_ANYCHAR(syn) (syn)->meta_char_table.anychar #define MC_ANYTIME(syn) (syn)->meta_char_table.anytime #define MC_ZERO_OR_ONE_TIME(syn) (syn)->meta_char_table.zero_or_one_time #define MC_ONE_OR_MORE_TIME(syn) (syn)->meta_char_table.one_or_more_time #define MC_ANYCHAR_ANYTIME(syn) (syn)->meta_char_table.anychar_anytime #define IS_MC_ESC_CODE(code, syn) \ ((code) == MC_ESC(syn) && \ !IS_SYNTAX_OP2((syn), ONIG_SYN_OP2_INEFFECTIVE_ESCAPE)) #define SYN_POSIX_COMMON_OP \ ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_POSIX_BRACKET | \ ONIG_SYN_OP_DECIMAL_BACKREF | \ ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_ASTERISK_ZERO_INF | \ ONIG_SYN_OP_LINE_ANCHOR | \ ONIG_SYN_OP_ESC_CONTROL_CHARS ) #define SYN_GNU_REGEX_OP \ ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | \ ONIG_SYN_OP_POSIX_BRACKET | ONIG_SYN_OP_DECIMAL_BACKREF | \ ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_LPAREN_SUBEXP | \ ONIG_SYN_OP_VBAR_ALT | \ ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | \ ONIG_SYN_OP_QMARK_ZERO_ONE | \ ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR | ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR | \ ONIG_SYN_OP_ESC_W_WORD | \ ONIG_SYN_OP_ESC_B_WORD_BOUND | ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | \ ONIG_SYN_OP_ESC_S_WHITE_SPACE | ONIG_SYN_OP_ESC_D_DIGIT | \ ONIG_SYN_OP_LINE_ANCHOR ) #define SYN_GNU_REGEX_BV \ ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | \ ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | ONIG_SYN_ALLOW_INVALID_INTERVAL | \ ONIG_SYN_BACKSLASH_ESCAPE_IN_CC | ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) #define NCCLASS_FLAGS(cc) ((cc)->flags) #define NCCLASS_FLAG_SET(cc,flag) (NCCLASS_FLAGS(cc) |= (flag)) #define NCCLASS_FLAG_CLEAR(cc,flag) (NCCLASS_FLAGS(cc) &= ~(flag)) #define IS_NCCLASS_FLAG_ON(cc,flag) ((NCCLASS_FLAGS(cc) & (flag)) != 0) /* cclass node */ #define FLAG_NCCLASS_NOT (1<<0) #define FLAG_NCCLASS_SHARE (1<<1) #define NCCLASS_SET_NOT(nd) NCCLASS_FLAG_SET(nd, FLAG_NCCLASS_NOT) #define NCCLASS_SET_SHARE(nd) NCCLASS_FLAG_SET(nd, FLAG_NCCLASS_SHARE) #define NCCLASS_CLEAR_NOT(nd) NCCLASS_FLAG_CLEAR(nd, FLAG_NCCLASS_NOT) #define IS_NCCLASS_NOT(nd) IS_NCCLASS_FLAG_ON(nd, FLAG_NCCLASS_NOT) #define IS_NCCLASS_SHARE(nd) IS_NCCLASS_FLAG_ON(nd, FLAG_NCCLASS_SHARE) typedef struct { int type; /* struct _Node* next; */ /* unsigned int flags; */ } NodeBase; typedef struct { NodeBase base; unsigned int flags; BitSet bs; BBuf* mbuf; /* multi-byte info or NULL */ } CClassNode; typedef OnigPosition OnigStackIndex; typedef struct _OnigStackType { unsigned int type; union { struct { UChar *pcode; /* byte code position */ OnigPosition pstr; /* string position */ OnigPosition pstr_prev; /* previous char position of pstr */ #ifdef USE_COMBINATION_EXPLOSION_CHECK unsigned int state_check; #endif OnigPosition pkeep; /* keep pattern position */ } state; struct { int count; /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */ UChar *pcode; /* byte code position (head of repeated target) */ int num; /* repeat id */ } repeat; struct { OnigStackIndex si; /* index of stack */ } repeat_inc; struct { int num; /* memory num */ OnigPosition pstr; /* start/end position */ /* Following information is set, if this stack type is MEM-START */ OnigStackIndex start; /* prev. info (for backtrack "(...)*" ) */ OnigStackIndex end; /* prev. info (for backtrack "(...)*" ) */ } mem; struct { int num; /* null check id */ OnigPosition pstr; /* start position */ } null_check; #ifdef USE_SUBEXP_CALL struct { UChar *ret_addr; /* byte code position */ int num; /* null check id */ OnigPosition pstr; /* string position */ } call_frame; #endif } u; } OnigStackType; typedef struct { void* stack_p; size_t stack_n; OnigOptionType options; OnigRegion* region; OnigPosition start; /* search start position */ OnigPosition gpos; /* global position (for \G: BEGIN_POSITION) */ #ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE OnigPosition best_len; /* for ONIG_OPTION_FIND_LONGEST */ OnigPosition best_s; #endif #ifdef USE_COMBINATION_EXPLOSION_CHECK void* state_check_buff; int state_check_buff_size; #endif } OnigMatchArg; #define IS_CODE_SB_WORD(enc,code) \ (ONIGENC_IS_CODE_ASCII(code) && ONIGENC_IS_CODE_WORD(enc,code)) #ifdef ONIG_DEBUG typedef struct { short int opcode; const char* name; short int arg_type; } OnigOpInfoType; extern OnigOpInfoType OnigOpInfo[]; extern void onig_print_compiled_byte_code P_((FILE* f, UChar* bp, UChar** nextp, OnigEncoding enc)); #ifdef ONIG_DEBUG_STATISTICS extern void onig_statistics_init P_((void)); extern void onig_print_statistics P_((FILE* f)); #endif #endif extern UChar* onig_error_code_to_format P_((OnigPosition code)); extern void onig_snprintf_with_pattern PV_((UChar buf[], int bufsize, OnigEncoding enc, UChar* pat, UChar* pat_end, const UChar *fmt, ...)); extern int onig_bbuf_init P_((BBuf* buf, OnigDistance size)); extern int onig_compile P_((regex_t* reg, const UChar* pattern, const UChar* pattern_end, OnigErrorInfo* einfo)); extern void onig_chain_reduce P_((regex_t* reg)); extern void onig_chain_link_add P_((regex_t* to, regex_t* add)); extern void onig_transfer P_((regex_t* to, regex_t* from)); extern int onig_is_code_in_cc P_((OnigEncoding enc, OnigCodePoint code, CClassNode* cc)); extern int onig_is_code_in_cc_len P_((int enclen, OnigCodePoint code, CClassNode* cc)); /* strend hash */ typedef void hash_table_type; typedef uintptr_t hash_data_type; extern hash_table_type* onig_st_init_strend_table_with_size P_((int size)); extern int onig_st_lookup_strend P_((hash_table_type* table, const UChar* str_key, const UChar* end_key, hash_data_type *value)); extern int onig_st_insert_strend P_((hash_table_type* table, const UChar* str_key, const UChar* end_key, hash_data_type value)); /* encoding property management */ #define PROPERTY_LIST_ADD_PROP(Name, CR) \ r = onigenc_property_list_add_property((UChar* )Name, CR,\ &PropertyNameTable, &PropertyList, &PropertyListNum,\ &PropertyListSize);\ if (r != 0) goto end #define PROPERTY_LIST_INIT_CHECK \ if (PropertyInited == 0) {\ int r = onigenc_property_list_init(init_property_list);\ if (r != 0) return r;\ } extern int onigenc_property_list_add_property P_((UChar* name, const OnigCodePoint* prop, hash_table_type **table, const OnigCodePoint*** plist, int *pnum, int *psize)); typedef int (*ONIGENC_INIT_PROPERTY_LIST_FUNC_TYPE)(void); extern int onigenc_property_list_init P_((ONIGENC_INIT_PROPERTY_LIST_FUNC_TYPE)); extern size_t onig_memsize P_((const regex_t *reg)); extern size_t onig_region_memsize P_((const struct re_registers *regs)); #endif /* REGINT_H */ ================================================ FILE: src/Onigmo/regparse.c ================================================ /********************************************************************** regparse.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ #include "regparse.h" #include "st.h" #define WARN_BUFSIZE 256 #define CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS OnigSyntaxType OnigSyntaxRuby = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_RUBY | ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF | ONIG_SYN_OP2_ESC_G_SUBEXP_CALL | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL | ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META | ONIG_SYN_OP2_ESC_V_VTAB | ONIG_SYN_OP2_ESC_H_XDIGIT | ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER | ONIG_SYN_OP2_QMARK_LPAREN_CONDITION | ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK | ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV | ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND | ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP | ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME | ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY | ONIG_SYN_WARN_CC_OP_NOT_ESCAPED | ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT ) , ( /*ONIG_OPTION_ASCII_RANGE |*/ ONIG_OPTION_POSIX_BRACKET_ALL_RANGE | ONIG_OPTION_WORD_BOUND_ALL_RANGE ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType* OnigDefaultSyntax = ONIG_SYNTAX_RUBY; extern void onig_null_warn(const char* s ARG_UNUSED) { } #ifdef DEFAULT_WARN_FUNCTION static OnigWarnFunc onig_warn = (OnigWarnFunc )DEFAULT_WARN_FUNCTION; #else static OnigWarnFunc onig_warn = onig_null_warn; #endif #ifdef DEFAULT_VERB_WARN_FUNCTION static OnigWarnFunc onig_verb_warn = (OnigWarnFunc )DEFAULT_VERB_WARN_FUNCTION; #else static OnigWarnFunc onig_verb_warn = onig_null_warn; #endif extern void onig_set_warn_func(OnigWarnFunc f) { onig_warn = f; } extern void onig_set_verb_warn_func(OnigWarnFunc f) { onig_verb_warn = f; } static void bbuf_free(BBuf* bbuf) { if (IS_NOT_NULL(bbuf)) { if (IS_NOT_NULL(bbuf->p)) xfree(bbuf->p); xfree(bbuf); } } static int bbuf_clone(BBuf** rto, BBuf* from) { int r; BBuf *to; *rto = to = (BBuf* )xmalloc(sizeof(BBuf)); CHECK_NULL_RETURN_MEMERR(to); r = BBUF_INIT(to, from->alloc); if (r != 0) return r; to->used = from->used; xmemcpy(to->p, from->p, from->used); return 0; } #define BACKREF_REL_TO_ABS(rel_no, env) \ ((env)->num_mem + 1 + (rel_no)) #define ONOFF(v,f,negative) (negative) ? ((v) &= ~(f)) : ((v) |= (f)) #define MBCODE_START_POS(enc) \ (OnigCodePoint )(ONIGENC_MBC_MINLEN(enc) > 1 ? 0 : 0x80) #define SET_ALL_MULTI_BYTE_RANGE(enc, pbuf) \ add_code_range_to_buf(pbuf, MBCODE_START_POS(enc), ONIG_LAST_CODE_POINT) #define ADD_ALL_MULTI_BYTE_RANGE(enc, mbuf) do {\ if (! ONIGENC_IS_SINGLEBYTE(enc)) {\ r = SET_ALL_MULTI_BYTE_RANGE(enc, &(mbuf));\ if (r) return r;\ }\ } while (0) #define BITSET_IS_EMPTY(bs,empty) do {\ int i;\ empty = 1;\ for (i = 0; i < BITSET_SIZE; i++) {\ if ((bs)[i] != 0) {\ empty = 0; break;\ }\ }\ } while (0) static void bitset_set_range(BitSetRef bs, int from, int to) { int i; for (i = from; i <= to && i < SINGLE_BYTE_SIZE; i++) { BITSET_SET_BIT(bs, i); } } #if 0 static void bitset_set_all(BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { bs[i] = ~((Bits )0); } } #endif static void bitset_invert(BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { bs[i] = ~(bs[i]); } } static void bitset_invert_to(BitSetRef from, BitSetRef to) { int i; for (i = 0; i < BITSET_SIZE; i++) { to[i] = ~(from[i]); } } static void bitset_and(BitSetRef dest, BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { dest[i] &= bs[i]; } } static void bitset_or(BitSetRef dest, BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { dest[i] |= bs[i]; } } static void bitset_copy(BitSetRef dest, BitSetRef bs) { int i; for (i = 0; i < BITSET_SIZE; i++) { dest[i] = bs[i]; } } extern int onig_strncmp(const UChar* s1, const UChar* s2, int n) { int x; while (n-- > 0) { x = *s2++ - *s1++; if (x) return x; } return 0; } extern void onig_strcpy(UChar* dest, const UChar* src, const UChar* end) { ptrdiff_t len = end - src; if (len > 0) { xmemcpy(dest, src, len); dest[len] = (UChar )0; } } #ifdef USE_NAMED_GROUP static UChar* strdup_with_null(OnigEncoding enc, UChar* s, UChar* end) { ptrdiff_t slen; int term_len, i; UChar *r; slen = end - s; term_len = ONIGENC_MBC_MINLEN(enc); r = (UChar* )xmalloc(slen + term_len); CHECK_NULL_RETURN(r); xmemcpy(r, s, slen); for (i = 0; i < term_len; i++) r[slen + i] = (UChar )0; return r; } #endif /* scan pattern methods */ #define PEND_VALUE 0 #define PFETCH_READY UChar* pfetch_prev #define PEND (p < end ? 0 : 1) #define PUNFETCH p = pfetch_prev #define PINC do { \ pfetch_prev = p; \ p += ONIGENC_MBC_ENC_LEN(enc, p); \ } while (0) #define PFETCH(c) do { \ c = ONIGENC_MBC_TO_CODE(enc, p, end); \ pfetch_prev = p; \ p += ONIGENC_MBC_ENC_LEN(enc, p); \ } while (0) #define PPEEK (p < end ? ONIGENC_MBC_TO_CODE(enc, p, end) : PEND_VALUE) #define PPEEK_IS(c) (PPEEK == (OnigCodePoint )c) static UChar* strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end, size_t capa) { UChar* r; if (dest) r = (UChar* )xrealloc(dest, capa + 1); else r = (UChar* )xmalloc(capa + 1); CHECK_NULL_RETURN(r); onig_strcpy(r + (dest_end - dest), src, src_end); return r; } /* dest on static area */ static UChar* strcat_capa_from_static(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end, size_t capa) { UChar* r; r = (UChar* )xmalloc(capa + 1); CHECK_NULL_RETURN(r); onig_strcpy(r, dest, dest_end); onig_strcpy(r + (dest_end - dest), src, src_end); return r; } #ifdef USE_ST_LIBRARY typedef struct { UChar* s; UChar* end; } st_str_end_key; static int str_end_cmp(st_str_end_key* x, st_str_end_key* y) { UChar *p, *q; int c; if ((x->end - x->s) != (y->end - y->s)) return 1; p = x->s; q = y->s; while (p < x->end) { c = (int )*p - (int )*q; if (c != 0) return c; p++; q++; } return 0; } static int str_end_hash(st_str_end_key* x) { UChar *p; int val = 0; p = x->s; while (p < x->end) { val = val * 997 + (int )*p++; } return val + (val >> 5); } extern hash_table_type* onig_st_init_strend_table_with_size(int size) { static struct st_hash_type hashType = { str_end_cmp, str_end_hash, }; return (hash_table_type* ) onig_st_init_table_with_size(&hashType, size); } extern int onig_st_lookup_strend(hash_table_type* table, const UChar* str_key, const UChar* end_key, hash_data_type *value) { st_str_end_key key; key.s = (UChar* )str_key; key.end = (UChar* )end_key; return onig_st_lookup(table, (st_data_t )(&key), value); } extern int onig_st_insert_strend(hash_table_type* table, const UChar* str_key, const UChar* end_key, hash_data_type value) { st_str_end_key* key; int result; key = (st_str_end_key* )xmalloc(sizeof(st_str_end_key)); key->s = (UChar* )str_key; key->end = (UChar* )end_key; result = onig_st_insert(table, (st_data_t )key, value); if (result) { xfree(key); } return result; } #endif /* USE_ST_LIBRARY */ #ifdef USE_NAMED_GROUP #define INIT_NAME_BACKREFS_ALLOC_NUM 8 typedef struct { UChar* name; size_t name_len; /* byte length */ int back_num; /* number of backrefs */ int back_alloc; int back_ref1; int* back_refs; } NameEntry; #ifdef USE_ST_LIBRARY typedef st_table NameTable; typedef st_data_t HashDataType; /* 1.6 st.h doesn't define st_data_t type */ #ifdef ONIG_DEBUG static int i_print_name_entry(UChar* key, NameEntry* e, void* arg) { int i; FILE* fp = (FILE* )arg; fprintf(fp, "%s: ", e->name); if (e->back_num == 0) fputs("-", fp); else if (e->back_num == 1) fprintf(fp, "%d", e->back_ref1); else { for (i = 0; i < e->back_num; i++) { if (i > 0) fprintf(fp, ", "); fprintf(fp, "%d", e->back_refs[i]); } } fputs("\n", fp); return ST_CONTINUE; } extern int onig_print_names(FILE* fp, regex_t* reg) { NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { fprintf(fp, "name table\n"); onig_st_foreach(t, i_print_name_entry, (HashDataType )fp); fputs("\n", fp); } return 0; } #endif /* ONIG_DEBUG */ static int i_free_name_entry(UChar* key, NameEntry* e, void* arg ARG_UNUSED) { xfree(e->name); if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs); xfree(key); xfree(e); return ST_DELETE; } static int names_clear(regex_t* reg) { NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { onig_st_foreach(t, i_free_name_entry, 0); } return 0; } extern int onig_names_free(regex_t* reg) { int r; NameTable* t; r = names_clear(reg); if (r) return r; t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) onig_st_free_table(t); reg->name_table = (void* )NULL; return 0; } static NameEntry* name_find(regex_t* reg, const UChar* name, const UChar* name_end) { NameEntry* e; NameTable* t = (NameTable* )reg->name_table; e = (NameEntry* )NULL; if (IS_NOT_NULL(t)) { onig_st_lookup_strend(t, name, name_end, (HashDataType* )((void* )(&e))); } return e; } typedef struct { int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*); regex_t* reg; void* arg; int ret; OnigEncoding enc; } INamesArg; static int i_names(UChar* key ARG_UNUSED, NameEntry* e, INamesArg* arg) { int r = (*(arg->func))(e->name, e->name + e->name_len, e->back_num, (e->back_num > 1 ? e->back_refs : &(e->back_ref1)), arg->reg, arg->arg); if (r != 0) { arg->ret = r; return ST_STOP; } return ST_CONTINUE; } extern int onig_foreach_name(regex_t* reg, int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg) { INamesArg narg; NameTable* t = (NameTable* )reg->name_table; narg.ret = 0; if (IS_NOT_NULL(t)) { narg.func = func; narg.reg = reg; narg.arg = arg; narg.enc = reg->enc; /* should be pattern encoding. */ onig_st_foreach(t, i_names, (HashDataType )&narg); } return narg.ret; } static int i_renumber_name(UChar* key ARG_UNUSED, NameEntry* e, GroupNumRemap* map) { int i; if (e->back_num > 1) { for (i = 0; i < e->back_num; i++) { e->back_refs[i] = map[e->back_refs[i]].new_val; } } else if (e->back_num == 1) { e->back_ref1 = map[e->back_ref1].new_val; } return ST_CONTINUE; } extern int onig_renumber_name_table(regex_t* reg, GroupNumRemap* map) { NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { onig_st_foreach(t, i_renumber_name, (HashDataType )map); } return 0; } extern int onig_number_of_names(regex_t* reg) { NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) return t->num_entries; else return 0; } #else /* USE_ST_LIBRARY */ #define INIT_NAMES_ALLOC_NUM 8 typedef struct { NameEntry* e; int num; int alloc; } NameTable; #ifdef ONIG_DEBUG extern int onig_print_names(FILE* fp, regex_t* reg) { int i, j; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t) && t->num > 0) { fprintf(fp, "name table\n"); for (i = 0; i < t->num; i++) { e = &(t->e[i]); fprintf(fp, "%s: ", e->name); if (e->back_num == 0) { fputs("-", fp); } else if (e->back_num == 1) { fprintf(fp, "%d", e->back_ref1); } else { for (j = 0; j < e->back_num; j++) { if (j > 0) fprintf(fp, ", "); fprintf(fp, "%d", e->back_refs[j]); } } fputs("\n", fp); } fputs("\n", fp); } return 0; } #endif static int names_clear(regex_t* reg) { int i; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { for (i = 0; i < t->num; i++) { e = &(t->e[i]); if (IS_NOT_NULL(e->name)) { xfree(e->name); e->name = NULL; e->name_len = 0; e->back_num = 0; e->back_alloc = 0; if (IS_NOT_NULL(e->back_refs)) xfree(e->back_refs); e->back_refs = (int* )NULL; } } if (IS_NOT_NULL(t->e)) { xfree(t->e); t->e = NULL; } t->num = 0; } return 0; } extern int onig_names_free(regex_t* reg) { int r; NameTable* t; r = names_clear(reg); if (r) return r; t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) xfree(t); reg->name_table = NULL; return 0; } static NameEntry* name_find(regex_t* reg, const UChar* name, const UChar* name_end) { int i, len; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { len = name_end - name; for (i = 0; i < t->num; i++) { e = &(t->e[i]); if (len == e->name_len && onig_strncmp(name, e->name, len) == 0) return e; } } return (NameEntry* )NULL; } extern int onig_foreach_name(regex_t* reg, int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg) { int i, r; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) { for (i = 0; i < t->num; i++) { e = &(t->e[i]); r = (*func)(e->name, e->name + e->name_len, e->back_num, (e->back_num > 1 ? e->back_refs : &(e->back_ref1)), reg, arg); if (r != 0) return r; } } return 0; } extern int onig_number_of_names(regex_t* reg) { NameTable* t = (NameTable* )reg->name_table; if (IS_NOT_NULL(t)) return t->num; else return 0; } #endif /* else USE_ST_LIBRARY */ static int name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env) { int alloc; NameEntry* e; NameTable* t = (NameTable* )reg->name_table; if (name_end - name <= 0) return ONIGERR_EMPTY_GROUP_NAME; e = name_find(reg, name, name_end); if (IS_NULL(e)) { #ifdef USE_ST_LIBRARY if (IS_NULL(t)) { t = onig_st_init_strend_table_with_size(5); reg->name_table = (void* )t; } e = (NameEntry* )xmalloc(sizeof(NameEntry)); CHECK_NULL_RETURN_MEMERR(e); e->name = strdup_with_null(reg->enc, name, name_end); if (IS_NULL(e->name)) { xfree(e); return ONIGERR_MEMORY; } onig_st_insert_strend(t, e->name, (e->name + (name_end - name)), (HashDataType )e); e->name_len = name_end - name; e->back_num = 0; e->back_alloc = 0; e->back_refs = (int* )NULL; #else if (IS_NULL(t)) { alloc = INIT_NAMES_ALLOC_NUM; t = (NameTable* )xmalloc(sizeof(NameTable)); CHECK_NULL_RETURN_MEMERR(t); t->e = NULL; t->alloc = 0; t->num = 0; t->e = (NameEntry* )xmalloc(sizeof(NameEntry) * alloc); if (IS_NULL(t->e)) { xfree(t); return ONIGERR_MEMORY; } t->alloc = alloc; reg->name_table = t; goto clear; } else if (t->num == t->alloc) { int i; NameEntry* p; alloc = t->alloc * 2; p = (NameEntry* )xrealloc(t->e, sizeof(NameEntry) * alloc); CHECK_NULL_RETURN_MEMERR(p); t->e = p; t->alloc = alloc; clear: for (i = t->num; i < t->alloc; i++) { t->e[i].name = NULL; t->e[i].name_len = 0; t->e[i].back_num = 0; t->e[i].back_alloc = 0; t->e[i].back_refs = (int* )NULL; } } e = &(t->e[t->num]); t->num++; e->name = strdup_with_null(reg->enc, name, name_end); if (IS_NULL(e->name)) return ONIGERR_MEMORY; e->name_len = name_end - name; #endif } if (e->back_num >= 1 && ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME)) { onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINED_NAME, name, name_end); return ONIGERR_MULTIPLEX_DEFINED_NAME; } e->back_num++; if (e->back_num == 1) { e->back_ref1 = backref; } else { if (e->back_num == 2) { alloc = INIT_NAME_BACKREFS_ALLOC_NUM; e->back_refs = (int* )xmalloc(sizeof(int) * alloc); CHECK_NULL_RETURN_MEMERR(e->back_refs); e->back_alloc = alloc; e->back_refs[0] = e->back_ref1; e->back_refs[1] = backref; } else { if (e->back_num > e->back_alloc) { int* p; alloc = e->back_alloc * 2; p = (int* )xrealloc(e->back_refs, sizeof(int) * alloc); CHECK_NULL_RETURN_MEMERR(p); e->back_refs = p; e->back_alloc = alloc; } e->back_refs[e->back_num - 1] = backref; } } return 0; } extern int onig_name_to_group_numbers(regex_t* reg, const UChar* name, const UChar* name_end, int** nums) { NameEntry* e = name_find(reg, name, name_end); if (IS_NULL(e)) return ONIGERR_UNDEFINED_NAME_REFERENCE; switch (e->back_num) { case 0: *nums = 0; break; case 1: *nums = &(e->back_ref1); break; default: *nums = e->back_refs; break; } return e->back_num; } extern int onig_name_to_backref_number(regex_t* reg, const UChar* name, const UChar* name_end, OnigRegion *region) { int i, n, *nums; n = onig_name_to_group_numbers(reg, name, name_end, &nums); if (n < 0) return n; else if (n == 0) return ONIGERR_PARSER_BUG; else if (n == 1) return nums[0]; else { if (IS_NOT_NULL(region)) { for (i = n - 1; i >= 0; i--) { if (region->beg[nums[i]] != ONIG_REGION_NOTPOS) return nums[i]; } } return nums[n - 1]; } } #else /* USE_NAMED_GROUP */ extern int onig_name_to_group_numbers(regex_t* reg, const UChar* name, const UChar* name_end, int** nums) { return ONIG_NO_SUPPORT_CONFIG; } extern int onig_name_to_backref_number(regex_t* reg, const UChar* name, const UChar* name_end, OnigRegion* region) { return ONIG_NO_SUPPORT_CONFIG; } extern int onig_foreach_name(regex_t* reg, int (*func)(const UChar*, const UChar*,int,int*,regex_t*,void*), void* arg) { return ONIG_NO_SUPPORT_CONFIG; } extern int onig_number_of_names(regex_t* reg) { return 0; } #endif /* else USE_NAMED_GROUP */ extern int onig_noname_group_capture_is_active(regex_t* reg) { if (ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_DONT_CAPTURE_GROUP)) return 0; #ifdef USE_NAMED_GROUP if (onig_number_of_names(reg) > 0 && IS_SYNTAX_BV(reg->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) && !ONIG_IS_OPTION_ON(reg->options, ONIG_OPTION_CAPTURE_GROUP)) { return 0; } #endif return 1; } #define INIT_SCANENV_MEMNODES_ALLOC_SIZE 16 static void scan_env_clear(ScanEnv* env) { int i; BIT_STATUS_CLEAR(env->capture_history); BIT_STATUS_CLEAR(env->bt_mem_start); BIT_STATUS_CLEAR(env->bt_mem_end); BIT_STATUS_CLEAR(env->backrefed_mem); env->error = (UChar* )NULL; env->error_end = (UChar* )NULL; env->num_call = 0; env->num_mem = 0; #ifdef USE_NAMED_GROUP env->num_named = 0; #endif env->mem_alloc = 0; env->mem_nodes_dynamic = (Node** )NULL; for (i = 0; i < SCANENV_MEMNODES_SIZE; i++) env->mem_nodes_static[i] = NULL_NODE; #ifdef USE_COMBINATION_EXPLOSION_CHECK env->num_comb_exp_check = 0; env->comb_exp_max_regnum = 0; env->curr_max_regnum = 0; env->has_recursion = 0; #endif } static int scan_env_add_mem_entry(ScanEnv* env) { int i, need, alloc; Node** p; need = env->num_mem + 1; if (need >= SCANENV_MEMNODES_SIZE) { if (env->mem_alloc <= need) { if (IS_NULL(env->mem_nodes_dynamic)) { alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE; p = (Node** )xmalloc(sizeof(Node*) * alloc); xmemcpy(p, env->mem_nodes_static, sizeof(Node*) * SCANENV_MEMNODES_SIZE); } else { alloc = env->mem_alloc * 2; p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc); } CHECK_NULL_RETURN_MEMERR(p); for (i = env->num_mem + 1; i < alloc; i++) p[i] = NULL_NODE; env->mem_nodes_dynamic = p; env->mem_alloc = alloc; } } env->num_mem++; return env->num_mem; } static int scan_env_set_mem_node(ScanEnv* env, int num, Node* node) { if (env->num_mem >= num) SCANENV_MEM_NODES(env)[num] = node; else return ONIGERR_PARSER_BUG; return 0; } #ifdef USE_PARSE_TREE_NODE_RECYCLE typedef struct _FreeNode { struct _FreeNode* next; } FreeNode; static FreeNode* FreeNodeList = (FreeNode* )NULL; #endif extern void onig_node_free(Node* node) { start: if (IS_NULL(node)) return ; switch (NTYPE(node)) { case NT_STR: if (NSTR(node)->capa != 0 && IS_NOT_NULL(NSTR(node)->s) && NSTR(node)->s != NSTR(node)->buf) { xfree(NSTR(node)->s); } break; case NT_LIST: case NT_ALT: onig_node_free(NCAR(node)); { Node* next_node = NCDR(node); #ifdef USE_PARSE_TREE_NODE_RECYCLE { FreeNode* n = (FreeNode* )node; THREAD_ATOMIC_START; n->next = FreeNodeList; FreeNodeList = n; THREAD_ATOMIC_END; } #else xfree(node); #endif node = next_node; goto start; } break; case NT_CCLASS: { CClassNode* cc = NCCLASS(node); if (IS_NCCLASS_SHARE(cc)) return ; if (cc->mbuf) bbuf_free(cc->mbuf); } break; case NT_QTFR: if (NQTFR(node)->target) onig_node_free(NQTFR(node)->target); break; case NT_ENCLOSE: if (NENCLOSE(node)->target) onig_node_free(NENCLOSE(node)->target); break; case NT_BREF: if (IS_NOT_NULL(NBREF(node)->back_dynamic)) xfree(NBREF(node)->back_dynamic); break; case NT_ANCHOR: if (NANCHOR(node)->target) onig_node_free(NANCHOR(node)->target); break; } #ifdef USE_PARSE_TREE_NODE_RECYCLE { FreeNode* n = (FreeNode* )node; THREAD_ATOMIC_START; n->next = FreeNodeList; FreeNodeList = n; THREAD_ATOMIC_END; } #else xfree(node); #endif } #ifdef USE_PARSE_TREE_NODE_RECYCLE extern int onig_free_node_list(void) { FreeNode* n; /* THREAD_ATOMIC_START; */ while (IS_NOT_NULL(FreeNodeList)) { n = FreeNodeList; FreeNodeList = FreeNodeList->next; xfree(n); } /* THREAD_ATOMIC_END; */ return 0; } #endif static Node* node_new(void) { Node* node; #ifdef USE_PARSE_TREE_NODE_RECYCLE THREAD_ATOMIC_START; if (IS_NOT_NULL(FreeNodeList)) { node = (Node* )FreeNodeList; FreeNodeList = FreeNodeList->next; THREAD_ATOMIC_END; return node; } THREAD_ATOMIC_END; #endif node = (Node* )xmalloc(sizeof(Node)); /* xmemset(node, 0, sizeof(Node)); */ return node; } static void initialize_cclass(CClassNode* cc) { BITSET_CLEAR(cc->bs); /* cc->base.flags = 0; */ cc->flags = 0; cc->mbuf = NULL; } static Node* node_new_cclass(void) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_CCLASS); initialize_cclass(NCCLASS(node)); return node; } static Node* node_new_cclass_by_codepoint_range(int not, OnigCodePoint sb_out, const OnigCodePoint ranges[]) { int n, i; CClassNode* cc; OnigCodePoint j; Node* node = node_new_cclass(); CHECK_NULL_RETURN(node); cc = NCCLASS(node); if (not != 0) NCCLASS_SET_NOT(cc); BITSET_CLEAR(cc->bs); if (sb_out > 0 && IS_NOT_NULL(ranges)) { n = ONIGENC_CODE_RANGE_NUM(ranges); for (i = 0; i < n; i++) { for (j = ONIGENC_CODE_RANGE_FROM(ranges, i); j <= (OnigCodePoint )ONIGENC_CODE_RANGE_TO(ranges, i); j++) { if (j >= sb_out) goto sb_end; BITSET_SET_BIT(cc->bs, j); } } } sb_end: if (IS_NULL(ranges)) { is_null: cc->mbuf = NULL; } else { BBuf* bbuf; n = ONIGENC_CODE_RANGE_NUM(ranges); if (n == 0) goto is_null; bbuf = (BBuf* )xmalloc(sizeof(BBuf)); CHECK_NULL_RETURN(bbuf); bbuf->alloc = n + 1; bbuf->used = n + 1; bbuf->p = (UChar* )((void* )ranges); cc->mbuf = bbuf; } return node; } static Node* node_new_ctype(int type, int not, int ascii_range) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_CTYPE); NCTYPE(node)->ctype = type; NCTYPE(node)->not = not; NCTYPE(node)->ascii_range = ascii_range; return node; } static Node* node_new_anychar(void) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_CANY); return node; } static Node* node_new_list(Node* left, Node* right) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_LIST); NCAR(node) = left; NCDR(node) = right; return node; } extern Node* onig_node_new_list(Node* left, Node* right) { return node_new_list(left, right); } extern Node* onig_node_list_add(Node* list, Node* x) { Node *n; n = onig_node_new_list(x, NULL); if (IS_NULL(n)) return NULL_NODE; if (IS_NOT_NULL(list)) { while (IS_NOT_NULL(NCDR(list))) list = NCDR(list); NCDR(list) = n; } return n; } extern Node* onig_node_new_alt(Node* left, Node* right) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_ALT); NCAR(node) = left; NCDR(node) = right; return node; } extern Node* onig_node_new_anchor(int type) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_ANCHOR); NANCHOR(node)->type = type; NANCHOR(node)->target = NULL; NANCHOR(node)->char_len = -1; NANCHOR(node)->ascii_range = 0; return node; } static Node* node_new_backref(int back_num, int* backrefs, int by_name, #ifdef USE_BACKREF_WITH_LEVEL int exist_level, int nest_level, #endif ScanEnv* env) { int i; Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_BREF); NBREF(node)->state = 0; NBREF(node)->back_num = back_num; NBREF(node)->back_dynamic = (int* )NULL; if (by_name != 0) NBREF(node)->state |= NST_NAME_REF; #ifdef USE_BACKREF_WITH_LEVEL if (exist_level != 0) { NBREF(node)->state |= NST_NEST_LEVEL; NBREF(node)->nest_level = nest_level; } #endif for (i = 0; i < back_num; i++) { if (backrefs[i] <= env->num_mem && IS_NULL(SCANENV_MEM_NODES(env)[backrefs[i]])) { NBREF(node)->state |= NST_RECURSION; /* /...(\1).../ */ break; } } if (back_num <= NODE_BACKREFS_SIZE) { for (i = 0; i < back_num; i++) NBREF(node)->back_static[i] = backrefs[i]; } else { int* p = (int* )xmalloc(sizeof(int) * back_num); if (IS_NULL(p)) { onig_node_free(node); return NULL; } NBREF(node)->back_dynamic = p; for (i = 0; i < back_num; i++) p[i] = backrefs[i]; } return node; } #ifdef USE_SUBEXP_CALL static Node* node_new_call(UChar* name, UChar* name_end, int gnum) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_CALL); NCALL(node)->state = 0; NCALL(node)->target = NULL_NODE; NCALL(node)->name = name; NCALL(node)->name_end = name_end; NCALL(node)->group_num = gnum; /* call by number if gnum != 0 */ return node; } #endif static Node* node_new_quantifier(int lower, int upper, int by_number) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_QTFR); NQTFR(node)->state = 0; NQTFR(node)->target = NULL; NQTFR(node)->lower = lower; NQTFR(node)->upper = upper; NQTFR(node)->greedy = 1; NQTFR(node)->target_empty_info = NQ_TARGET_ISNOT_EMPTY; NQTFR(node)->head_exact = NULL_NODE; NQTFR(node)->next_head_exact = NULL_NODE; NQTFR(node)->is_refered = 0; if (by_number != 0) NQTFR(node)->state |= NST_BY_NUMBER; #ifdef USE_COMBINATION_EXPLOSION_CHECK NQTFR(node)->comb_exp_check_num = 0; #endif return node; } static Node* node_new_enclose(int type) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_ENCLOSE); NENCLOSE(node)->type = type; NENCLOSE(node)->state = 0; NENCLOSE(node)->regnum = 0; NENCLOSE(node)->option = 0; NENCLOSE(node)->target = NULL; NENCLOSE(node)->call_addr = -1; NENCLOSE(node)->opt_count = 0; return node; } extern Node* onig_node_new_enclose(int type) { return node_new_enclose(type); } static Node* node_new_enclose_memory(OnigOptionType option, int is_named) { Node* node = node_new_enclose(ENCLOSE_MEMORY); CHECK_NULL_RETURN(node); if (is_named != 0) SET_ENCLOSE_STATUS(node, NST_NAMED_GROUP); #ifdef USE_SUBEXP_CALL NENCLOSE(node)->option = option; #endif return node; } static Node* node_new_option(OnigOptionType option) { Node* node = node_new_enclose(ENCLOSE_OPTION); CHECK_NULL_RETURN(node); NENCLOSE(node)->option = option; return node; } extern int onig_node_str_cat(Node* node, const UChar* s, const UChar* end) { ptrdiff_t addlen = end - s; if (addlen > 0) { ptrdiff_t len = NSTR(node)->end - NSTR(node)->s; if (NSTR(node)->capa > 0 || (len + addlen > NODE_STR_BUF_SIZE - 1)) { UChar* p; ptrdiff_t capa = len + addlen + NODE_STR_MARGIN; if (capa <= NSTR(node)->capa) { onig_strcpy(NSTR(node)->s + len, s, end); } else { if (NSTR(node)->s == NSTR(node)->buf) p = strcat_capa_from_static(NSTR(node)->s, NSTR(node)->end, s, end, capa); else p = strcat_capa(NSTR(node)->s, NSTR(node)->end, s, end, capa); CHECK_NULL_RETURN_MEMERR(p); NSTR(node)->s = p; NSTR(node)->capa = (int )capa; } } else { onig_strcpy(NSTR(node)->s + len, s, end); } NSTR(node)->end = NSTR(node)->s + len + addlen; } return 0; } extern int onig_node_str_set(Node* node, const UChar* s, const UChar* end) { onig_node_str_clear(node); return onig_node_str_cat(node, s, end); } static int node_str_cat_char(Node* node, UChar c) { UChar s[1]; s[0] = c; return onig_node_str_cat(node, s, s + 1); } static int node_str_cat_codepoint(Node* node, OnigEncoding enc, OnigCodePoint c) { UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; int num = ONIGENC_CODE_TO_MBC(enc, c, buf); if (num < 0) return num; return onig_node_str_cat(node, buf, buf + num); } extern void onig_node_conv_to_str_node(Node* node, int flag) { SET_NTYPE(node, NT_STR); NSTR(node)->flag = flag; NSTR(node)->capa = 0; NSTR(node)->s = NSTR(node)->buf; NSTR(node)->end = NSTR(node)->buf; } extern void onig_node_str_clear(Node* node) { if (NSTR(node)->capa != 0 && IS_NOT_NULL(NSTR(node)->s) && NSTR(node)->s != NSTR(node)->buf) { xfree(NSTR(node)->s); } NSTR(node)->capa = 0; NSTR(node)->flag = 0; NSTR(node)->s = NSTR(node)->buf; NSTR(node)->end = NSTR(node)->buf; } static Node* node_new_str(const UChar* s, const UChar* end) { Node* node = node_new(); CHECK_NULL_RETURN(node); SET_NTYPE(node, NT_STR); NSTR(node)->capa = 0; NSTR(node)->flag = 0; NSTR(node)->s = NSTR(node)->buf; NSTR(node)->end = NSTR(node)->buf; if (onig_node_str_cat(node, s, end)) { onig_node_free(node); return NULL; } return node; } extern Node* onig_node_new_str(const UChar* s, const UChar* end) { return node_new_str(s, end); } static Node* node_new_str_raw(UChar* s, UChar* end) { Node* node = node_new_str(s, end); if (IS_NOT_NULL(node)) NSTRING_SET_RAW(node); return node; } static Node* node_new_empty(void) { return node_new_str(NULL, NULL); } static Node* node_new_str_raw_char(UChar c) { UChar p[1]; p[0] = c; return node_new_str_raw(p, p + 1); } static Node* str_node_split_last_char(StrNode* sn, OnigEncoding enc) { const UChar *p; Node* n = NULL_NODE; if (sn->end > sn->s) { p = onigenc_get_prev_char_head(enc, sn->s, sn->end); if (p && p > sn->s) { /* can be split. */ n = node_new_str(p, sn->end); if (IS_NOT_NULL(n) && (sn->flag & NSTR_RAW) != 0) NSTRING_SET_RAW(n); sn->end = (UChar* )p; } } return n; } static int str_node_can_be_split(StrNode* sn, OnigEncoding enc) { if (sn->end > sn->s) { return ((enclen(enc, sn->s) < sn->end - sn->s) ? 1 : 0); } return 0; } #ifdef USE_PAD_TO_SHORT_BYTE_CHAR static int node_str_head_pad(StrNode* sn, int num, UChar val) { UChar buf[NODE_STR_BUF_SIZE]; int i, len; len = sn->end - sn->s; onig_strcpy(buf, sn->s, sn->end); onig_strcpy(&(sn->s[num]), buf, buf + len); sn->end += num; for (i = 0; i < num; i++) { sn->s[i] = val; } } #endif extern int onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc) { unsigned int num, val; OnigCodePoint c; UChar* p = *src; PFETCH_READY; num = 0; while (!PEND) { PFETCH(c); if (ONIGENC_IS_CODE_DIGIT(enc, c)) { val = (unsigned int )DIGITVAL(c); if ((INT_MAX_LIMIT - val) / 10UL < num) return -1; /* overflow */ num = num * 10 + val; } else { PUNFETCH; break; } } *src = p; return num; } static int scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen, int maxlen, OnigEncoding enc) { OnigCodePoint c; unsigned int num, val; int restlen; UChar* p = *src; PFETCH_READY; restlen = maxlen - minlen; num = 0; while (!PEND && maxlen-- != 0) { PFETCH(c); if (ONIGENC_IS_CODE_XDIGIT(enc, c)) { val = (unsigned int )XDIGITVAL(enc,c); if ((INT_MAX_LIMIT - val) / 16UL < num) return -1; /* overflow */ num = (num << 4) + XDIGITVAL(enc,c); } else { PUNFETCH; break; } } if (maxlen > restlen) return -2; /* not enough digits */ *src = p; return num; } static int scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen, OnigEncoding enc) { OnigCodePoint c; unsigned int num, val; UChar* p = *src; PFETCH_READY; num = 0; while (!PEND && maxlen-- != 0) { PFETCH(c); if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8') { val = ODIGITVAL(c); if ((INT_MAX_LIMIT - val) / 8UL < num) return -1; /* overflow */ num = (num << 3) + val; } else { PUNFETCH; break; } } *src = p; return num; } #define BBUF_WRITE_CODE_POINT(bbuf,pos,code) \ BBUF_WRITE(bbuf, pos, &(code), SIZE_CODE_POINT) /* data format: [n][from-1][to-1][from-2][to-2] ... [from-n][to-n] (all data size is OnigCodePoint) */ static int new_code_range(BBuf** pbuf) { #define INIT_MULTI_BYTE_RANGE_SIZE (SIZE_CODE_POINT * 5) int r; OnigCodePoint n; BBuf* bbuf; bbuf = *pbuf = (BBuf* )xmalloc(sizeof(BBuf)); CHECK_NULL_RETURN_MEMERR(*pbuf); r = BBUF_INIT(*pbuf, INIT_MULTI_BYTE_RANGE_SIZE); if (r) return r; n = 0; BBUF_WRITE_CODE_POINT(bbuf, 0, n); return 0; } static int add_code_range_to_buf(BBuf** pbuf, OnigCodePoint from, OnigCodePoint to) { int r, inc_n, pos; OnigCodePoint low, high, bound, x; OnigCodePoint n, *data; BBuf* bbuf; if (from > to) { n = from; from = to; to = n; } if (IS_NULL(*pbuf)) { r = new_code_range(pbuf); if (r) return r; bbuf = *pbuf; n = 0; } else { bbuf = *pbuf; GET_CODE_POINT(n, bbuf->p); } data = (OnigCodePoint* )(bbuf->p); data++; bound = (from == 0) ? 0 : n; for (low = 0; low < bound; ) { x = (low + bound) >> 1; if (from - 1 > data[x*2 + 1]) low = x + 1; else bound = x; } high = (to == ONIG_LAST_CODE_POINT) ? n : low; for (bound = n; high < bound; ) { x = (high + bound) >> 1; if (to + 1 >= data[x*2]) high = x + 1; else bound = x; } inc_n = low + 1 - high; if (n + inc_n > ONIG_MAX_MULTI_BYTE_RANGES_NUM) return ONIGERR_TOO_MANY_MULTI_BYTE_RANGES; if (inc_n != 1) { if (from > data[low*2]) from = data[low*2]; if (to < data[(high - 1)*2 + 1]) to = data[(high - 1)*2 + 1]; } if (inc_n != 0) { int from_pos = SIZE_CODE_POINT * (1 + high * 2); int to_pos = SIZE_CODE_POINT * (1 + (low + 1) * 2); if (inc_n > 0) { if (high < n) { int size = (n - high) * 2 * SIZE_CODE_POINT; BBUF_MOVE_RIGHT(bbuf, from_pos, to_pos, size); } } else { BBUF_MOVE_LEFT_REDUCE(bbuf, from_pos, to_pos); } } pos = SIZE_CODE_POINT * (1 + low * 2); BBUF_ENSURE_SIZE(bbuf, pos + SIZE_CODE_POINT * 2); BBUF_WRITE_CODE_POINT(bbuf, pos, from); BBUF_WRITE_CODE_POINT(bbuf, pos + SIZE_CODE_POINT, to); n += inc_n; BBUF_WRITE_CODE_POINT(bbuf, 0, n); return 0; } static int add_code_range(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to) { if (from > to) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC)) return 0; else return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS; } return add_code_range_to_buf(pbuf, from, to); } static int not_code_range_buf(OnigEncoding enc, BBuf* bbuf, BBuf** pbuf) { int r, i, n; OnigCodePoint pre, from, *data, to = 0; *pbuf = (BBuf* )NULL; if (IS_NULL(bbuf)) { set_all: return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); } data = (OnigCodePoint* )(bbuf->p); GET_CODE_POINT(n, data); data++; if (n <= 0) goto set_all; r = 0; pre = MBCODE_START_POS(enc); for (i = 0; i < n; i++) { from = data[i*2]; to = data[i*2+1]; if (pre <= from - 1) { r = add_code_range_to_buf(pbuf, pre, from - 1); if (r != 0) return r; } if (to == ONIG_LAST_CODE_POINT) break; pre = to + 1; } if (to < ONIG_LAST_CODE_POINT) { r = add_code_range_to_buf(pbuf, to + 1, ONIG_LAST_CODE_POINT); } return r; } #define SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2) do {\ BBuf *tbuf; \ int tnot; \ tnot = not1; not1 = not2; not2 = tnot; \ tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf; \ } while (0) static int or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) { int r; OnigCodePoint i, n1, *data1; OnigCodePoint from, to; *pbuf = (BBuf* )NULL; if (IS_NULL(bbuf1) && IS_NULL(bbuf2)) { if (not1 != 0 || not2 != 0) return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); return 0; } r = 0; if (IS_NULL(bbuf2)) SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2); if (IS_NULL(bbuf1)) { if (not1 != 0) { return SET_ALL_MULTI_BYTE_RANGE(enc, pbuf); } else { if (not2 == 0) { return bbuf_clone(pbuf, bbuf2); } else { return not_code_range_buf(enc, bbuf2, pbuf); } } } if (not1 != 0) SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2); data1 = (OnigCodePoint* )(bbuf1->p); GET_CODE_POINT(n1, data1); data1++; if (not2 == 0 && not1 == 0) { /* 1 OR 2 */ r = bbuf_clone(pbuf, bbuf2); } else if (not1 == 0) { /* 1 OR (not 2) */ r = not_code_range_buf(enc, bbuf2, pbuf); } if (r != 0) return r; for (i = 0; i < n1; i++) { from = data1[i*2]; to = data1[i*2+1]; r = add_code_range_to_buf(pbuf, from, to); if (r != 0) return r; } return 0; } static int and_code_range1(BBuf** pbuf, OnigCodePoint from1, OnigCodePoint to1, OnigCodePoint* data, int n) { int i, r; OnigCodePoint from2, to2; for (i = 0; i < n; i++) { from2 = data[i*2]; to2 = data[i*2+1]; if (from2 < from1) { if (to2 < from1) continue; else { from1 = to2 + 1; } } else if (from2 <= to1) { if (to2 < to1) { if (from1 <= from2 - 1) { r = add_code_range_to_buf(pbuf, from1, from2-1); if (r != 0) return r; } from1 = to2 + 1; } else { to1 = from2 - 1; } } else { from1 = from2; } if (from1 > to1) break; } if (from1 <= to1) { r = add_code_range_to_buf(pbuf, from1, to1); if (r != 0) return r; } return 0; } static int and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf) { int r; OnigCodePoint i, j, n1, n2, *data1, *data2; OnigCodePoint from, to, from1, to1, from2, to2; *pbuf = (BBuf* )NULL; if (IS_NULL(bbuf1)) { if (not1 != 0 && IS_NOT_NULL(bbuf2)) /* not1 != 0 -> not2 == 0 */ return bbuf_clone(pbuf, bbuf2); return 0; } else if (IS_NULL(bbuf2)) { if (not2 != 0) return bbuf_clone(pbuf, bbuf1); return 0; } if (not1 != 0) SWAP_BBUF_NOT(bbuf1, not1, bbuf2, not2); data1 = (OnigCodePoint* )(bbuf1->p); data2 = (OnigCodePoint* )(bbuf2->p); GET_CODE_POINT(n1, data1); GET_CODE_POINT(n2, data2); data1++; data2++; if (not2 == 0 && not1 == 0) { /* 1 AND 2 */ for (i = 0; i < n1; i++) { from1 = data1[i*2]; to1 = data1[i*2+1]; for (j = 0; j < n2; j++) { from2 = data2[j*2]; to2 = data2[j*2+1]; if (from2 > to1) break; if (to2 < from1) continue; from = MAX(from1, from2); to = MIN(to1, to2); r = add_code_range_to_buf(pbuf, from, to); if (r != 0) return r; } } } else if (not1 == 0) { /* 1 AND (not 2) */ for (i = 0; i < n1; i++) { from1 = data1[i*2]; to1 = data1[i*2+1]; r = and_code_range1(pbuf, from1, to1, data2, n2); if (r != 0) return r; } } return 0; } static int and_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) { int r, not1, not2; BBuf *buf1, *buf2, *pbuf = 0; BitSetRef bsr1, bsr2; BitSet bs1, bs2; not1 = IS_NCCLASS_NOT(dest); bsr1 = dest->bs; buf1 = dest->mbuf; not2 = IS_NCCLASS_NOT(cc); bsr2 = cc->bs; buf2 = cc->mbuf; if (not1 != 0) { bitset_invert_to(bsr1, bs1); bsr1 = bs1; } if (not2 != 0) { bitset_invert_to(bsr2, bs2); bsr2 = bs2; } bitset_and(bsr1, bsr2); if (bsr1 != dest->bs) { bitset_copy(dest->bs, bsr1); bsr1 = dest->bs; } if (not1 != 0) { bitset_invert(dest->bs); } if (! ONIGENC_IS_SINGLEBYTE(enc)) { if (not1 != 0 && not2 != 0) { r = or_code_range_buf(enc, buf1, 0, buf2, 0, &pbuf); } else { r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf); if (r == 0 && not1 != 0) { BBuf *tbuf = 0; r = not_code_range_buf(enc, pbuf, &tbuf); bbuf_free(pbuf); pbuf = tbuf; } } if (r != 0) { bbuf_free(pbuf); return r; } dest->mbuf = pbuf; bbuf_free(buf1); return r; } return 0; } static int or_cclass(CClassNode* dest, CClassNode* cc, OnigEncoding enc) { int r, not1, not2; BBuf *buf1, *buf2, *pbuf = 0; BitSetRef bsr1, bsr2; BitSet bs1, bs2; not1 = IS_NCCLASS_NOT(dest); bsr1 = dest->bs; buf1 = dest->mbuf; not2 = IS_NCCLASS_NOT(cc); bsr2 = cc->bs; buf2 = cc->mbuf; if (not1 != 0) { bitset_invert_to(bsr1, bs1); bsr1 = bs1; } if (not2 != 0) { bitset_invert_to(bsr2, bs2); bsr2 = bs2; } bitset_or(bsr1, bsr2); if (bsr1 != dest->bs) { bitset_copy(dest->bs, bsr1); bsr1 = dest->bs; } if (not1 != 0) { bitset_invert(dest->bs); } if (! ONIGENC_IS_SINGLEBYTE(enc)) { if (not1 != 0 && not2 != 0) { r = and_code_range_buf(buf1, 0, buf2, 0, &pbuf); } else { r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf); if (r == 0 && not1 != 0) { BBuf *tbuf = 0; r = not_code_range_buf(enc, pbuf, &tbuf); bbuf_free(pbuf); pbuf = tbuf; } } if (r != 0) { bbuf_free(pbuf); return r; } dest->mbuf = pbuf; bbuf_free(buf1); return r; } else return 0; } static int conv_backslash_value(int c, ScanEnv* env) { if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_CONTROL_CHARS)) { switch (c) { case 'n': return '\n'; case 't': return '\t'; case 'r': return '\r'; case 'f': return '\f'; case 'a': return '\007'; case 'b': return '\010'; case 'e': return '\033'; case 'v': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_V_VTAB)) return '\v'; break; default: break; } } return c; } #ifdef USE_NO_INVALID_QUANTIFIER #define is_invalid_quantifier_target(node) 0 #else static int is_invalid_quantifier_target(Node* node) { switch (NTYPE(node)) { case NT_ANCHOR: return 1; break; case NT_ENCLOSE: /* allow enclosed elements */ /* return is_invalid_quantifier_target(NENCLOSE(node)->target); */ break; case NT_LIST: do { if (! is_invalid_quantifier_target(NCAR(node))) return 0; } while (IS_NOT_NULL(node = NCDR(node))); return 0; break; case NT_ALT: do { if (is_invalid_quantifier_target(NCAR(node))) return 1; } while (IS_NOT_NULL(node = NCDR(node))); break; default: break; } return 0; } #endif /* ?:0, *:1, +:2, ??:3, *?:4, +?:5 */ static int popular_quantifier_num(QtfrNode* q) { if (q->greedy) { if (q->lower == 0) { if (q->upper == 1) return 0; else if (IS_REPEAT_INFINITE(q->upper)) return 1; } else if (q->lower == 1) { if (IS_REPEAT_INFINITE(q->upper)) return 2; } } else { if (q->lower == 0) { if (q->upper == 1) return 3; else if (IS_REPEAT_INFINITE(q->upper)) return 4; } else if (q->lower == 1) { if (IS_REPEAT_INFINITE(q->upper)) return 5; } } return -1; } enum ReduceType { RQ_ASIS = 0, /* as is */ RQ_DEL = 1, /* delete parent */ RQ_A, /* to '*' */ RQ_AQ, /* to '*?' */ RQ_QQ, /* to '??' */ RQ_P_QQ, /* to '+)??' */ RQ_PQ_Q /* to '+?)?' */ }; static enum ReduceType const ReduceTypeTable[6][6] = { {RQ_DEL, RQ_A, RQ_A, RQ_QQ, RQ_AQ, RQ_ASIS}, /* '?' */ {RQ_DEL, RQ_DEL, RQ_DEL, RQ_P_QQ, RQ_P_QQ, RQ_DEL}, /* '*' */ {RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */ {RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */ {RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */ {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */ }; extern void onig_reduce_nested_quantifier(Node* pnode, Node* cnode) { int pnum, cnum; QtfrNode *p, *c; p = NQTFR(pnode); c = NQTFR(cnode); pnum = popular_quantifier_num(p); cnum = popular_quantifier_num(c); if (pnum < 0 || cnum < 0) return ; switch (ReduceTypeTable[cnum][pnum]) { case RQ_DEL: *pnode = *cnode; break; case RQ_A: p->target = c->target; p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 1; break; case RQ_AQ: p->target = c->target; p->lower = 0; p->upper = REPEAT_INFINITE; p->greedy = 0; break; case RQ_QQ: p->target = c->target; p->lower = 0; p->upper = 1; p->greedy = 0; break; case RQ_P_QQ: p->target = cnode; p->lower = 0; p->upper = 1; p->greedy = 0; c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1; return ; break; case RQ_PQ_Q: p->target = cnode; p->lower = 0; p->upper = 1; p->greedy = 1; c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0; return ; break; case RQ_ASIS: p->target = cnode; return ; break; } c->target = NULL_NODE; onig_node_free(cnode); } enum TokenSyms { TK_EOT = 0, /* end of token */ TK_RAW_BYTE = 1, TK_CHAR, TK_STRING, TK_CODE_POINT, TK_ANYCHAR, TK_CHAR_TYPE, TK_BACKREF, TK_CALL, TK_ANCHOR, TK_OP_REPEAT, TK_INTERVAL, TK_ANYCHAR_ANYTIME, /* SQL '%' == .* */ TK_ALT, TK_SUBEXP_OPEN, TK_SUBEXP_CLOSE, TK_CC_OPEN, TK_QUOTE_OPEN, TK_CHAR_PROPERTY, /* \p{...}, \P{...} */ TK_LINEBREAK, TK_EXTENDED_GRAPHEME_CLUSTER, TK_KEEP, /* in cc */ TK_CC_CLOSE, TK_CC_RANGE, TK_POSIX_BRACKET_OPEN, TK_CC_AND, /* && */ TK_CC_CC_OPEN /* [ */ }; typedef struct { enum TokenSyms type; int escaped; int base; /* is number: 8, 16 (used in [....]) */ UChar* backp; union { UChar* s; int c; OnigCodePoint code; struct { int subtype; int ascii_range; } anchor; struct { int lower; int upper; int greedy; int possessive; } repeat; struct { int num; int ref1; int* refs; int by_name; #ifdef USE_BACKREF_WITH_LEVEL int exist_level; int level; /* \k */ #endif } backref; struct { UChar* name; UChar* name_end; int gnum; int rel; } call; struct { int ctype; int not; } prop; } u; } OnigToken; static int fetch_range_quantifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env) { int low, up, syn_allow, non_low = 0; int r = 0; OnigCodePoint c; OnigEncoding enc = env->enc; UChar* p = *src; PFETCH_READY; syn_allow = IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INVALID_INTERVAL); if (PEND) { if (syn_allow) return 1; /* "....{" : OK! */ else return ONIGERR_END_PATTERN_AT_LEFT_BRACE; /* "....{" syntax error */ } if (! syn_allow) { c = PPEEK; if (c == ')' || c == '(' || c == '|') { return ONIGERR_END_PATTERN_AT_LEFT_BRACE; } } low = onig_scan_unsigned_number(&p, end, env->enc); if (low < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE; if (low > ONIG_MAX_REPEAT_NUM) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE; if (p == *src) { /* can't read low */ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV)) { /* allow {,n} as {0,n} */ low = 0; non_low = 1; } else goto invalid; } if (PEND) goto invalid; PFETCH(c); if (c == ',') { UChar* prev = p; up = onig_scan_unsigned_number(&p, end, env->enc); if (up < 0) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE; if (up > ONIG_MAX_REPEAT_NUM) return ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE; if (p == prev) { if (non_low != 0) goto invalid; up = REPEAT_INFINITE; /* {n,} : {n,infinite} */ } } else { if (non_low != 0) goto invalid; PUNFETCH; up = low; /* {n} : exact n times */ r = 2; /* fixed */ } if (PEND) goto invalid; PFETCH(c); if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) { if (c != MC_ESC(env->syntax)) goto invalid; PFETCH(c); } if (c != '}') goto invalid; if (!IS_REPEAT_INFINITE(up) && low > up) { return ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE; } tok->type = TK_INTERVAL; tok->u.repeat.lower = low; tok->u.repeat.upper = up; *src = p; return r; /* 0: normal {n,m}, 2: fixed {n} */ invalid: if (syn_allow) return 1; /* OK */ else return ONIGERR_INVALID_REPEAT_RANGE_PATTERN; } /* \M-, \C-, \c, or \... */ static int fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env) { int v; OnigCodePoint c; OnigEncoding enc = env->enc; UChar* p = *src; PFETCH_READY; if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; PFETCH(c); switch (c) { case 'M': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_M_BAR_META)) { if (PEND) return ONIGERR_END_PATTERN_AT_META; PFETCH(c); if (c != '-') return ONIGERR_META_CODE_SYNTAX; if (PEND) return ONIGERR_END_PATTERN_AT_META; PFETCH(c); if (c == MC_ESC(env->syntax)) { v = fetch_escaped_value(&p, end, env); if (v < 0) return v; c = (OnigCodePoint )v; } c = ((c & 0xff) | 0x80); } else goto backslash; break; case 'C': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_CAPITAL_C_BAR_CONTROL)) { if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL; PFETCH(c); if (c != '-') return ONIGERR_CONTROL_CODE_SYNTAX; goto control; } else goto backslash; case 'c': if (IS_SYNTAX_OP(env->syntax, ONIG_SYN_OP_ESC_C_CONTROL)) { control: if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL; PFETCH(c); if (c == '?') { c = 0177; } else { if (c == MC_ESC(env->syntax)) { v = fetch_escaped_value(&p, end, env); if (v < 0) return v; c = (OnigCodePoint )v; } c &= 0x9f; } break; } /* fall through */ default: { backslash: c = conv_backslash_value(c, env); } break; } *src = p; return c; } static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env); static OnigCodePoint get_name_end_code_point(OnigCodePoint start) { switch (start) { case '<': return (OnigCodePoint )'>'; break; case '\'': return (OnigCodePoint )'\''; break; case '(': return (OnigCodePoint )')'; break; case '{': return (OnigCodePoint )'}'; break; default: break; } return (OnigCodePoint )0; } #ifdef USE_NAMED_GROUP #ifdef USE_BACKREF_WITH_LEVEL /* \k, \k \k, \k \k<-num+n>, \k<-num-n> */ static int fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int* rback_num, int* rlevel) { int r, sign, is_num, exist_level; OnigCodePoint end_code; OnigCodePoint c = 0; OnigEncoding enc = env->enc; UChar *name_end; UChar *pnum_head; UChar *p = *src; PFETCH_READY; *rback_num = 0; is_num = exist_level = 0; sign = 1; pnum_head = *src; end_code = get_name_end_code_point(start_code); name_end = end; r = 0; if (PEND) { return ONIGERR_EMPTY_GROUP_NAME; } else { PFETCH(c); if (c == end_code) return ONIGERR_EMPTY_GROUP_NAME; if (ONIGENC_IS_CODE_DIGIT(enc, c)) { is_num = 1; } else if (c == '-') { is_num = 2; sign = -1; pnum_head = p; } else if (!ONIGENC_IS_CODE_WORD(enc, c)) { r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } while (!PEND) { name_end = p; PFETCH(c); if (c == end_code || c == ')' || c == '+' || c == '-') { if (is_num == 2) r = ONIGERR_INVALID_GROUP_NAME; break; } if (is_num != 0) { if (ONIGENC_IS_CODE_DIGIT(enc, c)) { is_num = 1; } else { r = ONIGERR_INVALID_GROUP_NAME; is_num = 0; } } else if (!ONIGENC_IS_CODE_WORD(enc, c)) { r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } if (r == 0 && c != end_code) { if (c == '+' || c == '-') { int level; int flag = (c == '-' ? -1 : 1); PFETCH(c); if (! ONIGENC_IS_CODE_DIGIT(enc, c)) goto err; PUNFETCH; level = onig_scan_unsigned_number(&p, end, enc); if (level < 0) return ONIGERR_TOO_BIG_NUMBER; *rlevel = (level * flag); exist_level = 1; PFETCH(c); if (c == end_code) goto end; } err: r = ONIGERR_INVALID_GROUP_NAME; name_end = end; } end: if (r == 0) { if (is_num != 0) { *rback_num = onig_scan_unsigned_number(&pnum_head, name_end, enc); if (*rback_num < 0) return ONIGERR_TOO_BIG_NUMBER; else if (*rback_num == 0) goto err; *rback_num *= sign; } *rname_end = name_end; *src = p; return (exist_level ? 1 : 0); } else { onig_scan_env_set_error_string(env, r, *src, name_end); return r; } } #endif /* USE_BACKREF_WITH_LEVEL */ /* ref: 0 -> define name (don't allow number name) 1 -> reference name (allow number name) */ static int fetch_name(OnigCodePoint start_code, UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int* rback_num, int ref) { int r, is_num, sign; OnigCodePoint end_code; OnigCodePoint c = 0; OnigEncoding enc = env->enc; UChar *name_end; UChar *pnum_head; UChar *p = *src; PFETCH_READY; *rback_num = 0; end_code = get_name_end_code_point(start_code); name_end = end; pnum_head = *src; r = 0; is_num = 0; sign = 1; if (PEND) { return ONIGERR_EMPTY_GROUP_NAME; } else { PFETCH(c); if (c == end_code) return ONIGERR_EMPTY_GROUP_NAME; if (ONIGENC_IS_CODE_DIGIT(enc, c)) { if (ref == 1) is_num = 1; else { r = ONIGERR_INVALID_GROUP_NAME; is_num = 0; } } else if (c == '-') { if (ref == 1) { is_num = 2; sign = -1; pnum_head = p; } else { r = ONIGERR_INVALID_GROUP_NAME; is_num = 0; } } else if (!ONIGENC_IS_CODE_WORD(enc, c)) { r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } if (r == 0) { while (!PEND) { name_end = p; PFETCH(c); if (c == end_code || c == ')') { if (is_num == 2) r = ONIGERR_INVALID_GROUP_NAME; break; } if (is_num != 0) { if (ONIGENC_IS_CODE_DIGIT(enc, c)) { is_num = 1; } else { if (!ONIGENC_IS_CODE_WORD(enc, c)) r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; else r = ONIGERR_INVALID_GROUP_NAME; is_num = 0; } } else { if (!ONIGENC_IS_CODE_WORD(enc, c)) { r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } } if (c != end_code) { r = ONIGERR_INVALID_GROUP_NAME; name_end = end; } if (is_num != 0) { *rback_num = onig_scan_unsigned_number(&pnum_head, name_end, enc); if (*rback_num < 0) return ONIGERR_TOO_BIG_NUMBER; else if (*rback_num == 0) { r = ONIGERR_INVALID_GROUP_NAME; goto err; } *rback_num *= sign; } *rname_end = name_end; *src = p; return 0; } else { while (!PEND) { name_end = p; PFETCH(c); if (c == end_code || c == ')') break; } if (PEND) name_end = end; err: onig_scan_env_set_error_string(env, r, *src, name_end); return r; } } #else static int fetch_name(OnigCodePoint start_code, UChar** src, UChar* end, UChar** rname_end, ScanEnv* env, int* rback_num, int ref) { int r, is_num, sign; OnigCodePoint end_code; OnigCodePoint c = 0; UChar *name_end; OnigEncoding enc = env->enc; UChar *pnum_head; UChar *p = *src; PFETCH_READY; *rback_num = 0; end_code = get_name_end_code_point(start_code); *rname_end = name_end = end; r = 0; pnum_head = *src; is_num = 0; sign = 1; if (PEND) { return ONIGERR_EMPTY_GROUP_NAME; } else { PFETCH(c); if (c == end_code) return ONIGERR_EMPTY_GROUP_NAME; if (ONIGENC_IS_CODE_DIGIT(enc, c)) { is_num = 1; } else if (c == '-') { is_num = 2; sign = -1; pnum_head = p; } else { r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } } while (!PEND) { name_end = p; PFETCH(c); if (c == end_code || c == ')') break; if (! ONIGENC_IS_CODE_DIGIT(enc, c)) r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME; } if (r == 0 && c != end_code) { r = ONIGERR_INVALID_GROUP_NAME; name_end = end; } if (r == 0) { *rback_num = onig_scan_unsigned_number(&pnum_head, name_end, enc); if (*rback_num < 0) return ONIGERR_TOO_BIG_NUMBER; else if (*rback_num == 0) { r = ONIGERR_INVALID_GROUP_NAME; goto err; } *rback_num *= sign; *rname_end = name_end; *src = p; return 0; } else { err: onig_scan_env_set_error_string(env, r, *src, name_end); return r; } } #endif /* USE_NAMED_GROUP */ static void CC_ESC_WARN(ScanEnv* env, UChar *c) { if (onig_warn == onig_null_warn) return ; if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED) && IS_SYNTAX_BV(env->syntax, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) { UChar buf[WARN_BUFSIZE]; onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, env->pattern, env->pattern_end, (UChar* )"character class has '%s' without escape", c); (*onig_warn)((char* )buf); } } static void CLOSE_BRACKET_WITHOUT_ESC_WARN(ScanEnv* env, UChar* c) { if (onig_warn == onig_null_warn) return ; if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_CC_OP_NOT_ESCAPED)) { UChar buf[WARN_BUFSIZE]; onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, env->pattern, env->pattern_end, (UChar* )"regular expression has '%s' without escape", c); (*onig_warn)((char* )buf); } } static UChar* find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to, UChar **next, OnigEncoding enc) { int i; OnigCodePoint x; UChar *q; UChar *p = from; while (p < to) { x = ONIGENC_MBC_TO_CODE(enc, p, to); q = p + enclen(enc, p); if (x == s[0]) { for (i = 1; i < n && q < to; i++) { x = ONIGENC_MBC_TO_CODE(enc, q, to); if (x != s[i]) break; q += enclen(enc, q); } if (i >= n) { if (IS_NOT_NULL(next)) *next = q; return p; } } p = q; } return NULL_UCHARP; } static int str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to, OnigCodePoint bad, OnigEncoding enc, OnigSyntaxType* syn) { int i, in_esc; OnigCodePoint x; UChar *q; UChar *p = from; in_esc = 0; while (p < to) { if (in_esc) { in_esc = 0; p += enclen(enc, p); } else { x = ONIGENC_MBC_TO_CODE(enc, p, to); q = p + enclen(enc, p); if (x == s[0]) { for (i = 1; i < n && q < to; i++) { x = ONIGENC_MBC_TO_CODE(enc, q, to); if (x != s[i]) break; q += enclen(enc, q); } if (i >= n) return 1; p += enclen(enc, p); } else { x = ONIGENC_MBC_TO_CODE(enc, p, to); if (x == bad) return 0; else if (x == MC_ESC(syn)) in_esc = 1; p = q; } } } return 0; } static int fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { int num; OnigCodePoint c, c2; OnigSyntaxType* syn = env->syntax; OnigEncoding enc = env->enc; UChar* prev; UChar* p = *src; PFETCH_READY; if (PEND) { tok->type = TK_EOT; return tok->type; } PFETCH(c); tok->type = TK_CHAR; tok->base = 0; tok->u.c = c; tok->escaped = 0; if (c == ']') { tok->type = TK_CC_CLOSE; } else if (c == '-') { tok->type = TK_CC_RANGE; } else if (c == MC_ESC(syn)) { if (! IS_SYNTAX_BV(syn, ONIG_SYN_BACKSLASH_ESCAPE_IN_CC)) goto end; if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; PFETCH(c); tok->escaped = 1; tok->u.c = c; switch (c) { case 'w': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_WORD; tok->u.prop.not = 0; break; case 'W': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_WORD; tok->u.prop.not = 1; break; case 'd': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_DIGIT; tok->u.prop.not = 0; break; case 'D': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_DIGIT; tok->u.prop.not = 1; break; case 's': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_SPACE; tok->u.prop.not = 0; break; case 'S': tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_SPACE; tok->u.prop.not = 1; break; case 'h': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_XDIGIT; tok->u.prop.not = 0; break; case 'H': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_XDIGIT; tok->u.prop.not = 1; break; case 'p': case 'P': c2 = PPEEK; if (c2 == '{' && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) { PINC; tok->type = TK_CHAR_PROPERTY; tok->u.prop.not = (c == 'P' ? 1 : 0); if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) { PFETCH(c2); if (c2 == '^') { tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0); } else PUNFETCH; } } break; case 'x': if (PEND) break; prev = p; if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { PINC; num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc); if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; if (!PEND) { c2 = PPEEK; if (ONIGENC_IS_CODE_XDIGIT(enc, c2)) return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; } if (p > prev + enclen(enc, prev) && !PEND && (PPEEK_IS('}'))) { PINC; tok->type = TK_CODE_POINT; tok->base = 16; tok->u.code = (OnigCodePoint )num; } else { /* can't read nothing or invalid format */ p = prev; } } else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) { num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_RAW_BYTE; tok->base = 16; tok->u.c = num; } break; case 'u': if (PEND) break; prev = p; if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) { num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc); if (num < -1) return ONIGERR_TOO_SHORT_DIGITS; else if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_CODE_POINT; tok->base = 16; tok->u.code = (OnigCodePoint )num; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) { PUNFETCH; prev = p; num = scan_unsigned_octal_number(&p, end, 3, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_RAW_BYTE; tok->base = 8; tok->u.c = num; } break; default: PUNFETCH; num = fetch_escaped_value(&p, end, env); if (num < 0) return num; if (tok->u.c != num) { tok->u.code = (OnigCodePoint )num; tok->type = TK_CODE_POINT; } break; } } else if (c == '[') { if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_POSIX_BRACKET) && (PPEEK_IS(':'))) { OnigCodePoint send[] = { (OnigCodePoint )':', (OnigCodePoint )']' }; tok->backp = p; /* point at '[' is read */ PINC; if (str_exist_check_with_esc(send, 2, p, end, (OnigCodePoint )']', enc, syn)) { tok->type = TK_POSIX_BRACKET_OPEN; } else { PUNFETCH; goto cc_in_cc; } } else { cc_in_cc: if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP)) { tok->type = TK_CC_CC_OPEN; } else { CC_ESC_WARN(env, (UChar* )"["); } } } else if (c == '&') { if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP) && !PEND && (PPEEK_IS('&'))) { PINC; tok->type = TK_CC_AND; } } end: *src = p; return tok->type; } #ifdef USE_NAMED_GROUP static int fetch_named_backref_token(OnigCodePoint c, OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { int r, num; OnigSyntaxType* syn = env->syntax; UChar* prev; UChar* p = *src; UChar* name_end; int* backs; int back_num; prev = p; #ifdef USE_BACKREF_WITH_LEVEL name_end = NULL_UCHARP; /* no need. escape gcc warning. */ r = fetch_name_with_level(c, &p, end, &name_end, env, &back_num, &tok->u.backref.level); if (r == 1) tok->u.backref.exist_level = 1; else tok->u.backref.exist_level = 0; #else r = fetch_name(&p, end, &name_end, env, &back_num, 1); #endif if (r < 0) return r; if (back_num != 0) { if (back_num < 0) { back_num = BACKREF_REL_TO_ABS(back_num, env); if (back_num <= 0) return ONIGERR_INVALID_BACKREF; } if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) { if (back_num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[back_num])) return ONIGERR_INVALID_BACKREF; } tok->type = TK_BACKREF; tok->u.backref.by_name = 0; tok->u.backref.num = 1; tok->u.backref.ref1 = back_num; } else { num = onig_name_to_group_numbers(env->reg, prev, name_end, &backs); if (num <= 0) { onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end); return ONIGERR_UNDEFINED_NAME_REFERENCE; } if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) { int i; for (i = 0; i < num; i++) { if (backs[i] > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[backs[i]])) return ONIGERR_INVALID_BACKREF; } } tok->type = TK_BACKREF; tok->u.backref.by_name = 1; if (num == 1) { tok->u.backref.num = 1; tok->u.backref.ref1 = backs[0]; } else { tok->u.backref.num = num; tok->u.backref.refs = backs; } } *src = p; return 0; } #endif static int fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { int r, num; OnigCodePoint c; OnigEncoding enc = env->enc; OnigSyntaxType* syn = env->syntax; UChar* prev; UChar* p = *src; PFETCH_READY; start: if (PEND) { tok->type = TK_EOT; return tok->type; } tok->type = TK_STRING; tok->base = 0; tok->backp = p; PFETCH(c); if (IS_MC_ESC_CODE(c, syn)) { if (PEND) return ONIGERR_END_PATTERN_AT_ESCAPE; tok->backp = p; PFETCH(c); tok->u.c = c; tok->escaped = 1; switch (c) { case '*': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_ASTERISK_ZERO_INF)) break; tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 0; tok->u.repeat.upper = REPEAT_INFINITE; goto greedy_check; break; case '+': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_PLUS_ONE_INF)) break; tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 1; tok->u.repeat.upper = REPEAT_INFINITE; goto greedy_check; break; case '?': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_QMARK_ZERO_ONE)) break; tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 0; tok->u.repeat.upper = 1; greedy_check: if (!PEND && PPEEK_IS('?') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) { PFETCH(c); tok->u.repeat.greedy = 0; tok->u.repeat.possessive = 0; } else { possessive_check: if (!PEND && PPEEK_IS('+') && ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) && tok->type != TK_INTERVAL) || (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) && tok->type == TK_INTERVAL))) { PFETCH(c); tok->u.repeat.greedy = 1; tok->u.repeat.possessive = 1; } else { tok->u.repeat.greedy = 1; tok->u.repeat.possessive = 0; } } break; case '{': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_BRACE_INTERVAL)) break; r = fetch_range_quantifier(&p, end, tok, env); if (r < 0) return r; /* error */ if (r == 0) goto greedy_check; else if (r == 2) { /* {n} */ if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY)) goto possessive_check; goto greedy_check; } /* r == 1 : normal char */ break; case '|': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_VBAR_ALT)) break; tok->type = TK_ALT; break; case '(': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break; tok->type = TK_SUBEXP_OPEN; break; case ')': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LPAREN_SUBEXP)) break; tok->type = TK_SUBEXP_CLOSE; break; case 'w': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_WORD; tok->u.prop.not = 0; break; case 'W': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_W_WORD)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_WORD; tok->u.prop.not = 1; break; case 'b': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_WORD_BOUND; tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option) && ! IS_WORD_BOUND_ALL_RANGE(env->option); break; case 'B': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_B_WORD_BOUND)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_NOT_WORD_BOUND; tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option) && ! IS_WORD_BOUND_ALL_RANGE(env->option); break; #ifdef USE_WORD_BEGIN_END case '<': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_WORD_BEGIN; tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option); break; case '>': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_WORD_END; tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option); break; #endif case 's': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_SPACE; tok->u.prop.not = 0; break; case 'S': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_S_WHITE_SPACE)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_SPACE; tok->u.prop.not = 1; break; case 'd': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_DIGIT; tok->u.prop.not = 0; break; case 'D': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_D_DIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_DIGIT; tok->u.prop.not = 1; break; case 'h': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_XDIGIT; tok->u.prop.not = 0; break; case 'H': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_H_XDIGIT)) break; tok->type = TK_CHAR_TYPE; tok->u.prop.ctype = ONIGENC_CTYPE_XDIGIT; tok->u.prop.not = 1; break; case 'A': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break; begin_buf: tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_BEGIN_BUF; break; case 'Z': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_SEMI_END_BUF; break; case 'z': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_AZ_BUF_ANCHOR)) break; end_buf: tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_END_BUF; break; case 'G': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_CAPITAL_G_BEGIN_ANCHOR)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = ANCHOR_BEGIN_POSITION; break; case '`': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break; goto begin_buf; break; case '\'': if (! IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR)) break; goto end_buf; break; case 'x': if (PEND) break; prev = p; if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) { PINC; num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc); if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE; if (!PEND) { if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK)) return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE; } if ((p > prev + enclen(enc, prev)) && !PEND && PPEEK_IS('}')) { PINC; tok->type = TK_CODE_POINT; tok->u.code = (OnigCodePoint )num; } else { /* can't read nothing or invalid format */ p = prev; } } else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) { num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_RAW_BYTE; tok->base = 16; tok->u.c = num; } break; case 'u': if (PEND) break; prev = p; if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) { num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc); if (num < -1) return ONIGERR_TOO_SHORT_DIGITS; else if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_CODE_POINT; tok->base = 16; tok->u.code = (OnigCodePoint )num; } break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': PUNFETCH; prev = p; num = onig_scan_unsigned_number(&p, end, enc); if (num < 0 || num > ONIG_MAX_BACKREF_NUM) { goto skip_backref; } if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_DECIMAL_BACKREF) && (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */ if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) { if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num])) return ONIGERR_INVALID_BACKREF; } tok->type = TK_BACKREF; tok->u.backref.num = 1; tok->u.backref.ref1 = num; tok->u.backref.by_name = 0; #ifdef USE_BACKREF_WITH_LEVEL tok->u.backref.exist_level = 0; #endif break; } skip_backref: if (c == '8' || c == '9') { /* normal char */ p = prev; PINC; break; } p = prev; /* fall through */ case '0': if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) { prev = p; num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc); if (num < 0) return ONIGERR_TOO_BIG_NUMBER; if (p == prev) { /* can't read nothing. */ num = 0; /* but, it's not error */ } tok->type = TK_RAW_BYTE; tok->base = 8; tok->u.c = num; } else if (c != '0') { PINC; } break; #ifdef USE_NAMED_GROUP case 'k': if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) { PFETCH(c); if (c == '<' || c == '\'') { r = fetch_named_backref_token(c, tok, &p, end, env); if (r < 0) return r; } else PUNFETCH; } break; #endif #if defined(USE_SUBEXP_CALL) || defined(USE_NAMED_GROUP) case 'g': #ifdef USE_NAMED_GROUP if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_BRACE_BACKREF)) { PFETCH(c); if (c == '{') { r = fetch_named_backref_token(c, tok, &p, end, env); if (r < 0) return r; } else PUNFETCH; } #endif #ifdef USE_SUBEXP_CALL if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) { PFETCH(c); if (c == '<' || c == '\'') { int gnum = -1, rel = 0; UChar* name_end; OnigCodePoint cnext; cnext = PPEEK; if (cnext == '0') { PINC; if (PPEEK_IS(get_name_end_code_point(c))) { /* \g<0>, \g'0' */ PINC; name_end = p; gnum = 0; } } else if (cnext == '+') { PINC; rel = 1; } prev = p; if (gnum < 0) { r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &gnum, 1); if (r < 0) return r; } tok->type = TK_CALL; tok->u.call.name = prev; tok->u.call.name_end = name_end; tok->u.call.gnum = gnum; tok->u.call.rel = rel; } else PUNFETCH; } #endif break; #endif case 'Q': if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE)) { tok->type = TK_QUOTE_OPEN; } break; case 'p': case 'P': if (PPEEK_IS('{') && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) { PINC; tok->type = TK_CHAR_PROPERTY; tok->u.prop.not = (c == 'P' ? 1 : 0); if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) { PFETCH(c); if (c == '^') { tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0); } else PUNFETCH; } } break; case 'R': if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK)) { tok->type = TK_LINEBREAK; } break; case 'X': if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER)) { tok->type = TK_EXTENDED_GRAPHEME_CLUSTER; } break; case 'K': if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP)) { tok->type = TK_KEEP; } break; default: PUNFETCH; num = fetch_escaped_value(&p, end, env); if (num < 0) return num; /* set_raw: */ if (tok->u.c != num) { tok->type = TK_CODE_POINT; tok->u.code = (OnigCodePoint )num; } else { /* string */ p = tok->backp + enclen(enc, tok->backp); } break; } } else { tok->u.c = c; tok->escaped = 0; #ifdef USE_VARIABLE_META_CHARS if ((c != ONIG_INEFFECTIVE_META_CHAR) && IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) { if (c == MC_ANYCHAR(syn)) goto any_char; else if (c == MC_ANYTIME(syn)) goto anytime; else if (c == MC_ZERO_OR_ONE_TIME(syn)) goto zero_or_one_time; else if (c == MC_ONE_OR_MORE_TIME(syn)) goto one_or_more_time; else if (c == MC_ANYCHAR_ANYTIME(syn)) { tok->type = TK_ANYCHAR_ANYTIME; goto out; } } #endif switch (c) { case '.': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_DOT_ANYCHAR)) break; #ifdef USE_VARIABLE_META_CHARS any_char: #endif tok->type = TK_ANYCHAR; break; case '*': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_ASTERISK_ZERO_INF)) break; #ifdef USE_VARIABLE_META_CHARS anytime: #endif tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 0; tok->u.repeat.upper = REPEAT_INFINITE; goto greedy_check; break; case '+': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_PLUS_ONE_INF)) break; #ifdef USE_VARIABLE_META_CHARS one_or_more_time: #endif tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 1; tok->u.repeat.upper = REPEAT_INFINITE; goto greedy_check; break; case '?': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_ZERO_ONE)) break; #ifdef USE_VARIABLE_META_CHARS zero_or_one_time: #endif tok->type = TK_OP_REPEAT; tok->u.repeat.lower = 0; tok->u.repeat.upper = 1; goto greedy_check; break; case '{': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACE_INTERVAL)) break; r = fetch_range_quantifier(&p, end, tok, env); if (r < 0) return r; /* error */ if (r == 0) goto greedy_check; else if (r == 2) { /* {n} */ if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY)) goto possessive_check; goto greedy_check; } /* r == 1 : normal char */ break; case '|': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_VBAR_ALT)) break; tok->type = TK_ALT; break; case '(': if (PPEEK_IS('?') && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) { PINC; if (PPEEK_IS('#')) { PFETCH(c); while (1) { if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; PFETCH(c); if (c == MC_ESC(syn)) { if (!PEND) PFETCH(c); } else { if (c == ')') break; } } goto start; } #ifdef USE_PERL_SUBEXP_CALL /* (?&name), (?n), (?R), (?0), (?+n), (?-n) */ c = PPEEK; if ((c == '&' || c == 'R' || ONIGENC_IS_CODE_DIGIT(enc, c)) && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) { /* (?&name), (?n), (?R), (?0) */ int gnum; UChar *name; UChar *name_end; if (c == 'R' || c == '0') { PINC; /* skip 'R' / '0' */ if (!PPEEK_IS(')')) return ONIGERR_INVALID_GROUP_NAME; PINC; /* skip ')' */ name_end = name = p; gnum = 0; } else { int numref = 1; if (c == '&') { /* (?&name) */ PINC; numref = 0; /* don't allow number name */ } name = p; r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, numref); if (r < 0) return r; } tok->type = TK_CALL; tok->u.call.name = name; tok->u.call.name_end = name_end; tok->u.call.gnum = gnum; tok->u.call.rel = 0; break; } else if ((c == '-' || c == '+') && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) { /* (?+n), (?-n) */ int gnum; UChar *name; UChar *name_end; OnigCodePoint cnext; PFETCH_READY; PINC; /* skip '-' / '+' */ cnext = PPEEK; if (ONIGENC_IS_CODE_DIGIT(enc, cnext)) { if (c == '-') PUNFETCH; name = p; r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 1); if (r < 0) return r; tok->type = TK_CALL; tok->u.call.name = name; tok->u.call.name_end = name_end; tok->u.call.gnum = gnum; tok->u.call.rel = 1; break; } } #endif /* USE_PERL_SUBEXP_CALL */ #ifdef USE_CAPITAL_P_NAMED_GROUP if (PPEEK_IS('P') && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) { int gnum; UChar *name; UChar *name_end; PFETCH_READY; PINC; /* skip 'P' */ PFETCH(c); if (c == '=') { /* (?P=name): backref */ r = fetch_named_backref_token((OnigCodePoint )'(', tok, &p, end, env); if (r < 0) return r; break; } else if (c == '>') { /* (?P>name): subexp call */ name = p; r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 0); if (r < 0) return r; tok->type = TK_CALL; tok->u.call.name = name; tok->u.call.name_end = name_end; tok->u.call.gnum = gnum; tok->u.call.rel = 0; break; } PUNFETCH; } #endif /* USE_CAPITAL_P_NAMED_GROUP */ PUNFETCH; } if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break; tok->type = TK_SUBEXP_OPEN; break; case ')': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break; tok->type = TK_SUBEXP_CLOSE; break; case '^': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = (IS_SINGLELINE(env->option) ? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE); break; case '$': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break; tok->type = TK_ANCHOR; tok->u.anchor.subtype = (IS_SINGLELINE(env->option) ? ANCHOR_SEMI_END_BUF : ANCHOR_END_LINE); break; case '[': if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_BRACKET_CC)) break; tok->type = TK_CC_OPEN; break; case ']': if (*src > env->pattern) /* /].../ is allowed. */ CLOSE_BRACKET_WITHOUT_ESC_WARN(env, (UChar* )"]"); break; case '#': if (IS_EXTEND(env->option)) { while (!PEND) { PFETCH(c); if (ONIGENC_IS_CODE_NEWLINE(enc, c)) break; } goto start; break; } break; case ' ': case '\t': case '\n': case '\r': case '\f': if (IS_EXTEND(env->option)) goto start; break; default: /* string */ break; } } #ifdef USE_VARIABLE_META_CHARS out: #endif *src = p; return tok->type; } static int add_ctype_to_cc_by_range(CClassNode* cc, int ctype ARG_UNUSED, int not, OnigEncoding enc ARG_UNUSED, OnigCodePoint sb_out, const OnigCodePoint mbr[]) { int i, r; OnigCodePoint j; int n = ONIGENC_CODE_RANGE_NUM(mbr); if (not == 0) { for (i = 0; i < n; i++) { for (j = ONIGENC_CODE_RANGE_FROM(mbr, i); j <= ONIGENC_CODE_RANGE_TO(mbr, i); j++) { if (j >= sb_out) { if (j > ONIGENC_CODE_RANGE_FROM(mbr, i)) { r = add_code_range_to_buf(&(cc->mbuf), j, ONIGENC_CODE_RANGE_TO(mbr, i)); if (r != 0) return r; i++; } goto sb_end; } BITSET_SET_BIT(cc->bs, j); } } sb_end: for ( ; i < n; i++) { r = add_code_range_to_buf(&(cc->mbuf), ONIGENC_CODE_RANGE_FROM(mbr, i), ONIGENC_CODE_RANGE_TO(mbr, i)); if (r != 0) return r; } } else { OnigCodePoint prev = 0; for (i = 0; i < n; i++) { for (j = prev; j < ONIGENC_CODE_RANGE_FROM(mbr, i); j++) { if (j >= sb_out) { goto sb_end2; } BITSET_SET_BIT(cc->bs, j); } prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1; } for (j = prev; j < sb_out; j++) { BITSET_SET_BIT(cc->bs, j); } sb_end2: prev = sb_out; for (i = 0; i < n; i++) { if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) { r = add_code_range_to_buf(&(cc->mbuf), prev, ONIGENC_CODE_RANGE_FROM(mbr, i) - 1); if (r != 0) return r; } prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1; } if (prev < 0x7fffffff) { r = add_code_range_to_buf(&(cc->mbuf), prev, 0x7fffffff); if (r != 0) return r; } } return 0; } static int add_ctype_to_cc(CClassNode* cc, int ctype, int not, int char_prop, ScanEnv* env) { int maxcode, ascii_range; int c, r; const OnigCodePoint *ranges; OnigCodePoint sb_out; OnigEncoding enc = env->enc; OnigOptionType option = env->option; ascii_range = IS_ASCII_RANGE(option) && (char_prop == 0); r = ONIGENC_GET_CTYPE_CODE_RANGE(enc, ctype, &sb_out, &ranges); if (r == 0) { if (ascii_range) { CClassNode ccwork; initialize_cclass(&ccwork); r = add_ctype_to_cc_by_range(&ccwork, ctype, not, env->enc, sb_out, ranges); if (r == 0) { if (not) { r = add_code_range_to_buf(&(ccwork.mbuf), 0x80, ONIG_LAST_CODE_POINT); } else { CClassNode ccascii; initialize_cclass(&ccascii); if (ONIGENC_MBC_MINLEN(env->enc) > 1) { add_code_range(&(ccascii.mbuf), env, 0x00, 0x7F); } else { bitset_set_range(ccascii.bs, 0x00, 0x7F); } r = and_cclass(&ccwork, &ccascii, enc); if (IS_NOT_NULL(ccascii.mbuf)) bbuf_free(ccascii.mbuf); } if (r == 0) { r = or_cclass(cc, &ccwork, enc); } if (IS_NOT_NULL(ccwork.mbuf)) bbuf_free(ccwork.mbuf); } } else { r = add_ctype_to_cc_by_range(cc, ctype, not, env->enc, sb_out, ranges); } return r; } else if (r != ONIG_NO_SUPPORT_CONFIG) { return r; } maxcode = ascii_range ? 0x80 : SINGLE_BYTE_SIZE; r = 0; switch (ctype) { case ONIGENC_CTYPE_ALPHA: case ONIGENC_CTYPE_BLANK: case ONIGENC_CTYPE_CNTRL: case ONIGENC_CTYPE_DIGIT: case ONIGENC_CTYPE_LOWER: case ONIGENC_CTYPE_PUNCT: case ONIGENC_CTYPE_SPACE: case ONIGENC_CTYPE_UPPER: case ONIGENC_CTYPE_XDIGIT: case ONIGENC_CTYPE_ASCII: case ONIGENC_CTYPE_ALNUM: if (not != 0) { for (c = 0; c < SINGLE_BYTE_SIZE; c++) { if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)) BITSET_SET_BIT(cc->bs, c); } ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf); } else { for (c = 0; c < SINGLE_BYTE_SIZE; c++) { if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)) BITSET_SET_BIT(cc->bs, c); } } break; case ONIGENC_CTYPE_GRAPH: case ONIGENC_CTYPE_PRINT: if (not != 0) { for (c = 0; c < SINGLE_BYTE_SIZE; c++) { if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype) || c >= maxcode) BITSET_SET_BIT(cc->bs, c); } if (ascii_range) ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf); } else { for (c = 0; c < maxcode; c++) { if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)) BITSET_SET_BIT(cc->bs, c); } if (! ascii_range) ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf); } break; case ONIGENC_CTYPE_WORD: if (not == 0) { for (c = 0; c < maxcode; c++) { if (ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT(cc->bs, c); } if (! ascii_range) ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf); } else { for (c = 0; c < SINGLE_BYTE_SIZE; c++) { if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* check invalid code point */ && (! ONIGENC_IS_CODE_WORD(enc, c) || c >= maxcode)) BITSET_SET_BIT(cc->bs, c); } if (ascii_range) ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf); } break; default: return ONIGERR_PARSER_BUG; break; } return r; } static int parse_posix_bracket(CClassNode* cc, UChar** src, UChar* end, ScanEnv* env) { #define POSIX_BRACKET_CHECK_LIMIT_LENGTH 20 #define POSIX_BRACKET_NAME_MIN_LEN 4 static const PosixBracketEntryType PBS[] = { { (UChar* )"alnum", ONIGENC_CTYPE_ALNUM, 5 }, { (UChar* )"alpha", ONIGENC_CTYPE_ALPHA, 5 }, { (UChar* )"blank", ONIGENC_CTYPE_BLANK, 5 }, { (UChar* )"cntrl", ONIGENC_CTYPE_CNTRL, 5 }, { (UChar* )"digit", ONIGENC_CTYPE_DIGIT, 5 }, { (UChar* )"graph", ONIGENC_CTYPE_GRAPH, 5 }, { (UChar* )"lower", ONIGENC_CTYPE_LOWER, 5 }, { (UChar* )"print", ONIGENC_CTYPE_PRINT, 5 }, { (UChar* )"punct", ONIGENC_CTYPE_PUNCT, 5 }, { (UChar* )"space", ONIGENC_CTYPE_SPACE, 5 }, { (UChar* )"upper", ONIGENC_CTYPE_UPPER, 5 }, { (UChar* )"xdigit", ONIGENC_CTYPE_XDIGIT, 6 }, { (UChar* )"ascii", ONIGENC_CTYPE_ASCII, 5 }, { (UChar* )"word", ONIGENC_CTYPE_WORD, 4 }, { (UChar* )NULL, -1, 0 } }; const PosixBracketEntryType *pb; int not, i, r; OnigCodePoint c; OnigEncoding enc = env->enc; UChar *p = *src; PFETCH_READY; if (PPEEK_IS('^')) { PINC; not = 1; } else not = 0; if (onigenc_strlen(enc, p, end) < POSIX_BRACKET_NAME_MIN_LEN + 3) goto not_posix_bracket; for (pb = PBS; IS_NOT_NULL(pb->name); pb++) { if (onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) { p = (UChar* )onigenc_step(enc, p, end, pb->len); if (onigenc_with_ascii_strncmp(enc, p, end, (UChar* )":]", 2) != 0) return ONIGERR_INVALID_POSIX_BRACKET_TYPE; r = add_ctype_to_cc(cc, pb->ctype, not, IS_POSIX_BRACKET_ALL_RANGE(env->option), env); if (r != 0) return r; PINC; PINC; *src = p; return 0; } } not_posix_bracket: c = 0; i = 0; while (!PEND && ((c = PPEEK) != ':') && c != ']') { PINC; if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break; } if (c == ':' && ! PEND) { PINC; if (! PEND) { PFETCH(c); if (c == ']') return ONIGERR_INVALID_POSIX_BRACKET_TYPE; } } return 1; /* 1: is not POSIX bracket, but no error. */ } static int fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env) { int r; OnigCodePoint c; OnigEncoding enc = env->enc; UChar *prev, *start, *p = *src; PFETCH_READY; r = 0; start = prev = p; while (!PEND) { prev = p; PFETCH(c); if (c == '}') { r = ONIGENC_PROPERTY_NAME_TO_CTYPE(enc, start, prev); if (r < 0) break; *src = p; return r; } else if (c == '(' || c == ')' || c == '{' || c == '|') { r = ONIGERR_INVALID_CHAR_PROPERTY_NAME; break; } } onig_scan_env_set_error_string(env, r, *src, prev); return r; } static int parse_char_property(Node** np, OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { int r, ctype; CClassNode* cc; ctype = fetch_char_property_to_ctype(src, end, env); if (ctype < 0) return ctype; *np = node_new_cclass(); CHECK_NULL_RETURN_MEMERR(*np); cc = NCCLASS(*np); r = add_ctype_to_cc(cc, ctype, 0, 1, env); if (r != 0) return r; if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc); return 0; } enum CCSTATE { CCS_VALUE, CCS_RANGE, CCS_COMPLETE, CCS_START }; enum CCVALTYPE { CCV_SB, CCV_CODE_POINT, CCV_CLASS }; static int next_state_class(CClassNode* cc, OnigCodePoint* vs, enum CCVALTYPE* type, enum CCSTATE* state, ScanEnv* env) { int r; if (*state == CCS_RANGE) return ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE; if (*state == CCS_VALUE && *type != CCV_CLASS) { if (*type == CCV_SB) BITSET_SET_BIT(cc->bs, (int )(*vs)); else if (*type == CCV_CODE_POINT) { r = add_code_range(&(cc->mbuf), env, *vs, *vs); if (r < 0) return r; } } *state = CCS_VALUE; *type = CCV_CLASS; return 0; } static int next_state_val(CClassNode* cc, OnigCodePoint *vs, OnigCodePoint v, int* vs_israw, int v_israw, enum CCVALTYPE intype, enum CCVALTYPE* type, enum CCSTATE* state, ScanEnv* env) { int r; switch (*state) { case CCS_VALUE: if (*type == CCV_SB) BITSET_SET_BIT(cc->bs, (int )(*vs)); else if (*type == CCV_CODE_POINT) { r = add_code_range(&(cc->mbuf), env, *vs, *vs); if (r < 0) return r; } break; case CCS_RANGE: if (intype == *type) { if (intype == CCV_SB) { if (*vs > 0xff || v > 0xff) return ONIGERR_INVALID_CODE_POINT_VALUE; if (*vs > v) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC)) goto ccs_range_end; else return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS; } bitset_set_range(cc->bs, (int )*vs, (int )v); } else { r = add_code_range(&(cc->mbuf), env, *vs, v); if (r < 0) return r; } } else { #if 0 if (intype == CCV_CODE_POINT && *type == CCV_SB) { #endif if (*vs > v) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC)) goto ccs_range_end; else return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS; } bitset_set_range(cc->bs, (int )*vs, (int )(v < 0xff ? v : 0xff)); r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*vs, v); if (r < 0) return r; #if 0 } else return ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE; #endif } ccs_range_end: *state = CCS_COMPLETE; break; case CCS_COMPLETE: case CCS_START: *state = CCS_VALUE; break; default: break; } *vs_israw = v_israw; *vs = v; *type = intype; return 0; } static int code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped, ScanEnv* env) { int in_esc; OnigCodePoint code; OnigEncoding enc = env->enc; UChar* p = from; PFETCH_READY; in_esc = 0; while (! PEND) { if (ignore_escaped && in_esc) { in_esc = 0; } else { PFETCH(code); if (code == c) return 1; if (code == MC_ESC(env->syntax)) in_esc = 1; } } return 0; } static int parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end, ScanEnv* env) { int r, neg, len, fetched, and_start; OnigCodePoint v, vs; UChar *p; Node* node; CClassNode *cc, *prev_cc; CClassNode work_cc; enum CCSTATE state; enum CCVALTYPE val_type, in_type; int val_israw, in_israw; prev_cc = (CClassNode* )NULL; *np = NULL_NODE; r = fetch_token_in_cc(tok, src, end, env); if (r == TK_CHAR && tok->u.c == '^' && tok->escaped == 0) { neg = 1; r = fetch_token_in_cc(tok, src, end, env); } else { neg = 0; } if (r < 0) return r; if (r == TK_CC_CLOSE) { if (! code_exist_check((OnigCodePoint )']', *src, env->pattern_end, 1, env)) return ONIGERR_EMPTY_CHAR_CLASS; CC_ESC_WARN(env, (UChar* )"]"); r = tok->type = TK_CHAR; /* allow []...] */ } *np = node = node_new_cclass(); CHECK_NULL_RETURN_MEMERR(node); cc = NCCLASS(node); and_start = 0; state = CCS_START; p = *src; while (r != TK_CC_CLOSE) { fetched = 0; switch (r) { case TK_CHAR: if ((tok->u.code >= SINGLE_BYTE_SIZE) || (len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c)) > 1) { in_type = CCV_CODE_POINT; } else if (len < 0) { r = len; goto err; } else { sb_char: in_type = CCV_SB; } v = (OnigCodePoint )tok->u.c; in_israw = 0; goto val_entry2; break; case TK_RAW_BYTE: /* tok->base != 0 : octal or hexadec. */ if (! ONIGENC_IS_SINGLEBYTE(env->enc) && tok->base != 0) { UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN; UChar* psave = p; int i, base = tok->base; buf[0] = (UChar )tok->u.c; for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) { r = fetch_token_in_cc(tok, &p, end, env); if (r < 0) goto err; if (r != TK_RAW_BYTE || tok->base != base) { fetched = 1; break; } buf[i] = (UChar )tok->u.c; } if (i < ONIGENC_MBC_MINLEN(env->enc)) { r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING; goto err; } len = enclen(env->enc, buf); if (i < len) { r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING; goto err; } else if (i > len) { /* fetch back */ p = psave; for (i = 1; i < len; i++) { r = fetch_token_in_cc(tok, &p, end, env); } fetched = 0; } if (i == 1) { v = (OnigCodePoint )buf[0]; goto raw_single; } else { v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe); in_type = CCV_CODE_POINT; } } else { v = (OnigCodePoint )tok->u.c; raw_single: in_type = CCV_SB; } in_israw = 1; goto val_entry2; break; case TK_CODE_POINT: v = tok->u.code; in_israw = 1; val_entry: len = ONIGENC_CODE_TO_MBCLEN(env->enc, v); if (len < 0) { r = len; goto err; } in_type = (len == 1 ? CCV_SB : CCV_CODE_POINT); val_entry2: r = next_state_val(cc, &vs, v, &val_israw, in_israw, in_type, &val_type, &state, env); if (r != 0) goto err; break; case TK_POSIX_BRACKET_OPEN: r = parse_posix_bracket(cc, &p, end, env); if (r < 0) goto err; if (r == 1) { /* is not POSIX bracket */ CC_ESC_WARN(env, (UChar* )"["); p = tok->backp; v = (OnigCodePoint )tok->u.c; in_israw = 0; goto val_entry; } goto next_class; break; case TK_CHAR_TYPE: r = add_ctype_to_cc(cc, tok->u.prop.ctype, tok->u.prop.not, 0, env); if (r != 0) return r; next_class: r = next_state_class(cc, &vs, &val_type, &state, env); if (r != 0) goto err; break; case TK_CHAR_PROPERTY: { int ctype; ctype = fetch_char_property_to_ctype(&p, end, env); if (ctype < 0) return ctype; r = add_ctype_to_cc(cc, ctype, tok->u.prop.not, 1, env); if (r != 0) return r; goto next_class; } break; case TK_CC_RANGE: if (state == CCS_VALUE) { r = fetch_token_in_cc(tok, &p, end, env); if (r < 0) goto err; fetched = 1; if (r == TK_CC_CLOSE) { /* allow [x-] */ range_end_val: v = (OnigCodePoint )'-'; in_israw = 0; goto val_entry; } else if (r == TK_CC_AND) { CC_ESC_WARN(env, (UChar* )"-"); goto range_end_val; } state = CCS_RANGE; } else if (state == CCS_START) { /* [-xa] is allowed */ v = (OnigCodePoint )tok->u.c; in_israw = 0; r = fetch_token_in_cc(tok, &p, end, env); if (r < 0) goto err; fetched = 1; /* [--x] or [a&&-x] is warned. */ if (r == TK_CC_RANGE || and_start != 0) CC_ESC_WARN(env, (UChar* )"-"); goto val_entry; } else if (state == CCS_RANGE) { CC_ESC_WARN(env, (UChar* )"-"); goto sb_char; /* [!--x] is allowed */ } else { /* CCS_COMPLETE */ r = fetch_token_in_cc(tok, &p, end, env); if (r < 0) goto err; fetched = 1; if (r == TK_CC_CLOSE) goto range_end_val; /* allow [a-b-] */ else if (r == TK_CC_AND) { CC_ESC_WARN(env, (UChar* )"-"); goto range_end_val; } if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC)) { CC_ESC_WARN(env, (UChar* )"-"); goto range_end_val; /* [0-9-a] is allowed as [0-9\-a] */ } r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS; goto err; } break; case TK_CC_CC_OPEN: /* [ */ { Node *anode; CClassNode* acc; r = parse_char_class(&anode, tok, &p, end, env); if (r == 0) { acc = NCCLASS(anode); r = or_cclass(cc, acc, env->enc); } onig_node_free(anode); if (r != 0) goto err; } break; case TK_CC_AND: /* && */ { if (state == CCS_VALUE) { r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type, &val_type, &state, env); if (r != 0) goto err; } /* initialize local variables */ and_start = 1; state = CCS_START; if (IS_NOT_NULL(prev_cc)) { r = and_cclass(prev_cc, cc, env->enc); if (r != 0) goto err; bbuf_free(cc->mbuf); } else { prev_cc = cc; cc = &work_cc; } initialize_cclass(cc); } break; case TK_EOT: r = ONIGERR_PREMATURE_END_OF_CHAR_CLASS; goto err; break; default: r = ONIGERR_PARSER_BUG; goto err; break; } if (fetched) r = tok->type; else { r = fetch_token_in_cc(tok, &p, end, env); if (r < 0) goto err; } } if (state == CCS_VALUE) { r = next_state_val(cc, &vs, 0, &val_israw, 0, val_type, &val_type, &state, env); if (r != 0) goto err; } if (IS_NOT_NULL(prev_cc)) { r = and_cclass(prev_cc, cc, env->enc); if (r != 0) goto err; bbuf_free(cc->mbuf); cc = prev_cc; } if (neg != 0) NCCLASS_SET_NOT(cc); else NCCLASS_CLEAR_NOT(cc); if (IS_NCCLASS_NOT(cc) && IS_SYNTAX_BV(env->syntax, ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC)) { int is_empty; is_empty = (IS_NULL(cc->mbuf) ? 1 : 0); if (is_empty != 0) BITSET_IS_EMPTY(cc->bs, is_empty); if (is_empty == 0) { #define NEWLINE_CODE 0x0a if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) { if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1) BITSET_SET_BIT(cc->bs, NEWLINE_CODE); else { r = add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE); if (r < 0) goto err; } } } } *src = p; return 0; err: if (cc != NCCLASS(*np)) bbuf_free(cc->mbuf); return r; } static int parse_subexp(Node** top, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env); static int parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env) { int r = 0, num; Node *target, *work1 = NULL, *work2 = NULL; OnigOptionType option; OnigCodePoint c; OnigEncoding enc = env->enc; #ifdef USE_NAMED_GROUP int list_capture; #endif UChar* p = *src; PFETCH_READY; *np = NULL; if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS; option = env->option; if (PPEEK_IS('?') && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) { PINC; if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; PFETCH(c); switch (c) { case ':': /* (?:...) grouping only */ group: r = fetch_token(tok, &p, end, env); if (r < 0) return r; r = parse_subexp(np, tok, term, &p, end, env); if (r < 0) return r; *src = p; return 1; /* group */ break; case '=': *np = onig_node_new_anchor(ANCHOR_PREC_READ); break; case '!': /* preceding read */ *np = onig_node_new_anchor(ANCHOR_PREC_READ_NOT); break; case '>': /* (?>...) stop backtrack */ *np = node_new_enclose(ENCLOSE_STOP_BACKTRACK); break; #ifdef USE_NAMED_GROUP case '\'': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) { goto named_group1; } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; #ifdef USE_CAPITAL_P_NAMED_GROUP case 'P': /* (?P...) */ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) { PFETCH(c); if (c == '<') goto named_group1; } return ONIGERR_UNDEFINED_GROUP_OPTION; break; #endif #endif case '<': /* look behind (?<=...), (?...) */ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) { UChar *name; UChar *name_end; PUNFETCH; c = '<'; named_group1: list_capture = 0; named_group2: name = p; r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0); if (r < 0) return r; num = scan_env_add_mem_entry(env); if (num < 0) return num; if (list_capture != 0 && num >= (int )BIT_STATUS_BITS_NUM) return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY; r = name_add(env->reg, name, name_end, num, env); if (r != 0) return r; *np = node_new_enclose_memory(env->option, 1); CHECK_NULL_RETURN_MEMERR(*np); NENCLOSE(*np)->regnum = num; if (list_capture != 0) BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num); env->num_named++; } else { return ONIGERR_UNDEFINED_GROUP_OPTION; } } #else else { return ONIGERR_UNDEFINED_GROUP_OPTION; } #endif break; case '@': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) { #ifdef USE_NAMED_GROUP if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) { PFETCH(c); if (c == '<' || c == '\'') { list_capture = 1; goto named_group2; /* (?@...) */ } PUNFETCH; } #endif *np = node_new_enclose_memory(env->option, 0); CHECK_NULL_RETURN_MEMERR(*np); num = scan_env_add_mem_entry(env); if (num < 0) { onig_node_free(*np); return num; } else if (num >= (int )BIT_STATUS_BITS_NUM) { onig_node_free(*np); return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY; } NENCLOSE(*np)->regnum = num; BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num); } else { return ONIGERR_UNDEFINED_GROUP_OPTION; } break; case '(': /* conditional expression: (?(cond)yes), (?(cond)yes|no) */ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_CONDITION)) { UChar *name = NULL; UChar *name_end; PFETCH(c); if (ONIGENC_IS_CODE_DIGIT(enc, c)) { /* (n) */ PUNFETCH; r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &num, 1); if (r < 0) return r; if (num < 0) { num = BACKREF_REL_TO_ABS(num, env); if (num <= 0) return ONIGERR_INVALID_BACKREF; } if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) { if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num])) return ONIGERR_INVALID_BACKREF; } } #ifdef USE_NAMED_GROUP else if (c == '<' || c == '\'') { /* (), ('name') */ int nums; int *backs; name = p; r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0); if (r < 0) return r; PFETCH(c); if (c != ')') return ONIGERR_UNDEFINED_GROUP_OPTION; nums = onig_name_to_group_numbers(env->reg, name, name_end, &backs); if (nums <= 0) { onig_scan_env_set_error_string(env, ONIGERR_UNDEFINED_NAME_REFERENCE, name, name_end); return ONIGERR_UNDEFINED_NAME_REFERENCE; } if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) { int i; for (i = 0; i < nums; i++) { if (backs[i] > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[backs[i]])) return ONIGERR_INVALID_BACKREF; } } num = backs[0]; /* XXX: use left most named group as Perl */ } #endif else return ONIGERR_INVALID_CONDITION_PATTERN; *np = node_new_enclose(ENCLOSE_CONDITION); CHECK_NULL_RETURN_MEMERR(*np); NENCLOSE(*np)->regnum = num; if (IS_NOT_NULL(name)) NENCLOSE(*np)->state |= NST_NAME_REF; } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; #if 0 case '|': /* branch reset: (?|...) */ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET)) { /* TODO */ } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; #endif case '^': /* loads default options */ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) { /* d-imsx */ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1); ONOFF(option, ONIG_OPTION_IGNORECASE, 1); ONOFF(option, ONIG_OPTION_SINGLELINE, 0); ONOFF(option, ONIG_OPTION_MULTILINE, 1); ONOFF(option, ONIG_OPTION_EXTEND, 1); PFETCH(c); } #if 0 else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) { /* d-imx */ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0); ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0); ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0); ONOFF(option, ONIG_OPTION_IGNORECASE, 1); ONOFF(option, ONIG_OPTION_MULTILINE, 1); ONOFF(option, ONIG_OPTION_EXTEND, 1); PFETCH(c); } #endif else { return ONIGERR_UNDEFINED_GROUP_OPTION; } /* fall through */ #ifdef USE_POSIXLINE_OPTION case 'p': #endif case '-': case 'i': case 'm': case 's': case 'x': case 'a': case 'd': case 'l': case 'u': { int neg = 0; while (1) { switch (c) { case ':': case ')': break; case '-': neg = 1; break; case 'x': ONOFF(option, ONIG_OPTION_EXTEND, neg); break; case 'i': ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break; case 's': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) { ONOFF(option, ONIG_OPTION_MULTILINE, neg); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; case 'm': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) { ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0)); } else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) { ONOFF(option, ONIG_OPTION_MULTILINE, neg); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; #ifdef USE_POSIXLINE_OPTION case 'p': ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg); break; #endif case 'a': /* limits \d, \s, \w and POSIX brackets to ASCII range */ if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) || IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) && (neg == 0)) { ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0); ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1); ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; case 'u': if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) || IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) && (neg == 0)) { ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1); ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1); ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; case 'd': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) && (neg == 0)) { ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1); } else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY) && (neg == 0)) { ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0); ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0); ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; case 'l': if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) && (neg == 0)) { ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1); } else return ONIGERR_UNDEFINED_GROUP_OPTION; break; default: return ONIGERR_UNDEFINED_GROUP_OPTION; } if (c == ')') { *np = node_new_option(option); CHECK_NULL_RETURN_MEMERR(*np); *src = p; return 2; /* option only */ } else if (c == ':') { OnigOptionType prev = env->option; env->option = option; r = fetch_token(tok, &p, end, env); if (r < 0) return r; r = parse_subexp(&target, tok, term, &p, end, env); env->option = prev; if (r < 0) return r; *np = node_new_option(option); CHECK_NULL_RETURN_MEMERR(*np); NENCLOSE(*np)->target = target; *src = p; return 0; } if (PEND) return ONIGERR_END_PATTERN_IN_GROUP; PFETCH(c); } } break; default: return ONIGERR_UNDEFINED_GROUP_OPTION; } } else { if (ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_DONT_CAPTURE_GROUP)) goto group; *np = node_new_enclose_memory(env->option, 0); CHECK_NULL_RETURN_MEMERR(*np); num = scan_env_add_mem_entry(env); if (num < 0) return num; NENCLOSE(*np)->regnum = num; } CHECK_NULL_RETURN_MEMERR(*np); r = fetch_token(tok, &p, end, env); if (r < 0) return r; r = parse_subexp(&target, tok, term, &p, end, env); if (r < 0) { onig_node_free(target); return r; } if (NTYPE(*np) == NT_ANCHOR) NANCHOR(*np)->target = target; else { NENCLOSE(*np)->target = target; if (NENCLOSE(*np)->type == ENCLOSE_MEMORY) { /* Don't move this to previous of parse_subexp() */ r = scan_env_set_mem_node(env, NENCLOSE(*np)->regnum, *np); if (r != 0) return r; } else if (NENCLOSE(*np)->type == ENCLOSE_CONDITION) { if (NTYPE(target) != NT_ALT) { /* convert (?(cond)yes) to (?(cond)yes|empty) */ work1 = node_new_empty(); if (IS_NULL(work1)) goto err; work2 = onig_node_new_alt(work1, NULL_NODE); if (IS_NULL(work2)) goto err; work1 = onig_node_new_alt(target, work2); if (IS_NULL(work1)) goto err; NENCLOSE(*np)->target = work1; } } } *src = p; return 0; err: onig_node_free(work1); onig_node_free(work2); onig_node_free(*np); *np = NULL; return ONIGERR_MEMORY; } static const char* const PopularQStr[] = { "?", "*", "+", "??", "*?", "+?" }; static const char* const ReduceQStr[] = { "", "", "*", "*?", "??", "+ and ??", "+? and ?" }; static int set_quantifier(Node* qnode, Node* target, int group, ScanEnv* env) { QtfrNode* qn; qn = NQTFR(qnode); if (qn->lower == 1 && qn->upper == 1) { return 1; } switch (NTYPE(target)) { case NT_STR: if (! group) { StrNode* sn = NSTR(target); if (str_node_can_be_split(sn, env->enc)) { Node* n = str_node_split_last_char(sn, env->enc); if (IS_NOT_NULL(n)) { qn->target = n; return 2; } } } break; case NT_QTFR: { /* check redundant double repeat. */ /* verbose warn (?:.?)? etc... but not warn (.?)? etc... */ QtfrNode* qnt = NQTFR(target); int nestq_num = popular_quantifier_num(qn); int targetq_num = popular_quantifier_num(qnt); #ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR if (!IS_QUANTIFIER_BY_NUMBER(qn) && !IS_QUANTIFIER_BY_NUMBER(qnt) && IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) { UChar buf[WARN_BUFSIZE]; switch (ReduceTypeTable[targetq_num][nestq_num]) { case RQ_ASIS: break; case RQ_DEL: if (onig_verb_warn != onig_null_warn) { onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, env->pattern, env->pattern_end, (UChar* )"redundant nested repeat operator"); (*onig_verb_warn)((char* )buf); } goto warn_exit; break; default: if (onig_verb_warn != onig_null_warn) { onig_snprintf_with_pattern(buf, WARN_BUFSIZE, env->enc, env->pattern, env->pattern_end, (UChar* )"nested repeat operator %s and %s was replaced with '%s'", PopularQStr[targetq_num], PopularQStr[nestq_num], ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]); (*onig_verb_warn)((char* )buf); } goto warn_exit; break; } } warn_exit: #endif if (targetq_num >= 0) { if (nestq_num >= 0) { onig_reduce_nested_quantifier(qnode, target); goto q_exit; } else if (targetq_num == 1 || targetq_num == 2) { /* * or + */ /* (?:a*){n,m}, (?:a+){n,m} => (?:a*){n,n}, (?:a+){n,n} */ if (! IS_REPEAT_INFINITE(qn->upper) && qn->upper > 1 && qn->greedy) { qn->upper = (qn->lower == 0 ? 1 : qn->lower); } } } } break; default: break; } qn->target = target; q_exit: return 0; } #ifdef USE_SHARED_CCLASS_TABLE #define THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS 8 /* for ctype node hash table */ typedef struct { OnigEncoding enc; int not; int type; } type_cclass_key; static int type_cclass_cmp(type_cclass_key* x, type_cclass_key* y) { if (x->type != y->type) return 1; if (x->enc != y->enc) return 1; if (x->not != y->not) return 1; return 0; } static int type_cclass_hash(type_cclass_key* key) { int i, val; UChar *p; val = 0; p = (UChar* )&(key->enc); for (i = 0; i < (int )sizeof(key->enc); i++) { val = val * 997 + (int )*p++; } p = (UChar* )(&key->type); for (i = 0; i < (int )sizeof(key->type); i++) { val = val * 997 + (int )*p++; } val += key->not; return val + (val >> 5); } static struct st_hash_type type_type_cclass_hash = { type_cclass_cmp, type_cclass_hash, }; static st_table* OnigTypeCClassTable; static int i_free_shared_class(type_cclass_key* key, Node* node, void* arg ARG_UNUSED) { if (IS_NOT_NULL(node)) { CClassNode* cc = NCCLASS(node); if (IS_NOT_NULL(cc->mbuf)) xfree(cc->mbuf); xfree(node); } if (IS_NOT_NULL(key)) xfree(key); return ST_DELETE; } extern int onig_free_shared_cclass_table(void) { THREAD_ATOMIC_START; if (IS_NOT_NULL(OnigTypeCClassTable)) { onig_st_foreach(OnigTypeCClassTable, i_free_shared_class, 0); onig_st_free_table(OnigTypeCClassTable); OnigTypeCClassTable = NULL; } THREAD_ATOMIC_END; return 0; } #endif /* USE_SHARED_CCLASS_TABLE */ #ifdef USE_SHARED_UNICODE_TABLE extern st_table* FoldTable; /* fold-1, fold-2, fold-3 */ extern st_table* Unfold1Table; extern st_table* Unfold2Table; extern st_table* Unfold3Table; extern int CaseFoldInited; static int i_free_shared_unicode_table(st_str_end_key* key, Node* node, void* arg ARG_UNUSED) { if (IS_NOT_NULL(key)) xfree(key); return ST_DELETE; } extern int onig_free_shared_unicode_table(void) { THREAD_ATOMIC_START; if (IS_NOT_NULL(FoldTable)) { onig_st_free_table(FoldTable); FoldTable = NULL; } if (IS_NOT_NULL(Unfold1Table)) { onig_st_free_table(Unfold1Table); Unfold1Table = NULL; } if (IS_NOT_NULL(Unfold2Table)) { onig_st_free_table(Unfold2Table); Unfold2Table = NULL; } if (IS_NOT_NULL(Unfold3Table)) { onig_st_free_table(Unfold3Table); Unfold3Table = NULL; } CaseFoldInited = 0; THREAD_ATOMIC_END; return 0; } #endif // USE_SHARED_UNICODE_TABLE #ifndef CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS static int clear_not_flag_cclass(CClassNode* cc, OnigEncoding enc) { BBuf *tbuf; int r; if (IS_NCCLASS_NOT(cc)) { bitset_invert(cc->bs); if (! ONIGENC_IS_SINGLEBYTE(enc)) { r = not_code_range_buf(enc, cc->mbuf, &tbuf); if (r != 0) return r; bbuf_free(cc->mbuf); cc->mbuf = tbuf; } NCCLASS_CLEAR_NOT(cc); } return 0; } #endif /* CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS */ typedef struct { ScanEnv* env; CClassNode* cc; Node* alt_root; Node** ptail; } IApplyCaseFoldArg; static int i_apply_case_fold(OnigCodePoint from, OnigCodePoint to[], int to_len, void* arg) { IApplyCaseFoldArg* iarg; ScanEnv* env; CClassNode* cc; BitSetRef bs; iarg = (IApplyCaseFoldArg* )arg; env = iarg->env; cc = iarg->cc; bs = cc->bs; if (to_len == 1) { int is_in = onig_is_code_in_cc(env->enc, from, cc); #ifdef CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS if ((is_in != 0 && !IS_NCCLASS_NOT(cc)) || (is_in == 0 && IS_NCCLASS_NOT(cc))) { if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) { add_code_range(&(cc->mbuf), env, *to, *to); } else { BITSET_SET_BIT(bs, *to); } } #else if (is_in != 0) { if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) { if (IS_NCCLASS_NOT(cc)) clear_not_flag_cclass(cc, env->enc); add_code_range(&(cc->mbuf), env, *to, *to); } else { if (IS_NCCLASS_NOT(cc)) { BITSET_CLEAR_BIT(bs, *to); } else BITSET_SET_BIT(bs, *to); } } #endif /* CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS */ } else { int r, i, len; UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN]; Node *snode = NULL_NODE; if (onig_is_code_in_cc(env->enc, from, cc) #ifdef CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS && !IS_NCCLASS_NOT(cc) #endif ) { for (i = 0; i < to_len; i++) { len = ONIGENC_CODE_TO_MBC(env->enc, to[i], buf); if (i == 0) { snode = onig_node_new_str(buf, buf + len); CHECK_NULL_RETURN_MEMERR(snode); /* char-class expanded multi-char only compare with string folded at match time. */ NSTRING_SET_AMBIG(snode); } else { r = onig_node_str_cat(snode, buf, buf + len); if (r < 0) { onig_node_free(snode); return r; } } } *(iarg->ptail) = onig_node_new_alt(snode, NULL_NODE); CHECK_NULL_RETURN_MEMERR(*(iarg->ptail)); iarg->ptail = &(NCDR((*(iarg->ptail)))); } } return 0; } static int node_linebreak(Node** np, ScanEnv* env) { /* same as (?>\x0D\x0A|[\x0A-\x0D\x{85}\x{2028}\x{2029}]) */ Node* left = NULL; Node* right = NULL; Node* target1 = NULL; Node* target2 = NULL; CClassNode* cc; int num1, num2; UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN * 2]; /* \x0D\x0A */ num1 = ONIGENC_CODE_TO_MBC(env->enc, 0x0D, buf); if (num1 < 0) return num1; num2 = ONIGENC_CODE_TO_MBC(env->enc, 0x0A, buf + num1); if (num2 < 0) return num2; left = node_new_str_raw(buf, buf + num1 + num2); if (IS_NULL(left)) goto err; /* [\x0A-\x0D] or [\x0A-\x0D\x{85}\x{2028}\x{2029}] */ right = node_new_cclass(); if (IS_NULL(right)) goto err; cc = NCCLASS(right); if (ONIGENC_MBC_MINLEN(env->enc) > 1) { add_code_range(&(cc->mbuf), env, 0x0A, 0x0D); } else { bitset_set_range(cc->bs, 0x0A, 0x0D); } /* TODO: move this block to enc/unicode.c */ if (ONIGENC_IS_UNICODE(env->enc)) { /* UTF-8, UTF-16BE/LE, UTF-32BE/LE */ add_code_range(&(cc->mbuf), env, 0x85, 0x85); add_code_range(&(cc->mbuf), env, 0x2028, 0x2029); } /* ...|... */ target1 = onig_node_new_alt(right, NULL_NODE); if (IS_NULL(target1)) goto err; right = NULL; target2 = onig_node_new_alt(left, target1); if (IS_NULL(target2)) goto err; left = NULL; target1 = NULL; /* (?>...) */ *np = node_new_enclose(ENCLOSE_STOP_BACKTRACK); if (IS_NULL(*np)) goto err; NENCLOSE(*np)->target = target2; return ONIG_NORMAL; err: onig_node_free(left); onig_node_free(right); onig_node_free(target1); onig_node_free(target2); return ONIGERR_MEMORY; } static int node_extended_grapheme_cluster(Node** np, ScanEnv* env) { /* same as (?>\P{M}\p{M}*) */ Node* np1 = NULL; Node* np2 = NULL; Node* qn = NULL; Node* list1 = NULL; Node* list2 = NULL; int r = 0; #ifdef USE_UNICODE_PROPERTIES if (ONIGENC_IS_UNICODE(env->enc)) { /* UTF-8, UTF-16BE/LE, UTF-32BE/LE */ CClassNode* cc1; CClassNode* cc2; UChar* propname = (UChar* )"M"; int ctype = env->enc->property_name_to_ctype(ONIG_ENCODING_ASCII, propname, propname + 1); if (ctype >= 0) { /* \P{M} */ np1 = node_new_cclass(); if (IS_NULL(np1)) goto err; cc1 = NCCLASS(np1); r = add_ctype_to_cc(cc1, ctype, 0, 1, env); if (r != 0) goto err; NCCLASS_SET_NOT(cc1); /* \p{M}* */ np2 = node_new_cclass(); if (IS_NULL(np2)) goto err; cc2 = NCCLASS(np2); r = add_ctype_to_cc(cc2, ctype, 0, 1, env); if (r != 0) goto err; qn = node_new_quantifier(0, REPEAT_INFINITE, 0); if (IS_NULL(qn)) goto err; NQTFR(qn)->target = np2; np2 = NULL; /* \P{M}\p{M}* */ list2 = node_new_list(qn, NULL_NODE); if (IS_NULL(list2)) goto err; qn = NULL; list1 = node_new_list(np1, list2); if (IS_NULL(list1)) goto err; np1 = NULL; list2 = NULL; /* (?>...) */ *np = node_new_enclose(ENCLOSE_STOP_BACKTRACK); if (IS_NULL(*np)) goto err; NENCLOSE(*np)->target = list1; return ONIG_NORMAL; } } #endif /* USE_UNICODE_PROPERTIES */ if (IS_NULL(*np)) { /* PerlSyntax: (?s:.), RubySyntax: (?m:.) */ OnigOptionType option; np1 = node_new_anychar(); if (IS_NULL(np1)) goto err; option = env->option; ONOFF(option, ONIG_OPTION_MULTILINE, 0); *np = node_new_option(option); if (IS_NULL(*np)) goto err; NENCLOSE(*np)->target = np1; } return ONIG_NORMAL; err: onig_node_free(np1); onig_node_free(np2); onig_node_free(qn); onig_node_free(list1); onig_node_free(list2); return (r == 0) ? ONIGERR_MEMORY : r; } static int countbits(unsigned int bits) { bits = (bits & 0x55555555) + ((bits >> 1) & 0x55555555); bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333); bits = (bits & 0x0f0f0f0f) + ((bits >> 4) & 0x0f0f0f0f); bits = (bits & 0x00ff00ff) + ((bits >> 8) & 0x00ff00ff); return (bits & 0x0000ffff) + ((bits >>16) & 0x0000ffff); } static int is_onechar_cclass(CClassNode* cc, OnigCodePoint* code) { const OnigCodePoint not_found = ONIG_LAST_CODE_POINT; OnigCodePoint c = not_found; int i; BBuf *bbuf = cc->mbuf; if (IS_NCCLASS_NOT(cc)) return 0; /* check bbuf */ if (IS_NOT_NULL(bbuf)) { OnigCodePoint n, *data; GET_CODE_POINT(n, bbuf->p); data = (OnigCodePoint* )(bbuf->p) + 1; if ((n == 1) && (data[0] == data[1])) { /* only one char found in the bbuf, save the code point. */ c = data[0]; if (((c < SINGLE_BYTE_SIZE) && BITSET_AT(cc->bs, c))) { /* skip if c is included in the bitset */ c = not_found; } } else { return 0; /* the bbuf contains multiple chars */ } } /* check bitset */ for (i = 0; i < BITSET_SIZE; i++) { Bits b1 = cc->bs[i]; if (b1 != 0) { if (((b1 & (b1 - 1)) == 0) && (c == not_found)) { c = BITS_IN_ROOM * i + countbits(b1 - 1); } else { return 0; /* the character class contains multiple chars */ } } } if (c != not_found) { *code = c; return 1; } /* the character class contains no char. */ return 0; } static int parse_exp(Node** np, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env) { int r, len, group = 0; Node* qn; Node** targetp; *np = NULL; if (tok->type == (enum TokenSyms )term) goto end_of_token; switch (tok->type) { case TK_ALT: case TK_EOT: end_of_token: *np = node_new_empty(); return tok->type; break; case TK_SUBEXP_OPEN: r = parse_enclose(np, tok, TK_SUBEXP_CLOSE, src, end, env); if (r < 0) return r; if (r == 1) group = 1; else if (r == 2) { /* option only */ Node* target; OnigOptionType prev = env->option; env->option = NENCLOSE(*np)->option; r = fetch_token(tok, src, end, env); if (r < 0) return r; r = parse_subexp(&target, tok, term, src, end, env); env->option = prev; if (r < 0) { onig_node_free(target); return r; } NENCLOSE(*np)->target = target; return tok->type; } break; case TK_SUBEXP_CLOSE: if (! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP)) return ONIGERR_UNMATCHED_CLOSE_PARENTHESIS; if (tok->escaped) goto tk_raw_byte; else goto tk_byte; break; case TK_LINEBREAK: r = node_linebreak(np, env); if (r < 0) return r; break; case TK_EXTENDED_GRAPHEME_CLUSTER: r = node_extended_grapheme_cluster(np, env); if (r < 0) return r; break; case TK_KEEP: *np = onig_node_new_anchor(ANCHOR_KEEP); CHECK_NULL_RETURN_MEMERR(*np); break; case TK_STRING: tk_byte: { *np = node_new_str(tok->backp, *src); CHECK_NULL_RETURN_MEMERR(*np); string_loop: while (1) { r = fetch_token(tok, src, end, env); if (r < 0) return r; if (r == TK_STRING) { r = onig_node_str_cat(*np, tok->backp, *src); } #ifndef NUMBERED_CHAR_IS_NOT_CASE_AMBIG else if (r == TK_CODE_POINT) { r = node_str_cat_codepoint(*np, env->enc, tok->u.code); } #endif else { break; } if (r < 0) return r; } string_end: targetp = np; goto repeat; } break; case TK_RAW_BYTE: tk_raw_byte: { *np = node_new_str_raw_char((UChar )tok->u.c); CHECK_NULL_RETURN_MEMERR(*np); len = 1; while (1) { if (len >= ONIGENC_MBC_MINLEN(env->enc)) { if (len == enclen(env->enc, NSTR(*np)->s)) { r = fetch_token(tok, src, end, env); NSTRING_CLEAR_RAW(*np); goto string_end; } } r = fetch_token(tok, src, end, env); if (r < 0) return r; if (r != TK_RAW_BYTE) { /* Don't use this, it is wrong for little endian encodings. */ #ifdef USE_PAD_TO_SHORT_BYTE_CHAR int rem; if (len < ONIGENC_MBC_MINLEN(env->enc)) { rem = ONIGENC_MBC_MINLEN(env->enc) - len; (void )node_str_head_pad(NSTR(*np), rem, (UChar )0); if (len + rem == enclen(env->enc, NSTR(*np)->s)) { NSTRING_CLEAR_RAW(*np); goto string_end; } } #endif return ONIGERR_TOO_SHORT_MULTI_BYTE_STRING; } r = node_str_cat_char(*np, (UChar )tok->u.c); if (r < 0) return r; len++; } } break; case TK_CODE_POINT: { *np = node_new_empty(); CHECK_NULL_RETURN_MEMERR(*np); r = node_str_cat_codepoint(*np, env->enc, tok->u.code); if (r != 0) return r; #ifdef NUMBERED_CHAR_IS_NOT_CASE_AMBIG NSTRING_SET_RAW(*np); #else goto string_loop; #endif } break; case TK_QUOTE_OPEN: { OnigCodePoint end_op[2]; UChar *qstart, *qend, *nextp; end_op[0] = (OnigCodePoint )MC_ESC(env->syntax); end_op[1] = (OnigCodePoint )'E'; qstart = *src; qend = find_str_position(end_op, 2, qstart, end, &nextp, env->enc); if (IS_NULL(qend)) { nextp = qend = end; } *np = node_new_str(qstart, qend); CHECK_NULL_RETURN_MEMERR(*np); *src = nextp; } break; case TK_CHAR_TYPE: { switch (tok->u.prop.ctype) { case ONIGENC_CTYPE_WORD: *np = node_new_ctype(tok->u.prop.ctype, tok->u.prop.not, IS_ASCII_RANGE(env->option)); CHECK_NULL_RETURN_MEMERR(*np); break; case ONIGENC_CTYPE_SPACE: case ONIGENC_CTYPE_DIGIT: case ONIGENC_CTYPE_XDIGIT: { CClassNode* cc; #ifdef USE_SHARED_CCLASS_TABLE const OnigCodePoint *mbr; OnigCodePoint sb_out; r = ONIGENC_GET_CTYPE_CODE_RANGE(env->enc, tok->u.prop.ctype, &sb_out, &mbr); if (r == 0 && ! IS_ASCII_RANGE(env->option) && ONIGENC_CODE_RANGE_NUM(mbr) >= THRESHOLD_RANGE_NUM_FOR_SHARE_CCLASS) { type_cclass_key key; type_cclass_key* new_key; key.enc = env->enc; key.not = tok->u.prop.not; key.type = tok->u.prop.ctype; THREAD_ATOMIC_START; if (IS_NULL(OnigTypeCClassTable)) { OnigTypeCClassTable = onig_st_init_table_with_size(&type_type_cclass_hash, 10); if (IS_NULL(OnigTypeCClassTable)) { THREAD_ATOMIC_END; return ONIGERR_MEMORY; } } else { if (onig_st_lookup(OnigTypeCClassTable, (st_data_t )&key, (st_data_t* )np)) { THREAD_ATOMIC_END; break; } } *np = node_new_cclass_by_codepoint_range(tok->u.prop.not, sb_out, mbr); if (IS_NULL(*np)) { THREAD_ATOMIC_END; return ONIGERR_MEMORY; } cc = NCCLASS(*np); NCCLASS_SET_SHARE(cc); new_key = (type_cclass_key* )xmalloc(sizeof(type_cclass_key)); xmemcpy(new_key, &key, sizeof(type_cclass_key)); onig_st_add_direct(OnigTypeCClassTable, (st_data_t )new_key, (st_data_t )*np); THREAD_ATOMIC_END; } else { #endif *np = node_new_cclass(); CHECK_NULL_RETURN_MEMERR(*np); cc = NCCLASS(*np); r = add_ctype_to_cc(cc, tok->u.prop.ctype, 0, 0, env); if (r != 0) return r; if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc); #ifdef USE_SHARED_CCLASS_TABLE } #endif } break; default: return ONIGERR_PARSER_BUG; break; } } break; case TK_CHAR_PROPERTY: r = parse_char_property(np, tok, src, end, env); if (r != 0) return r; break; case TK_CC_OPEN: { CClassNode* cc; OnigCodePoint code; r = parse_char_class(np, tok, src, end, env); if (r != 0) return r; cc = NCCLASS(*np); if (is_onechar_cclass(cc, &code)) { onig_node_free(*np); *np = node_new_empty(); CHECK_NULL_RETURN_MEMERR(*np); r = node_str_cat_codepoint(*np, env->enc, code); if (r != 0) return r; goto string_loop; } if (IS_IGNORECASE(env->option)) { IApplyCaseFoldArg iarg; iarg.env = env; iarg.cc = cc; iarg.alt_root = NULL_NODE; iarg.ptail = &(iarg.alt_root); r = ONIGENC_APPLY_ALL_CASE_FOLD(env->enc, env->case_fold_flag, i_apply_case_fold, &iarg); if (r != 0) { onig_node_free(iarg.alt_root); return r; } if (IS_NOT_NULL(iarg.alt_root)) { Node* work = onig_node_new_alt(*np, iarg.alt_root); if (IS_NULL(work)) { onig_node_free(iarg.alt_root); return ONIGERR_MEMORY; } *np = work; } } } break; case TK_ANYCHAR: *np = node_new_anychar(); CHECK_NULL_RETURN_MEMERR(*np); break; case TK_ANYCHAR_ANYTIME: *np = node_new_anychar(); CHECK_NULL_RETURN_MEMERR(*np); qn = node_new_quantifier(0, REPEAT_INFINITE, 0); CHECK_NULL_RETURN_MEMERR(qn); NQTFR(qn)->target = *np; *np = qn; break; case TK_BACKREF: len = tok->u.backref.num; *np = node_new_backref(len, (len > 1 ? tok->u.backref.refs : &(tok->u.backref.ref1)), tok->u.backref.by_name, #ifdef USE_BACKREF_WITH_LEVEL tok->u.backref.exist_level, tok->u.backref.level, #endif env); CHECK_NULL_RETURN_MEMERR(*np); break; #ifdef USE_SUBEXP_CALL case TK_CALL: { int gnum = tok->u.call.gnum; if (gnum < 0 || tok->u.call.rel != 0) { if (gnum > 0) gnum--; gnum = BACKREF_REL_TO_ABS(gnum, env); if (gnum <= 0) return ONIGERR_INVALID_BACKREF; } *np = node_new_call(tok->u.call.name, tok->u.call.name_end, gnum); CHECK_NULL_RETURN_MEMERR(*np); env->num_call++; } break; #endif case TK_ANCHOR: *np = onig_node_new_anchor(tok->u.anchor.subtype); CHECK_NULL_RETURN_MEMERR(*np); NANCHOR(*np)->ascii_range = tok->u.anchor.ascii_range; break; case TK_OP_REPEAT: case TK_INTERVAL: if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS)) { if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS)) return ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED; else *np = node_new_empty(); } else { goto tk_byte; } break; default: return ONIGERR_PARSER_BUG; break; } { targetp = np; re_entry: r = fetch_token(tok, src, end, env); if (r < 0) return r; repeat: if (r == TK_OP_REPEAT || r == TK_INTERVAL) { if (is_invalid_quantifier_target(*targetp)) return ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID; qn = node_new_quantifier(tok->u.repeat.lower, tok->u.repeat.upper, (r == TK_INTERVAL ? 1 : 0)); CHECK_NULL_RETURN_MEMERR(qn); NQTFR(qn)->greedy = tok->u.repeat.greedy; r = set_quantifier(qn, *targetp, group, env); if (r < 0) { onig_node_free(qn); return r; } if (tok->u.repeat.possessive != 0) { Node* en; en = node_new_enclose(ENCLOSE_STOP_BACKTRACK); if (IS_NULL(en)) { onig_node_free(qn); return ONIGERR_MEMORY; } NENCLOSE(en)->target = qn; qn = en; } if (r == 0) { *targetp = qn; } else if (r == 1) { onig_node_free(qn); } else if (r == 2) { /* split case: /abc+/ */ Node *tmp; *targetp = node_new_list(*targetp, NULL); if (IS_NULL(*targetp)) { onig_node_free(qn); return ONIGERR_MEMORY; } tmp = NCDR(*targetp) = node_new_list(qn, NULL); if (IS_NULL(tmp)) { onig_node_free(qn); return ONIGERR_MEMORY; } targetp = &(NCAR(tmp)); } goto re_entry; } } return r; } static int parse_branch(Node** top, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env) { int r; Node *node, **headp; *top = NULL; r = parse_exp(&node, tok, term, src, end, env); if (r < 0) { onig_node_free(node); return r; } if (r == TK_EOT || r == term || r == TK_ALT) { *top = node; } else { *top = node_new_list(node, NULL); headp = &(NCDR(*top)); while (r != TK_EOT && r != term && r != TK_ALT) { r = parse_exp(&node, tok, term, src, end, env); if (r < 0) { onig_node_free(node); return r; } if (NTYPE(node) == NT_LIST) { *headp = node; while (IS_NOT_NULL(NCDR(node))) node = NCDR(node); headp = &(NCDR(node)); } else { *headp = node_new_list(node, NULL); headp = &(NCDR(*headp)); } } } return r; } /* term_tok: TK_EOT or TK_SUBEXP_CLOSE */ static int parse_subexp(Node** top, OnigToken* tok, int term, UChar** src, UChar* end, ScanEnv* env) { int r; Node *node, **headp; *top = NULL; r = parse_branch(&node, tok, term, src, end, env); if (r < 0) { onig_node_free(node); return r; } if (r == term) { *top = node; } else if (r == TK_ALT) { *top = onig_node_new_alt(node, NULL); headp = &(NCDR(*top)); while (r == TK_ALT) { r = fetch_token(tok, src, end, env); if (r < 0) return r; r = parse_branch(&node, tok, term, src, end, env); if (r < 0) { onig_node_free(node); return r; } *headp = onig_node_new_alt(node, NULL); headp = &(NCDR(*headp)); } if (tok->type != (enum TokenSyms )term) goto err; } else { onig_node_free(node); err: if (term == TK_SUBEXP_CLOSE) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS; else return ONIGERR_PARSER_BUG; } return r; } static int parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env) { int r; OnigToken tok; r = fetch_token(&tok, src, end, env); if (r < 0) return r; r = parse_subexp(top, &tok, TK_EOT, src, end, env); if (r < 0) return r; #ifdef USE_SUBEXP_CALL if (env->num_call > 0) { /* Capture the pattern itself. It is used for (?R), (?0) and \g<0>. */ const int num = 0; Node* np; np = node_new_enclose_memory(env->option, 0); CHECK_NULL_RETURN_MEMERR(np); NENCLOSE(np)->regnum = num; NENCLOSE(np)->target = *top; r = scan_env_set_mem_node(env, num, np); if (r != 0) return r; *top = np; } #endif return 0; } extern int onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end, regex_t* reg, ScanEnv* env) { int r; UChar* p; #ifdef USE_NAMED_GROUP names_clear(reg); #endif scan_env_clear(env); env->option = reg->options; env->case_fold_flag = reg->case_fold_flag; env->enc = reg->enc; env->syntax = reg->syntax; env->pattern = (UChar* )pattern; env->pattern_end = (UChar* )end; env->reg = reg; *root = NULL; p = (UChar* )pattern; r = parse_regexp(root, &p, (UChar* )end, env); reg->num_mem = env->num_mem; return r; } extern void onig_scan_env_set_error_string(ScanEnv* env, int ecode ARG_UNUSED, UChar* arg, UChar* arg_end) { env->error = arg; env->error_end = arg_end; } ================================================ FILE: src/Onigmo/regparse.h ================================================ #ifndef REGPARSE_H #define REGPARSE_H /********************************************************************** regparse.h - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" /* node type */ #define NT_STR 0 #define NT_CCLASS 1 #define NT_CTYPE 2 #define NT_CANY 3 #define NT_BREF 4 #define NT_QTFR 5 #define NT_ENCLOSE 6 #define NT_ANCHOR 7 #define NT_LIST 8 #define NT_ALT 9 #define NT_CALL 10 /* node type bit */ #define NTYPE2BIT(type) (1<<(type)) #define BIT_NT_STR NTYPE2BIT(NT_STR) #define BIT_NT_CCLASS NTYPE2BIT(NT_CCLASS) #define BIT_NT_CTYPE NTYPE2BIT(NT_CTYPE) #define BIT_NT_CANY NTYPE2BIT(NT_CANY) #define BIT_NT_BREF NTYPE2BIT(NT_BREF) #define BIT_NT_QTFR NTYPE2BIT(NT_QTFR) #define BIT_NT_ENCLOSE NTYPE2BIT(NT_ENCLOSE) #define BIT_NT_ANCHOR NTYPE2BIT(NT_ANCHOR) #define BIT_NT_LIST NTYPE2BIT(NT_LIST) #define BIT_NT_ALT NTYPE2BIT(NT_ALT) #define BIT_NT_CALL NTYPE2BIT(NT_CALL) #define IS_NODE_TYPE_SIMPLE(type) \ ((NTYPE2BIT(type) & (BIT_NT_STR | BIT_NT_CCLASS | BIT_NT_CTYPE |\ BIT_NT_CANY | BIT_NT_BREF)) != 0) #define NTYPE(node) ((node)->u.base.type) #define SET_NTYPE(node, ntype) (node)->u.base.type = (ntype) #define NSTR(node) (&((node)->u.str)) #define NCCLASS(node) (&((node)->u.cclass)) #define NCTYPE(node) (&((node)->u.ctype)) #define NBREF(node) (&((node)->u.bref)) #define NQTFR(node) (&((node)->u.qtfr)) #define NENCLOSE(node) (&((node)->u.enclose)) #define NANCHOR(node) (&((node)->u.anchor)) #define NCONS(node) (&((node)->u.cons)) #define NCALL(node) (&((node)->u.call)) #define NCAR(node) (NCONS(node)->car) #define NCDR(node) (NCONS(node)->cdr) #define ANCHOR_ANYCHAR_STAR_MASK (ANCHOR_ANYCHAR_STAR | ANCHOR_ANYCHAR_STAR_ML) #define ANCHOR_END_BUF_MASK (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF) #define ENCLOSE_MEMORY (1<<0) #define ENCLOSE_OPTION (1<<1) #define ENCLOSE_STOP_BACKTRACK (1<<2) #define ENCLOSE_CONDITION (1<<3) #define NODE_STR_MARGIN 16 #define NODE_STR_BUF_SIZE 24 /* sizeof(CClassNode) - sizeof(int)*4 */ #define NODE_BACKREFS_SIZE 6 #define NSTR_RAW (1<<0) /* by backslashed number */ #define NSTR_AMBIG (1<<1) #define NSTR_DONT_GET_OPT_INFO (1<<2) #define NSTRING_LEN(node) (OnigDistance )((node)->u.str.end - (node)->u.str.s) #define NSTRING_SET_RAW(node) (node)->u.str.flag |= NSTR_RAW #define NSTRING_CLEAR_RAW(node) (node)->u.str.flag &= ~NSTR_RAW #define NSTRING_SET_AMBIG(node) (node)->u.str.flag |= NSTR_AMBIG #define NSTRING_SET_DONT_GET_OPT_INFO(node) \ (node)->u.str.flag |= NSTR_DONT_GET_OPT_INFO #define NSTRING_IS_RAW(node) (((node)->u.str.flag & NSTR_RAW) != 0) #define NSTRING_IS_AMBIG(node) (((node)->u.str.flag & NSTR_AMBIG) != 0) #define NSTRING_IS_DONT_GET_OPT_INFO(node) \ (((node)->u.str.flag & NSTR_DONT_GET_OPT_INFO) != 0) #define BACKREFS_P(br) \ (IS_NOT_NULL((br)->back_dynamic) ? (br)->back_dynamic : (br)->back_static); #define NQ_TARGET_ISNOT_EMPTY 0 #define NQ_TARGET_IS_EMPTY 1 #define NQ_TARGET_IS_EMPTY_MEM 2 #define NQ_TARGET_IS_EMPTY_REC 3 /* status bits */ #define NST_MIN_FIXED (1<<0) #define NST_MAX_FIXED (1<<1) #define NST_CLEN_FIXED (1<<2) #define NST_MARK1 (1<<3) #define NST_MARK2 (1<<4) #define NST_MEM_BACKREFED (1<<5) #define NST_STOP_BT_SIMPLE_REPEAT (1<<6) #define NST_RECURSION (1<<7) #define NST_CALLED (1<<8) #define NST_ADDR_FIXED (1<<9) #define NST_NAMED_GROUP (1<<10) #define NST_NAME_REF (1<<11) #define NST_IN_REPEAT (1<<12) /* STK_REPEAT is nested in stack. */ #define NST_NEST_LEVEL (1<<13) #define NST_BY_NUMBER (1<<14) /* {n,m} */ #define SET_ENCLOSE_STATUS(node,f) (node)->u.enclose.state |= (f) #define CLEAR_ENCLOSE_STATUS(node,f) (node)->u.enclose.state &= ~(f) #define IS_ENCLOSE_CALLED(en) (((en)->state & NST_CALLED) != 0) #define IS_ENCLOSE_ADDR_FIXED(en) (((en)->state & NST_ADDR_FIXED) != 0) #define IS_ENCLOSE_RECURSION(en) (((en)->state & NST_RECURSION) != 0) #define IS_ENCLOSE_MARK1(en) (((en)->state & NST_MARK1) != 0) #define IS_ENCLOSE_MARK2(en) (((en)->state & NST_MARK2) != 0) #define IS_ENCLOSE_MIN_FIXED(en) (((en)->state & NST_MIN_FIXED) != 0) #define IS_ENCLOSE_MAX_FIXED(en) (((en)->state & NST_MAX_FIXED) != 0) #define IS_ENCLOSE_CLEN_FIXED(en) (((en)->state & NST_CLEN_FIXED) != 0) #define IS_ENCLOSE_STOP_BT_SIMPLE_REPEAT(en) \ (((en)->state & NST_STOP_BT_SIMPLE_REPEAT) != 0) #define IS_ENCLOSE_NAMED_GROUP(en) (((en)->state & NST_NAMED_GROUP) != 0) #define IS_ENCLOSE_NAME_REF(en) (((en)->state & NST_NAME_REF) != 0) #define SET_CALL_RECURSION(node) (node)->u.call.state |= NST_RECURSION #define IS_CALL_RECURSION(cn) (((cn)->state & NST_RECURSION) != 0) #define IS_CALL_NAME_REF(cn) (((cn)->state & NST_NAME_REF) != 0) #define IS_BACKREF_NAME_REF(bn) (((bn)->state & NST_NAME_REF) != 0) #define IS_BACKREF_NEST_LEVEL(bn) (((bn)->state & NST_NEST_LEVEL) != 0) #define IS_QUANTIFIER_IN_REPEAT(qn) (((qn)->state & NST_IN_REPEAT) != 0) #define IS_QUANTIFIER_BY_NUMBER(qn) (((qn)->state & NST_BY_NUMBER) != 0) #define CALLNODE_REFNUM_UNDEF -1 typedef struct { NodeBase base; UChar* s; UChar* end; unsigned int flag; int capa; /* (allocated size - 1) or 0: use buf[] */ UChar buf[NODE_STR_BUF_SIZE]; } StrNode; typedef struct { NodeBase base; int state; struct _Node* target; int lower; int upper; int greedy; int target_empty_info; struct _Node* head_exact; struct _Node* next_head_exact; int is_refered; /* include called node. don't eliminate even if {0} */ #ifdef USE_COMBINATION_EXPLOSION_CHECK int comb_exp_check_num; /* 1,2,3...: check, 0: no check */ #endif } QtfrNode; typedef struct { NodeBase base; int state; int type; int regnum; OnigOptionType option; struct _Node* target; AbsAddrType call_addr; /* for multiple call reference */ OnigDistance min_len; /* min length (byte) */ OnigDistance max_len; /* max length (byte) */ int char_len; /* character length */ int opt_count; /* referenced count in optimize_node_left() */ } EncloseNode; #ifdef USE_SUBEXP_CALL typedef struct { int offset; struct _Node* target; } UnsetAddr; typedef struct { int num; int alloc; UnsetAddr* us; } UnsetAddrList; typedef struct { NodeBase base; int state; int group_num; UChar* name; UChar* name_end; struct _Node* target; /* EncloseNode : ENCLOSE_MEMORY */ UnsetAddrList* unset_addr_list; } CallNode; #endif typedef struct { NodeBase base; int state; int back_num; int back_static[NODE_BACKREFS_SIZE]; int* back_dynamic; int nest_level; } BRefNode; typedef struct { NodeBase base; int type; struct _Node* target; int char_len; int ascii_range; } AnchorNode; typedef struct { NodeBase base; struct _Node* car; struct _Node* cdr; } ConsAltNode; typedef struct { NodeBase base; int ctype; int not; int ascii_range; } CtypeNode; typedef struct _Node { union { NodeBase base; StrNode str; CClassNode cclass; QtfrNode qtfr; EncloseNode enclose; BRefNode bref; AnchorNode anchor; ConsAltNode cons; CtypeNode ctype; #ifdef USE_SUBEXP_CALL CallNode call; #endif } u; } Node; #define NULL_NODE ((Node* )0) #define SCANENV_MEMNODES_SIZE 8 #define SCANENV_MEM_NODES(senv) \ (IS_NOT_NULL((senv)->mem_nodes_dynamic) ? \ (senv)->mem_nodes_dynamic : (senv)->mem_nodes_static) typedef struct { OnigOptionType option; OnigCaseFoldType case_fold_flag; OnigEncoding enc; OnigSyntaxType* syntax; BitStatusType capture_history; BitStatusType bt_mem_start; BitStatusType bt_mem_end; BitStatusType backrefed_mem; UChar* pattern; UChar* pattern_end; UChar* error; UChar* error_end; regex_t* reg; /* for reg->names only */ int num_call; #ifdef USE_SUBEXP_CALL UnsetAddrList* unset_addr_list; #endif int num_mem; #ifdef USE_NAMED_GROUP int num_named; #endif int mem_alloc; Node* mem_nodes_static[SCANENV_MEMNODES_SIZE]; Node** mem_nodes_dynamic; #ifdef USE_COMBINATION_EXPLOSION_CHECK int num_comb_exp_check; int comb_exp_max_regnum; int curr_max_regnum; int has_recursion; #endif } ScanEnv; #define IS_SYNTAX_OP(syn, opm) (((syn)->op & (opm)) != 0) #define IS_SYNTAX_OP2(syn, opm) (((syn)->op2 & (opm)) != 0) #define IS_SYNTAX_BV(syn, bvm) (((syn)->behavior & (bvm)) != 0) #ifdef USE_NAMED_GROUP typedef struct { int new_val; } GroupNumRemap; extern int onig_renumber_name_table P_((regex_t* reg, GroupNumRemap* map)); #endif extern int onig_strncmp P_((const UChar* s1, const UChar* s2, int n)); extern void onig_strcpy P_((UChar* dest, const UChar* src, const UChar* end)); extern void onig_scan_env_set_error_string P_((ScanEnv* env, int ecode, UChar* arg, UChar* arg_end)); extern int onig_scan_unsigned_number P_((UChar** src, const UChar* end, OnigEncoding enc)); extern void onig_reduce_nested_quantifier P_((Node* pnode, Node* cnode)); extern void onig_node_conv_to_str_node P_((Node* node, int raw)); extern int onig_node_str_cat P_((Node* node, const UChar* s, const UChar* end)); extern int onig_node_str_set P_((Node* node, const UChar* s, const UChar* end)); extern void onig_node_free P_((Node* node)); extern Node* onig_node_new_enclose P_((int type)); extern Node* onig_node_new_anchor P_((int type)); extern Node* onig_node_new_str P_((const UChar* s, const UChar* end)); extern Node* onig_node_new_list P_((Node* left, Node* right)); extern Node* onig_node_list_add P_((Node* list, Node* x)); extern Node* onig_node_new_alt P_((Node* left, Node* right)); extern void onig_node_str_clear P_((Node* node)); extern int onig_free_node_list P_((void)); extern int onig_names_free P_((regex_t* reg)); extern int onig_parse_make_tree P_((Node** root, const UChar* pattern, const UChar* end, regex_t* reg, ScanEnv* env)); extern int onig_free_shared_cclass_table P_((void)); #ifdef USE_SHARED_UNICODE_TABLE extern int onig_free_shared_unicode_table P_((void)); #endif //USE_SHARED_UNICODE_TABLE #ifdef ONIG_DEBUG #ifdef USE_NAMED_GROUP extern int onig_print_names(FILE*, regex_t*); #endif #endif #endif /* REGPARSE_H */ ================================================ FILE: src/Onigmo/regposerr.c ================================================ /********************************************************************** regposerr.c - Oniguruma (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2007 K.Kosako * 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. */ #define regex_t onig_regex_t #include "regint.h" #undef regex_t #include "onigposix.h" #ifdef HAVE_STRING_H # include #else # include #endif #if defined(__GNUC__) # define ARG_UNUSED __attribute__ ((unused)) #else # define ARG_UNUSED #endif static char* ESTRING[] = { NULL, "failed to match", /* REG_NOMATCH */ "Invalid regular expression", /* REG_BADPAT */ "invalid collating element referenced", /* REG_ECOLLATE */ "invalid character class type referenced", /* REG_ECTYPE */ "bad backslash-escape sequence", /* REG_EESCAPE */ "invalid back reference number", /* REG_ESUBREG */ "imbalanced [ and ]", /* REG_EBRACK */ "imbalanced ( and )", /* REG_EPAREN */ "imbalanced { and }", /* REG_EBRACE */ "invalid repeat range {n,m}", /* REG_BADBR */ "invalid range", /* REG_ERANGE */ "Out of memory", /* REG_ESPACE */ "? * + not preceded by valid regular expression", /* REG_BADRPT */ /* Extended errors */ "internal error", /* REG_EONIG_INTERNAL */ "invalid wide char value", /* REG_EONIG_BADWC */ "invalid argument", /* REG_EONIG_BADARG */ "multi-thread error" /* REG_EONIG_THREAD */ }; #include extern size_t regerror(int posix_ecode, const regex_t* reg ARG_UNUSED, char* buf, size_t size) { char* s; char tbuf[35]; size_t len; if (posix_ecode > 0 && posix_ecode < (int )(sizeof(ESTRING) / sizeof(ESTRING[0]))) { s = ESTRING[posix_ecode]; } else if (posix_ecode == 0) { s = ""; } else { sprintf(tbuf, "undefined error code (%d)", posix_ecode); s = tbuf; } len = strlen(s) + 1; /* use strlen() because s is ascii encoding. */ if (buf != NULL && size > 0) { strncpy(buf, s, size - 1); buf[size - 1] = '\0'; } return len; } ================================================ FILE: src/Onigmo/regposix.c ================================================ /********************************************************************** regposix.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2008 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #define regex_t onig_regex_t #include "regint.h" #undef regex_t #include "onigposix.h" #define ONIG_C(reg) ((onig_regex_t* )((reg)->onig)) #define PONIG_C(reg) ((onig_regex_t** )(&(reg)->onig)) /* #define ENC_STRING_LEN(enc,s,len) len = strlen(s) */ #define ENC_STRING_LEN(enc,s,len) do { \ if (ONIGENC_MBC_MINLEN(enc) == 1) { \ UChar* tmps = (UChar* )(s); \ while (*tmps != 0) tmps++; \ len = (int )(tmps - (UChar* )(s)); \ } \ else { \ len = onigenc_str_bytelen_null(enc, (UChar* )s); \ } \ } while(0) /* #define ENC_STRING_LEN_SE(enc,s,len) len = strlen(s) */ #define ENC_STRING_LEN_SE(enc,s,len) do { \ if (ONIGENC_MBC_MINLEN(enc) == 1) { \ OnigPosition tmps = s; \ while (ONIG_CHARAT(tmps) != 0) tmps++; \ len = tmps - s; \ } \ else { \ len = onigenc_str_bytelen_null_se(it, enc, s); \ } \ } while(0) typedef struct { int onig_err; int posix_err; } O2PERR; static int onig2posix_error_code(int code) { static const O2PERR o2p[] = { { ONIG_MISMATCH, REG_NOMATCH }, { ONIG_NO_SUPPORT_CONFIG, REG_EONIG_INTERNAL }, { ONIGERR_MEMORY, REG_ESPACE }, { ONIGERR_MATCH_STACK_LIMIT_OVER, REG_EONIG_INTERNAL }, { ONIGERR_TYPE_BUG, REG_EONIG_INTERNAL }, { ONIGERR_PARSER_BUG, REG_EONIG_INTERNAL }, { ONIGERR_STACK_BUG, REG_EONIG_INTERNAL }, { ONIGERR_UNDEFINED_BYTECODE, REG_EONIG_INTERNAL }, { ONIGERR_UNEXPECTED_BYTECODE, REG_EONIG_INTERNAL }, { ONIGERR_DEFAULT_ENCODING_IS_NOT_SET, REG_EONIG_BADARG }, { ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR, REG_EONIG_BADARG }, { ONIGERR_INVALID_ARGUMENT, REG_EONIG_BADARG }, { ONIGERR_END_PATTERN_AT_LEFT_BRACE, REG_EBRACE }, { ONIGERR_END_PATTERN_AT_LEFT_BRACKET, REG_EBRACK }, { ONIGERR_EMPTY_CHAR_CLASS, REG_ECTYPE }, { ONIGERR_PREMATURE_END_OF_CHAR_CLASS, REG_ECTYPE }, { ONIGERR_END_PATTERN_AT_ESCAPE, REG_EESCAPE }, { ONIGERR_END_PATTERN_AT_META, REG_EESCAPE }, { ONIGERR_END_PATTERN_AT_CONTROL, REG_EESCAPE }, { ONIGERR_META_CODE_SYNTAX, REG_BADPAT }, { ONIGERR_CONTROL_CODE_SYNTAX, REG_BADPAT }, { ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE, REG_ECTYPE }, { ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE, REG_ECTYPE }, { ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS, REG_ECTYPE }, { ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED, REG_BADRPT }, { ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID, REG_BADRPT }, { ONIGERR_NESTED_REPEAT_OPERATOR, REG_BADRPT }, { ONIGERR_UNMATCHED_CLOSE_PARENTHESIS, REG_EPAREN }, { ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS, REG_EPAREN }, { ONIGERR_END_PATTERN_IN_GROUP, REG_BADPAT }, { ONIGERR_UNDEFINED_GROUP_OPTION, REG_BADPAT }, { ONIGERR_INVALID_POSIX_BRACKET_TYPE, REG_BADPAT }, { ONIGERR_INVALID_LOOK_BEHIND_PATTERN, REG_BADPAT }, { ONIGERR_INVALID_REPEAT_RANGE_PATTERN, REG_BADPAT }, { ONIGERR_TOO_BIG_NUMBER, REG_BADPAT }, { ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE, REG_BADBR }, { ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE, REG_BADBR }, { ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS, REG_ECTYPE }, { ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE, REG_ECTYPE }, { ONIGERR_TOO_MANY_MULTI_BYTE_RANGES, REG_ECTYPE }, { ONIGERR_TOO_SHORT_MULTI_BYTE_STRING, REG_BADPAT }, { ONIGERR_TOO_BIG_BACKREF_NUMBER, REG_ESUBREG }, { ONIGERR_INVALID_BACKREF, REG_ESUBREG }, { ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED, REG_BADPAT }, { ONIGERR_TOO_BIG_WIDE_CHAR_VALUE, REG_EONIG_BADWC }, { ONIGERR_TOO_LONG_WIDE_CHAR_VALUE, REG_EONIG_BADWC }, { ONIGERR_INVALID_CODE_POINT_VALUE, REG_EONIG_BADWC }, { ONIGERR_EMPTY_GROUP_NAME, REG_BADPAT }, { ONIGERR_INVALID_GROUP_NAME, REG_BADPAT }, { ONIGERR_INVALID_CHAR_IN_GROUP_NAME, REG_BADPAT }, { ONIGERR_UNDEFINED_NAME_REFERENCE, REG_BADPAT }, { ONIGERR_UNDEFINED_GROUP_REFERENCE, REG_BADPAT }, { ONIGERR_MULTIPLEX_DEFINED_NAME, REG_BADPAT }, { ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, REG_BADPAT }, { ONIGERR_NEVER_ENDING_RECURSION, REG_BADPAT }, { ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY, REG_BADPAT }, { ONIGERR_INVALID_CHAR_PROPERTY_NAME, REG_BADPAT }, { ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION, REG_EONIG_BADARG }, { ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT, REG_EONIG_THREAD } }; int i; if (code >= 0) return 0; for (i = 0; i < (int )(sizeof(o2p) / sizeof(o2p[0])); i++) { if (code == o2p[i].onig_err) return o2p[i].posix_err; } return REG_EONIG_INTERNAL; /* but, unknown error code */ } extern int regcomp(regex_t* reg, const char* pattern, int posix_options) { int r, len; OnigSyntaxType* syntax = OnigDefaultSyntax; OnigOptionType options; if ((posix_options & REG_EXTENDED) == 0) syntax = ONIG_SYNTAX_POSIX_BASIC; options = syntax->options; if ((posix_options & REG_ICASE) != 0) ONIG_OPTION_ON(options, ONIG_OPTION_IGNORECASE); if ((posix_options & REG_NEWLINE) != 0) { ONIG_OPTION_ON( options, ONIG_OPTION_NEGATE_SINGLELINE); ONIG_OPTION_OFF(options, ONIG_OPTION_SINGLELINE); } reg->comp_options = posix_options; ENC_STRING_LEN(OnigEncDefaultCharEncoding, pattern, len); r = onig_new(PONIG_C(reg), (UChar* )pattern, (UChar* )(pattern + len), options, OnigEncDefaultCharEncoding, syntax, (OnigErrorInfo* )NULL); if (r != ONIG_NORMAL) { return onig2posix_error_code(r); } reg->re_nsub = ONIG_C(reg)->num_mem; return 0; } extern OnigPosition regexec(OnigIterator* it, regex_t* reg, OnigPosition str, size_t nmatch, regmatch_t pmatch[], int posix_options) { OnigPosition r, i, len; OnigPosition end; regmatch_t* pm; OnigOptionType options; options = ONIG_OPTION_POSIX_REGION; if ((posix_options & REG_NOTBOL) != 0) options |= ONIG_OPTION_NOTBOL; if ((posix_options & REG_NOTEOL) != 0) options |= ONIG_OPTION_NOTEOL; if (nmatch == 0 || (reg->comp_options & REG_NOSUB) != 0) { pm = (regmatch_t* )NULL; nmatch = 0; } else if ((int )nmatch < ONIG_C(reg)->num_mem + 1) { pm = (regmatch_t* )xmalloc(sizeof(regmatch_t) * (ONIG_C(reg)->num_mem + 1)); if (pm == NULL) return REG_ESPACE; } else { pm = pmatch; } ENC_STRING_LEN_SE(ONIG_C(reg)->enc, str, len); end = str + len; r = onig_search(it, ONIG_C(reg), str, end, str, end, (OnigRegion* )pm, options); if (r >= 0) { r = 0; /* Match */ if (pm != pmatch && pm != NULL) { xmemcpy(pmatch, pm, sizeof(regmatch_t) * nmatch); } } else if (r == ONIG_MISMATCH) { r = REG_NOMATCH; for (i = 0; i < (int )nmatch; i++) pmatch[i].rm_so = pmatch[i].rm_eo = ONIG_REGION_NOTPOS; } else { r = onig2posix_error_code((int)r); } if (pm != pmatch && pm != NULL) xfree(pm); #if 0 if (reg->re_nsub > nmatch - 1) reg->re_nsub = (nmatch <= 1 ? 0 : nmatch - 1); #endif return r; } extern void regfree(regex_t* reg) { onig_free(ONIG_C(reg)); } extern void reg_set_encoding(int mb_code) { OnigEncoding enc; switch (mb_code) { case REG_POSIX_ENCODING_ASCII: enc = ONIG_ENCODING_ASCII; break; case REG_POSIX_ENCODING_EUC_JP: enc = ONIG_ENCODING_EUC_JP; break; case REG_POSIX_ENCODING_SJIS: enc = ONIG_ENCODING_SJIS; break; case REG_POSIX_ENCODING_UTF8: enc = ONIG_ENCODING_UTF8; break; case REG_POSIX_ENCODING_UTF16_BE: enc = ONIG_ENCODING_UTF16_BE; break; case REG_POSIX_ENCODING_UTF16_LE: enc = ONIG_ENCODING_UTF16_LE; break; default: return ; break; } onigenc_set_default_encoding(enc); } extern int reg_name_to_group_numbers(regex_t* reg, const unsigned char* name, const unsigned char* name_end, int** nums) { return onig_name_to_group_numbers(ONIG_C(reg), name, name_end, nums); } typedef struct { int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*); regex_t* reg; void* arg; } i_wrap; static int i_wrapper(const UChar* name, const UChar* name_end, int ng, int* gs, onig_regex_t* reg ARG_UNUSED, void* arg) { i_wrap* warg = (i_wrap* )arg; return (*warg->func)(name, name_end, ng, gs, warg->reg, warg->arg); } extern int reg_foreach_name(regex_t* reg, int (*func)(const unsigned char*, const unsigned char*,int,int*,regex_t*,void*), void* arg) { i_wrap warg; warg.func = func; warg.reg = reg; warg.arg = arg; return onig_foreach_name(ONIG_C(reg), i_wrapper, &warg); } extern int reg_number_of_names(regex_t* reg) { return onig_number_of_names(ONIG_C(reg)); } ================================================ FILE: src/Onigmo/regsyntax.c ================================================ /********************************************************************** regsyntax.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2006 K.Kosako * Copyright (c) 2011-2012 K.Takata * 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. */ #include "regint.h" OnigSyntaxType OnigSyntaxASIS = { 0 , ONIG_SYN_OP2_INEFFECTIVE_ESCAPE , 0 , ONIG_OPTION_NONE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxWildChar = { ONIG_SYN_OP_VARIABLE_META_CHARACTERS , 0 , 0 , ONIG_OPTION_SINGLELINE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )'?' /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )'*' /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxPosixBasic = { ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | ONIG_SYN_OP_ESC_BRACE_INTERVAL ) , 0 , 0 , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxPosixExtended = { ( SYN_POSIX_COMMON_OP | ONIG_SYN_OP_LPAREN_SUBEXP | ONIG_SYN_OP_BRACE_INTERVAL | ONIG_SYN_OP_PLUS_ONE_INF | ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_VBAR_ALT ) , 0 , ( ONIG_SYN_CONTEXT_INDEP_ANCHORS | ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS | ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS | ONIG_SYN_ALLOW_UNMATCHED_CLOSE_SUBEXP | ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC ) , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_MULTILINE ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxEmacs = { ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_ESC_BRACE_INTERVAL | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | ONIG_SYN_OP_ESC_VBAR_ALT | ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_PLUS_ONE_INF | ONIG_SYN_OP_QMARK_ZERO_ONE | ONIG_SYN_OP_DECIMAL_BACKREF | ONIG_SYN_OP_LINE_ANCHOR | ONIG_SYN_OP_ESC_CONTROL_CHARS ) , ONIG_SYN_OP2_ESC_GNU_BUF_ANCHOR , ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC , ONIG_OPTION_NONE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxGrep = { ( ONIG_SYN_OP_DOT_ANYCHAR | ONIG_SYN_OP_BRACKET_CC | ONIG_SYN_OP_POSIX_BRACKET | ONIG_SYN_OP_ESC_BRACE_INTERVAL | ONIG_SYN_OP_ESC_LPAREN_SUBEXP | ONIG_SYN_OP_ESC_VBAR_ALT | ONIG_SYN_OP_ASTERISK_ZERO_INF | ONIG_SYN_OP_ESC_PLUS_ONE_INF | ONIG_SYN_OP_ESC_QMARK_ZERO_ONE | ONIG_SYN_OP_LINE_ANCHOR | ONIG_SYN_OP_ESC_W_WORD | ONIG_SYN_OP_ESC_B_WORD_BOUND | ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END | ONIG_SYN_OP_DECIMAL_BACKREF ) , 0 , ( ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC | ONIG_SYN_NOT_NEWLINE_IN_NEGATIVE_CC ) , ONIG_OPTION_NONE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxGnuRegex = { SYN_GNU_REGEX_OP , 0 , SYN_GNU_REGEX_BV , ONIG_OPTION_NONE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxJava = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL | ONIG_SYN_OP2_CCLASS_SET_OP | ONIG_SYN_OP2_ESC_V_VTAB | ONIG_SYN_OP2_ESC_U_HEX4 | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_DIFFERENT_LEN_ALT_LOOK_BEHIND ) , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_ASCII_RANGE | ONIG_OPTION_WORD_BOUND_ALL_RANGE ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; /* Perl 5.8 */ OnigSyntaxType OnigSyntaxPerl58 = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER | ONIG_SYN_OP2_QMARK_LPAREN_CONDITION) , SYN_GNU_REGEX_BV , ONIG_OPTION_SINGLELINE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; /* Perl 5.8 + named group */ OnigSyntaxType OnigSyntaxPerl58_NG = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER | ONIG_SYN_OP2_QMARK_LPAREN_CONDITION | ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF | ONIG_SYN_OP2_ESC_G_SUBEXP_CALL ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP | ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME ) , ONIG_OPTION_SINGLELINE , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; /* Perl 5.10+ */ OnigSyntaxType OnigSyntaxPerl = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE | ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER | ONIG_SYN_OP2_QMARK_LPAREN_CONDITION | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL | ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK | ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP | ONIG_SYN_OP2_QMARK_SUBEXP_CALL | ONIG_SYN_OP2_ESC_G_BRACE_BACKREF | ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP | ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP | ONIG_SYN_OP2_ESC_K_NAMED_BACKREF ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME | ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL ) , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_CAPTURE_GROUP ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; OnigSyntaxType OnigSyntaxPython = { (( SYN_GNU_REGEX_OP | ONIG_SYN_OP_QMARK_NON_GREEDY | ONIG_SYN_OP_ESC_OCTAL3 | ONIG_SYN_OP_ESC_X_HEX2 | ONIG_SYN_OP_ESC_X_BRACE_HEX8 | ONIG_SYN_OP_ESC_CONTROL_CHARS | ONIG_SYN_OP_ESC_C_CONTROL ) & ~ONIG_SYN_OP_ESC_LTGT_WORD_BEGIN_END ) , ( ONIG_SYN_OP2_QMARK_GROUP_EFFECT | ONIG_SYN_OP2_OPTION_PERL | ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY | ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT | ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT | ONIG_SYN_OP2_ESC_V_VTAB | ONIG_SYN_OP2_ESC_U_HEX4 | ONIG_SYN_OP2_QMARK_LPAREN_CONDITION | ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP ) , ( SYN_GNU_REGEX_BV | ONIG_SYN_ALLOW_INTERVAL_LOW_ABBREV ) , ( ONIG_OPTION_SINGLELINE | ONIG_OPTION_ASCII_RANGE ) , { (OnigCodePoint )'\\' /* esc */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar '.' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anytime '*' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* zero or one time '?' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* one or more time '+' */ , (OnigCodePoint )ONIG_INEFFECTIVE_META_CHAR /* anychar anytime */ } }; extern int onig_set_default_syntax(OnigSyntaxType* syntax) { if (IS_NULL(syntax)) syntax = ONIG_SYNTAX_RUBY; OnigDefaultSyntax = syntax; return 0; } extern void onig_copy_syntax(OnigSyntaxType* to, const OnigSyntaxType* from) { *to = *from; } extern void onig_set_syntax_op(OnigSyntaxType* syntax, unsigned int op) { syntax->op = op; } extern void onig_set_syntax_op2(OnigSyntaxType* syntax, unsigned int op2) { syntax->op2 = op2; } extern void onig_set_syntax_behavior(OnigSyntaxType* syntax, unsigned int behavior) { syntax->behavior = behavior; } extern void onig_set_syntax_options(OnigSyntaxType* syntax, OnigOptionType options) { syntax->options = options; } extern unsigned int onig_get_syntax_op(OnigSyntaxType* syntax) { return syntax->op; } extern unsigned int onig_get_syntax_op2(OnigSyntaxType* syntax) { return syntax->op2; } extern unsigned int onig_get_syntax_behavior(OnigSyntaxType* syntax) { return syntax->behavior; } extern OnigOptionType onig_get_syntax_options(OnigSyntaxType* syntax) { return syntax->options; } #ifdef USE_VARIABLE_META_CHARS extern int onig_set_meta_char(OnigSyntaxType* enc, unsigned int what, OnigCodePoint code) { switch (what) { case ONIG_META_CHAR_ESCAPE: enc->meta_char_table.esc = code; break; case ONIG_META_CHAR_ANYCHAR: enc->meta_char_table.anychar = code; break; case ONIG_META_CHAR_ANYTIME: enc->meta_char_table.anytime = code; break; case ONIG_META_CHAR_ZERO_OR_ONE_TIME: enc->meta_char_table.zero_or_one_time = code; break; case ONIG_META_CHAR_ONE_OR_MORE_TIME: enc->meta_char_table.one_or_more_time = code; break; case ONIG_META_CHAR_ANYCHAR_ANYTIME: enc->meta_char_table.anychar_anytime = code; break; default: return ONIGERR_INVALID_ARGUMENT; break; } return 0; } #endif /* USE_VARIABLE_META_CHARS */ ================================================ FILE: src/Onigmo/regtrav.c ================================================ /********************************************************************** regtrav.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2004 K.Kosako * Copyright (c) 2011 K.Takata * 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. */ #include "regint.h" #ifdef USE_CAPTURE_HISTORY static int capture_tree_traverse(OnigCaptureTreeNode* node, int at, int(*callback_func)(int,OnigPosition,OnigPosition,int,int,void*), int level, void* arg) { int r, i; if (node == (OnigCaptureTreeNode* )0) return 0; if ((at & ONIG_TRAVERSE_CALLBACK_AT_FIRST) != 0) { r = (*callback_func)(node->group, node->beg, node->end, level, ONIG_TRAVERSE_CALLBACK_AT_FIRST, arg); if (r != 0) return r; } for (i = 0; i < node->num_childs; i++) { r = capture_tree_traverse(node->childs[i], at, callback_func, level + 1, arg); if (r != 0) return r; } if ((at & ONIG_TRAVERSE_CALLBACK_AT_LAST) != 0) { r = (*callback_func)(node->group, node->beg, node->end, level, ONIG_TRAVERSE_CALLBACK_AT_LAST, arg); if (r != 0) return r; } return 0; } #endif /* USE_CAPTURE_HISTORY */ extern int onig_capture_tree_traverse(OnigRegion* region, int at, int(*callback_func)(int,OnigPosition,OnigPosition,int,int,void*), void* arg) { #ifdef USE_CAPTURE_HISTORY return capture_tree_traverse(region->history_root, at, callback_func, 0, arg); #else return ONIG_NO_SUPPORT_CONFIG; #endif } ================================================ FILE: src/Onigmo/regversion.c ================================================ /********************************************************************** regversion.c - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2002-2009 K.Kosako * Copyright (c) 2011-2013 K.Takata * 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. */ #include "config.h" #include "oniguruma.h" #include extern const char* onig_version(void) { static char s[12]; sprintf(s, "%d.%d.%d", ONIGURUMA_VERSION_MAJOR, ONIGURUMA_VERSION_MINOR, ONIGURUMA_VERSION_TEENY); return s; } extern const char* onig_copyright(void) { static char s[80]; sprintf(s, "Onigmo %d.%d.%d : Copyright (C) 2002-2009 K.Kosako, " "2011-2013 K.Takata", ONIGURUMA_VERSION_MAJOR, ONIGURUMA_VERSION_MINOR, ONIGURUMA_VERSION_TEENY); return s; } ================================================ FILE: src/Onigmo/sample/Makefile.am ================================================ noinst_PROGRAMS = encode listcap names posix simple sql syntax crnl libname = $(top_builddir)/libonig.la LDADD = $(libname) INCLUDES = -I$(top_srcdir) -I$(includedir) encode_SOURCES = encode.c listcap_SOURCES = listcap.c names_SOURCES = names.c posix_SOURCES = posix.c simple_SOURCES = simple.c sql_SOURCES = sql.c syntax_SOURCES = syntax.c sampledir = $(top_builddir)/sample test: encode listcap names posix simple sql syntax @$(sampledir)/encode @$(sampledir)/listcap @$(sampledir)/names @$(sampledir)/posix @$(sampledir)/simple @$(sampledir)/sql @$(sampledir)/syntax ================================================ FILE: src/Onigmo/sample/Makefile.in ================================================ # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program 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. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = encode$(EXEEXT) listcap$(EXEEXT) names$(EXEEXT) \ posix$(EXEEXT) simple$(EXEEXT) sql$(EXEEXT) syntax$(EXEEXT) \ crnl$(EXEEXT) subdir = sample DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) crnl_SOURCES = crnl.c crnl_OBJECTS = crnl.$(OBJEXT) crnl_LDADD = $(LDADD) crnl_DEPENDENCIES = $(libname) am_encode_OBJECTS = encode.$(OBJEXT) encode_OBJECTS = $(am_encode_OBJECTS) encode_LDADD = $(LDADD) encode_DEPENDENCIES = $(libname) am_listcap_OBJECTS = listcap.$(OBJEXT) listcap_OBJECTS = $(am_listcap_OBJECTS) listcap_LDADD = $(LDADD) listcap_DEPENDENCIES = $(libname) am_names_OBJECTS = names.$(OBJEXT) names_OBJECTS = $(am_names_OBJECTS) names_LDADD = $(LDADD) names_DEPENDENCIES = $(libname) am_posix_OBJECTS = posix.$(OBJEXT) posix_OBJECTS = $(am_posix_OBJECTS) posix_LDADD = $(LDADD) posix_DEPENDENCIES = $(libname) am_simple_OBJECTS = simple.$(OBJEXT) simple_OBJECTS = $(am_simple_OBJECTS) simple_LDADD = $(LDADD) simple_DEPENDENCIES = $(libname) am_sql_OBJECTS = sql.$(OBJEXT) sql_OBJECTS = $(am_sql_OBJECTS) sql_LDADD = $(LDADD) sql_DEPENDENCIES = $(libname) am_syntax_OBJECTS = syntax.$(OBJEXT) syntax_OBJECTS = $(am_syntax_OBJECTS) syntax_LDADD = $(LDADD) syntax_DEPENDENCIES = $(libname) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = crnl.c $(encode_SOURCES) $(listcap_SOURCES) $(names_SOURCES) \ $(posix_SOURCES) $(simple_SOURCES) $(sql_SOURCES) \ $(syntax_SOURCES) DIST_SOURCES = crnl.c $(encode_SOURCES) $(listcap_SOURCES) \ $(names_SOURCES) $(posix_SOURCES) $(simple_SOURCES) \ $(sql_SOURCES) $(syntax_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LTVERSION = @LTVERSION@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ RUBYDIR = @RUBYDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STATISTICS = @STATISTICS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ libname = $(top_builddir)/libonig.la LDADD = $(libname) INCLUDES = -I$(top_srcdir) -I$(includedir) encode_SOURCES = encode.c listcap_SOURCES = listcap.c names_SOURCES = names.c posix_SOURCES = posix.c simple_SOURCES = simple.c sql_SOURCES = sql.c syntax_SOURCES = syntax.c sampledir = $(top_builddir)/sample all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sample/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign sample/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list crnl$(EXEEXT): $(crnl_OBJECTS) $(crnl_DEPENDENCIES) @rm -f crnl$(EXEEXT) $(LINK) $(crnl_OBJECTS) $(crnl_LDADD) $(LIBS) encode$(EXEEXT): $(encode_OBJECTS) $(encode_DEPENDENCIES) @rm -f encode$(EXEEXT) $(LINK) $(encode_OBJECTS) $(encode_LDADD) $(LIBS) listcap$(EXEEXT): $(listcap_OBJECTS) $(listcap_DEPENDENCIES) @rm -f listcap$(EXEEXT) $(LINK) $(listcap_OBJECTS) $(listcap_LDADD) $(LIBS) names$(EXEEXT): $(names_OBJECTS) $(names_DEPENDENCIES) @rm -f names$(EXEEXT) $(LINK) $(names_OBJECTS) $(names_LDADD) $(LIBS) posix$(EXEEXT): $(posix_OBJECTS) $(posix_DEPENDENCIES) @rm -f posix$(EXEEXT) $(LINK) $(posix_OBJECTS) $(posix_LDADD) $(LIBS) simple$(EXEEXT): $(simple_OBJECTS) $(simple_DEPENDENCIES) @rm -f simple$(EXEEXT) $(LINK) $(simple_OBJECTS) $(simple_LDADD) $(LIBS) sql$(EXEEXT): $(sql_OBJECTS) $(sql_DEPENDENCIES) @rm -f sql$(EXEEXT) $(LINK) $(sql_OBJECTS) $(sql_LDADD) $(LIBS) syntax$(EXEEXT): $(syntax_OBJECTS) $(syntax_DEPENDENCIES) @rm -f syntax$(EXEEXT) $(LINK) $(syntax_OBJECTS) $(syntax_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crnl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listcap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/names.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posix.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syntax.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am test: encode listcap names posix simple sql syntax @$(sampledir)/encode @$(sampledir)/listcap @$(sampledir)/names @$(sampledir)/posix @$(sampledir)/simple @$(sampledir)/sql @$(sampledir)/syntax # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ================================================ FILE: src/Onigmo/sample/crnl.c ================================================ /* * crnl.c 2007/05/30 K.Kosako * * !!! You should enable USE_CRNL_AS_LINE_TERMINATOR. !!! * * USE_CRNL_AS_LINE_TERMINATOR config test program. */ #include #include #include "oniguruma.h" #define USE_UNICODE_ALL_LINE_TERMINATORS static int nfail = 0; static void result(int no, OnigPosition from, OnigPosition to, OnigPosition expected_from, OnigPosition expected_to) { fprintf(stderr, "%3d: ", no); if (from == expected_from && to == expected_to) { fprintf(stderr, "Success\n"); } else { fprintf(stderr, "Fail: expected: (%d-%d), result: (%d-%d)\n", (int)expected_from, (int)expected_to, (int)from, (int)to); nfail++; } } static int x0(int no, char* pattern_arg, char* str_arg, int start_offset, int expected_from, int expected_to, int backward) { OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; UChar *pattern, *str; OnigIterator it = {onig_default_charat, str_arg}; pattern = (UChar* )pattern_arg; str = (UChar* )str_arg; r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_NEWLINE_CRLF, ONIG_ENCODING_UTF8, ONIG_SYNTAX_DEFAULT, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } region = onig_region_new(); end = strlen((char* )str); if (backward) { start = end + start_offset; range = 0; } else { start = start_offset; range = end; } r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0 || r == ONIG_MISMATCH) { result(no, region->beg[0], region->end[0], expected_from, expected_to); } else if (r == ONIG_MISMATCH) { result(no, r, -1, expected_from, expected_to); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); return 0; } static int x(int no, char* pattern_arg, char* str_arg, int expected_from, int expected_to) { return x0(no, pattern_arg, str_arg, 0, expected_from, expected_to, 0); } static int f0(int no, char* pattern_arg, char* str_arg, int start_offset, int backward) { return x0(no, pattern_arg, str_arg, start_offset, -1, -1, backward); } static int f(int no, char* pattern_arg, char* str_arg) { return x(no, pattern_arg, str_arg, -1, -1); } extern int main(int argc, char* argv[]) { x( 1, "", "\r\n", 0, 0); /* x( 2, ".", "\r\n", 0, 1); */ f( 2, ".", "\r\n"); f( 3, "..", "\r\n"); x( 4, "^", "\r\n", 0, 0); x( 5, "\\n^", "\r\nf", 1, 2); x( 6, "\\n^a", "\r\na", 1, 3); x( 7, "$", "\r\n", 0, 0); x( 8, "T$", "T\r\n", 0, 1); #ifdef USE_UNICODE_ALL_LINE_TERMINATORS x( 9, "T$", "T\raT\r\n", 0, 1); #else x( 9, "T$", "T\raT\r\n", 3, 4); #endif x(10, "\\z", "\r\n", 2, 2); f(11, "a\\z", "a\r\n"); x(12, "\\Z", "\r\n", 0, 0); x(13, "\\Z", "\r\na", 3, 3); x(14, "\\Z", "\r\n\r\n\n", 4, 4); x(15, "\\Z", "\r\n\r\nX", 5, 5); x(16, "a\\Z", "a\r\n", 0, 1); x(17, "aaaaaaaaaaaaaaa\\Z", "aaaaaaaaaaaaaaa\r\n", 0, 15); x(18, "a|$", "b\r\n", 1, 1); #ifdef USE_UNICODE_ALL_LINE_TERMINATORS x(19, "$|b", "\rb", 0, 0); #else x(19, "$|b", "\rb", 1, 2); #endif x(20, "a$|ab$", "\r\nab\r\n", 2, 4); x(21, "a|\\Z", "b\r\n", 1, 1); #ifdef USE_UNICODE_ALL_LINE_TERMINATORS x(22, "\\Z|b", "\rb", 0, 0); #else x(22, "\\Z|b", "\rb", 1, 2); #endif x(23, "a\\Z|ab\\Z", "\r\nab\r\n", 2, 4); x(24, "(?=a$).", "a\r\n", 0, 1); #ifdef USE_UNICODE_ALL_LINE_TERMINATORS x(25, "(?=a$).", "a\r", 0, 1); f(26, "(?!a$)..", "a\r"); #else f(25, "(?=a$).", "a\r"); x(26, "(?!a$)..", "a\r", 0, 2); #endif /* x(27, "(?<=a$).\\n", "a\r\n", 1, 3); */ x(27, "(?<=a$)\\r\\n", "a\r\n", 1, 3); /* f(28, "(? 0) { fprintf(stderr, "\n"); fprintf(stderr, "!!! You have to enable USE_CRNL_AS_LINE_TERMINATOR\n"); fprintf(stderr, "!!! in regenc.h for this test program.\n"); fprintf(stderr, "\n"); } return 0; } ================================================ FILE: src/Onigmo/sample/encode.c ================================================ /* * encode.c */ #include #include "oniguruma.h" static int search(OnigIterator* it, regex_t* reg, OnigPosition str, OnigPosition end) { OnigPosition r; OnigPosition start, range; OnigRegion *region; region = onig_region_new(); start = str; range = end; r = onig_search(it, reg, str, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i; fprintf(stderr, "match at %d (%s)\n", (int)r, ONIGENC_NAME(onig_get_encoding(reg))); for (i = 0; i < region->num_regs; i++) { fprintf(stderr, "%d: (%ld-%ld)\n", i, (int)region->beg[i], (int)region->end[i]); } } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail (%s)\n", ONIGENC_NAME(onig_get_encoding(reg))); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); fprintf(stderr, " (%s)\n", ONIGENC_NAME(onig_get_encoding(reg))); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); return 0; } static int exec(OnigEncoding enc, OnigOptionType options, char* apattern, char* astr) { OnigPosition r; OnigPosition end; regex_t* reg; OnigErrorInfo einfo; UChar* pattern = (UChar* )apattern; UChar* str = (UChar* )astr; OnigIterator it = {onig_default_charat, str}; onig_init(); r = onig_new(®, pattern, pattern + onigenc_str_bytelen_null(enc, pattern), options, enc, ONIG_SYNTAX_DEFAULT, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } end = onigenc_str_bytelen_null(enc, str); r = search(&it, reg, 0, end); onig_free(reg); onig_end(); return 0; } static OnigCaseFoldType CF = ONIGENC_CASE_FOLD_MIN; #if 0 static void set_case_fold(OnigCaseFoldType cf) { CF = cf; } #endif static int exec_deluxe(OnigEncoding pattern_enc, OnigEncoding str_enc, OnigOptionType options, char* apattern, char* astr) { OnigPosition r; OnigPosition end; regex_t* reg; OnigCompileInfo ci; OnigErrorInfo einfo; UChar* pattern = (UChar* )apattern; UChar* str = (UChar* )astr; OnigIterator it = {onig_default_charat, str}; ci.num_of_elements = 5; ci.pattern_enc = pattern_enc; ci.target_enc = str_enc; ci.syntax = ONIG_SYNTAX_DEFAULT; ci.option = options; ci.case_fold_flag = CF; r = onig_new_deluxe(®, pattern, pattern + onigenc_str_bytelen_null(pattern_enc, pattern), &ci, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } end = onigenc_str_bytelen_null(str_enc, str); r = search(&it, reg, 0, end); onig_free(reg); onig_end(); return 0; } extern int main(int argc, char* argv[]) { int r; /* ISO 8859-1 test */ static unsigned char str[] = { 0xc7, 0xd6, 0xfe, 0xea, 0xe0, 0xe2, 0x00 }; static unsigned char pattern[] = { 0xe7, 0xf6, 0xde, '\\', 'w', '+', 0x00 }; r = exec(ONIG_ENCODING_CP1251, ONIG_OPTION_IGNORECASE, "aBc", " AbC"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, " [a-c\337z] ", " SS "); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, " [\330-\341] ", " SS "); r = exec(ONIG_ENCODING_ISO_8859_2, ONIG_OPTION_IGNORECASE, "\337 ", " Ss "); r = exec(ONIG_ENCODING_ISO_8859_2, ONIG_OPTION_IGNORECASE, "SS ", " \337 "); r = exec(ONIG_ENCODING_ISO_8859_2, ONIG_OPTION_IGNORECASE, "\\A\\S\\z", "ss"); r = exec(ONIG_ENCODING_ISO_8859_2, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_3, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_4, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_5, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_6, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_7, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_8, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_9, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_10, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_11, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_13, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_14, ONIG_OPTION_IGNORECASE, "[ac]+", "bbbaAaCCC"); r = exec(ONIG_ENCODING_ISO_8859_15, ONIG_OPTION_IGNORECASE, (char* )pattern, (char* )str); r = exec(ONIG_ENCODING_ISO_8859_16, ONIG_OPTION_IGNORECASE, (char* )pattern, (char* )str); r = exec(ONIG_ENCODING_KOI8_R, ONIG_OPTION_NONE, "a+", "bbbaaaccc"); r = exec(ONIG_ENCODING_EUC_TW, ONIG_OPTION_NONE, "b*a+?c+", "bbbaaaccc"); r = exec(ONIG_ENCODING_EUC_KR, ONIG_OPTION_NONE, "a+", "bbbaaaccc"); r = exec(ONIG_ENCODING_EUC_CN, ONIG_OPTION_NONE, "c+", "bbbaaaccc"); r = exec(ONIG_ENCODING_BIG5, ONIG_OPTION_NONE, "a+", "bbbaaaccc"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, "\337", "SS"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, "SS", "\337"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, "SSb\337ssc", "a\337bSS\337cd"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, "[a\337]{0,2}", "aSS"); r = exec(ONIG_ENCODING_ISO_8859_1, ONIG_OPTION_IGNORECASE, "is", "iss"); r = exec_deluxe(ONIG_ENCODING_ASCII, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_NONE, "a+", "\000b\000a\000a\000a\000c\000c\000\000"); r = exec_deluxe(ONIG_ENCODING_ASCII, ONIG_ENCODING_UTF16_LE, ONIG_OPTION_NONE, "a+", "b\000a\000a\000a\000a\000c\000\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_LE, ONIG_OPTION_NONE, "\000b\000a\000a\000a\000c\000c\000\000", "x\000b\000a\000a\000a\000c\000c\000\000\000"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\337", "\000S\000S\000\000"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "SS", "\000\337\000\000"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF16_LE, ONIG_OPTION_IGNORECASE, "\337", "S\000S\000\000\000"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF32_BE, ONIG_OPTION_IGNORECASE, "SS", "\000\000\000\337\000\000\000\000"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF32_LE, ONIG_OPTION_IGNORECASE, "\337", "S\000\000\000S\000\000\000\000\000\000\000"); r = exec(ONIG_ENCODING_UTF16_BE, ONIG_OPTION_NONE, "\000[\000[\000:\000a\000l\000n\000u\000m\000:\000]\000]\000+\000\000", "\000#\002\120\000a\000Z\012\077\012\076\012\075\000\000"); /* 0x0a3d == \012\075 : is not alnum */ /* 0x0a3e == \012\076 : is alnum */ r = exec(ONIG_ENCODING_UTF16_BE, ONIG_OPTION_NONE, "\000\\\000d\000+\000\000", "\0003\0001\377\020\377\031\377\032\000\000"); r = exec(ONIG_ENCODING_GB18030, ONIG_OPTION_IGNORECASE, "(Aa\\d)+", "BaA5Aa0234"); r = exec_deluxe(ONIG_ENCODING_ISO_8859_1, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_NONE, "^\\P{Hiragana}\\p{^Hiragana}(\\p{Hiragana}+)$", "\060\100\060\240\060\101\060\102\060\226\060\237\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000[\000\337\000]\000\000", "\000S\000S\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000[\000\337\000]\000\000", "\000s\000S\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000^\000[\000\001\000-\377\375\000]\000$\000\000", "\000s\000S\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000S\000S\000\000", "\000S\000T\000\337\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000S\000T\000S\000S\000\000", "\000S\000t\000s\000S\000\000"); { UChar pat[] = { 0x1f, 0xfc, 0x00, 0x00 }; UChar str1[] = { 0x21, 0x26, 0x1f, 0xbe, 0x00, 0x00 }; UChar str2[] = { 0x1f, 0xf3, 0x00, 0x00 }; r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, (char* )pat, (char* )str1); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, (char* )pat, (char* )str2); } #if 0 /* You should define USE_UNICODE_CASE_FOLD_TURKISH_AZERI in regenc.h. */ set_case_fold(ONIGENC_CASE_FOLD_TURKISH_AZERI); r = exec_deluxe(ONIG_ENCODING_UTF8, ONIG_ENCODING_UTF8, ONIG_OPTION_IGNORECASE, "Ii", "\304\261\304\260"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\000I\000i\000\000", "\001\061\001\060\000\000"); r = exec_deluxe(ONIG_ENCODING_UTF16_BE, ONIG_ENCODING_UTF16_BE, ONIG_OPTION_IGNORECASE, "\001\061\001\060\000\000", "\000I\000i\000\000"); set_case_fold(ONIGENC_CASE_FOLD_MIN); #endif return 0; } ================================================ FILE: src/Onigmo/sample/listcap.c ================================================ /* * listcap.c * * capture history (?@...) sample. */ #include #include #include "oniguruma.h" static int node_callback(int group, OnigPosition beg, OnigPosition end, int level, int at, void* arg) { int i; if (at != ONIG_TRAVERSE_CALLBACK_AT_FIRST) return -1; /* error */ /* indent */ for (i = 0; i < level * 2; i++) fputc(' ', stderr); fprintf(stderr, "%d: (%ld-%ld)\n", group, (int)beg, (int)end); return 0; } extern int ex(unsigned char* str, unsigned char* pattern, OnigSyntaxType* syntax) { OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; OnigIterator it = {onig_default_charat, str}; r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_DEFAULT, ONIG_ENCODING_ASCII, syntax, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } fprintf(stderr, "number of captures: %d\n", onig_number_of_captures(reg)); fprintf(stderr, "number of capture histories: %d\n", onig_number_of_capture_histories(reg)); region = onig_region_new(); end = strlen((char* )str); start = 0; range = end; r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i; fprintf(stderr, "match at %d\n", (int)r); for (i = 0; i < region->num_regs; i++) { fprintf(stderr, "%d: (%ld-%ld)\n", i, (long)region->beg[i], (long)region->end[i]); } fprintf(stderr, "\n"); r = onig_capture_tree_traverse(region, ONIG_TRAVERSE_CALLBACK_AT_FIRST, node_callback, (void* )0); } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail\n"); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); return 0; } extern int main(int argc, char* argv[]) { int r; OnigSyntaxType syn; static UChar* str1 = (UChar* )"((())())"; static UChar* pattern1 = (UChar* )"\\g

(?@

\\(\\g\\)){0}(?@(?:\\g

)*|){0}"; static UChar* str2 = (UChar* )"x00x00x00"; static UChar* pattern2 = (UChar* )"(?@x(?@\\d+))+"; static UChar* str3 = (UChar* )"0123"; static UChar* pattern3 = (UChar* )"(?@.)(?@.)(?@.)(?@.)"; /* enable capture hostory */ onig_copy_syntax(&syn, ONIG_SYNTAX_DEFAULT); onig_set_syntax_op2(&syn, onig_get_syntax_op2(&syn) | ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY); r = ex(str1, pattern1, &syn); r = ex(str2, pattern2, &syn); r = ex(str3, pattern3, &syn); onig_end(); return 0; } ================================================ FILE: src/Onigmo/sample/names.c ================================================ /* * names.c -- example of group name callback. */ #include #include #include "oniguruma.h" static int name_callback(const UChar* name, const UChar* name_end, int ngroup_num, int* group_nums, regex_t* reg, void* arg) { int i, gn, ref; char* s; OnigRegion *region = (OnigRegion* )arg; for (i = 0; i < ngroup_num; i++) { gn = group_nums[i]; ref = onig_name_to_backref_number(reg, name, name_end, region); s = (ref == gn ? "*" : ""); fprintf(stderr, "%s (%d): ", name, gn); fprintf(stderr, "(%ld-%ld) %s\n", (int)region->beg[gn], (int)region->end[gn], s); } return 0; /* 0: continue */ } extern int main(int argc, char* argv[]) { OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; static UChar* pattern = (UChar* )"(?a*)(?b*)(?c*)"; static UChar* str = (UChar* )"aaabbbbcc"; OnigIterator it = {onig_default_charat, str}; r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_DEFAULT, ONIG_ENCODING_ASCII, ONIG_SYNTAX_DEFAULT, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } fprintf(stderr, "number of names: %d\n", onig_number_of_names(reg)); region = onig_region_new(); end = strlen((char* )str); start = 0; range = end; r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { fprintf(stderr, "match at %d\n\n", r); r = onig_foreach_name(reg, name_callback, (void* )region); } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail\n"); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); onig_end(); return 0; } ================================================ FILE: src/Onigmo/sample/posix.c ================================================ /* * posix.c */ #include #define regex_t onig_regex_t #include "regint.h" #undef regex_t #include "onigposix.h" typedef unsigned char UChar; static int x(regex_t* reg, unsigned char* pattern, unsigned char* str) { int r, i; char buf[200]; regmatch_t pmatch[20]; OnigIterator it = {onig_default_charat, str}; r = (int)regexec(&it, reg, 0, reg->re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, reg, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } if (r == REG_NOMATCH) { fprintf(stderr, "FAIL: /%s/ '%s'\n", pattern, str); } else { fprintf(stderr, "OK: /%s/ '%s'\n", pattern, str); for (i = 0; i <= (int )reg->re_nsub; i++) { fprintf(stderr, "%d: %d-%d\n", i, pmatch[i].rm_so, pmatch[i].rm_eo); } } return 0; } extern int main(int argc, char* argv[]) { int r; char buf[200]; regex_t reg; UChar* pattern; /* default syntax (ONIG_SYNTAX_RUBY) */ pattern = (UChar* )"^a+b{2,7}[c-f]?$|uuu"; r = regcomp(®, (char* )pattern, REG_EXTENDED); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } x(®, pattern, (UChar* )"aaabbbbd"); /* POSIX Basic RE (REG_EXTENDED is not specified.) */ pattern = (UChar* )"^a+b{2,7}[c-f]?|uuu"; r = regcomp(®, (char* )pattern, 0); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } x(®, pattern, (UChar* )"a+b{2,7}d?|uuu"); /* POSIX Basic RE (REG_EXTENDED is not specified.) */ pattern = (UChar* )"^a*b\\{2,7\\}\\([c-f]\\)$"; r = regcomp(®, (char* )pattern, 0); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } x(®, pattern, (UChar* )"aaaabbbbbbd"); /* POSIX Extended RE */ onig_set_default_syntax(ONIG_SYNTAX_POSIX_EXTENDED); pattern = (UChar* )"^a+b{2,7}[c-f]?)$|uuu"; r = regcomp(®, (char* )pattern, REG_EXTENDED); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } x(®, pattern, (UChar* )"aaabbbbd)"); pattern = (UChar* )"^b."; r = regcomp(®, (char* )pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(stderr, "ERROR: %s\n", buf); return -1; } x(®, pattern, (UChar* )"a\nb\n"); regfree(®); return 0; } ================================================ FILE: src/Onigmo/sample/simple.c ================================================ /* * simple.c */ #include #include #include "oniguruma.h" extern int main(int argc, char* argv[]) { OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; static UChar* pattern = (UChar* )"a(.*)b|[e-f]+"; static UChar* str = (UChar* )"zzzzaffffffffb"; OnigIterator it = {onig_default_charat, str}; r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_DEFAULT, ONIG_ENCODING_ASCII, ONIG_SYNTAX_DEFAULT, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } region = onig_region_new(); end = strlen((char* )str); start = 0; range = end; r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i; fprintf(stderr, "match at %d\n", r); for (i = 0; i < region->num_regs; i++) { fprintf(stderr, "%d: (%ld-%ld)\n", i, (int)region->beg[i], (int)region->end[i]); } } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail\n"); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); onig_end(); return 0; } ================================================ FILE: src/Onigmo/sample/sql.c ================================================ /* * sql.c */ #include #include #include "oniguruma.h" extern int main(int argc, char* argv[]) { static OnigSyntaxType SQLSyntax; OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; static UChar* pattern = (UChar* )"\\_%\\\\__zz"; static UChar* str = (UChar* )"a_abcabcabc\\ppzz"; OnigIterator it = {onig_default_charat, str}; onig_set_syntax_op (&SQLSyntax, ONIG_SYN_OP_VARIABLE_META_CHARACTERS); onig_set_syntax_op2 (&SQLSyntax, 0); onig_set_syntax_behavior(&SQLSyntax, 0); onig_set_syntax_options (&SQLSyntax, ONIG_OPTION_MULTILINE); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ESCAPE, (OnigCodePoint )'\\'); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ANYCHAR, (OnigCodePoint )'_'); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ANYTIME, ONIG_INEFFECTIVE_META_CHAR); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ZERO_OR_ONE_TIME, ONIG_INEFFECTIVE_META_CHAR); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ONE_OR_MORE_TIME, ONIG_INEFFECTIVE_META_CHAR); onig_set_meta_char(&SQLSyntax, ONIG_META_CHAR_ANYCHAR_ANYTIME, (OnigCodePoint )'%'); r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_DEFAULT, ONIG_ENCODING_ASCII, &SQLSyntax, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } region = onig_region_new(); end = strlen((char* )str); start = 0; range = end; r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i; fprintf(stderr, "match at %d\n", r); for (i = 0; i < region->num_regs; i++) { fprintf(stderr, "%d: (%ld-%ld)\n", i, (int)region->beg[i], (int)region->end[i]); } } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail\n"); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); onig_end(); return 0; } ================================================ FILE: src/Onigmo/sample/syntax.c ================================================ /* * syntax.c */ #include #include #include "oniguruma.h" extern int exec(OnigSyntaxType* syntax, char* apattern, char* astr) { OnigPosition r; OnigPosition start, range, end; regex_t* reg; OnigErrorInfo einfo; OnigRegion *region; UChar* pattern = (UChar* )apattern; UChar* str = (UChar* )astr; OnigIterator it = {onig_default_charat, str}; r = onig_new(®, pattern, pattern + strlen((char* )pattern), ONIG_OPTION_DEFAULT, ONIG_ENCODING_ASCII, syntax, &einfo); if (r != ONIG_NORMAL) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(stderr, "ERROR: %s\n", s); return -1; } region = onig_region_new(); end = strlen((char* )str); start = 0; range = end; r = onig_search(&it, reg, 0, end, start, range, region, ONIG_OPTION_NONE); if (r >= 0) { int i; fprintf(stderr, "match at %d\n", r); for (i = 0; i < region->num_regs; i++) { fprintf(stderr, "%d: (%ld-%ld)\n", i, (int)region->beg[i], (int)region->end[i]); } } else if (r == ONIG_MISMATCH) { fprintf(stderr, "search fail\n"); } else { /* error */ char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(stderr, "ERROR: %s\n", s); return -1; } onig_region_free(region, 1 /* 1:free self, 0:free contents only */); onig_free(reg); onig_end(); return 0; } extern int main(int argc, char* argv[]) { int r; r = exec(ONIG_SYNTAX_PERL, "\\p{XDigit}\\P{XDigit}\\p{^XDigit}\\P{^XDigit}\\p{XDigit}", "bgh3a"); r = exec(ONIG_SYNTAX_JAVA, "\\p{XDigit}\\P{XDigit}[a-c&&b-g]", "bgc"); r = exec(ONIG_SYNTAX_ASIS, "abc def* e+ g?ddd[a-rvvv] (vv){3,7}hv\\dvv(?:aczui ss)\\W\\w$", "abc def* e+ g?ddd[a-rvvv] (vv){3,7}hv\\dvv(?:aczui ss)\\W\\w$"); onig_end(); return 0; } ================================================ FILE: src/Onigmo/st.c ================================================ /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */ /* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */ #include #include #include #ifdef _WIN32 #include #endif #include "regint.h" #include "st.h" typedef struct st_table_entry st_table_entry; struct st_table_entry { unsigned int hash; st_data_t key; st_data_t record; st_table_entry *next; }; #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 /* * DEFAULT_MAX_DENSITY is the default for the largest we allow the * average number of items per bin before increasing the number of * bins * * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins * allocated initially * */ static int numcmp(long, long); static int numhash(long); static struct st_hash_type type_numhash = { numcmp, numhash, }; /* extern int strcmp(const char *, const char *); */ static int strhash(const char *); static struct st_hash_type type_strhash = { strcmp, strhash, }; static void rehash(st_table *); #define alloc(type) (type*)xmalloc((unsigned)sizeof(type)) #define Calloc(n,s) (char*)xcalloc((n),(s)) #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)((x),(y)) == 0) #define do_hash(key,table) (unsigned int)(*(table)->type->hash)((key)) #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) /* * MINSIZE is the minimum size of a dictionary. */ #define MINSIZE 8 /* Table of prime numbers 2^n+a, 2<=n<=30. */ static const long primes[] = { 8 + 3, 16 + 3, 32 + 5, 64 + 3, 128 + 3, 256 + 27, 512 + 9, 1024 + 9, 2048 + 5, 4096 + 3, 8192 + 27, 16384 + 43, 32768 + 3, 65536 + 45, 131072 + 29, 262144 + 3, 524288 + 21, 1048576 + 7, 2097152 + 17, 4194304 + 15, 8388608 + 9, 16777216 + 43, 33554432 + 35, 67108864 + 15, 134217728 + 29, 268435456 + 3, 536870912 + 11, 1073741824 + 85, 0 }; static int new_size(size) int size; { int i; #if 0 for (i=3; i<31; i++) { if ((1< size) return 1< size) return primes[i]; } /* Ran out of polynomials */ return -1; /* should raise exception */ #endif } #ifdef HASH_LOG static int collision = 0; static int init_st = 0; static void stat_col() { FILE *f = fopen("/tmp/col", "w"); fprintf(f, "collision: %d\n", collision); fclose(f); } #endif st_table* st_init_table_with_size(type, size) struct st_hash_type *type; int size; { st_table *tbl; #ifdef HASH_LOG if (init_st == 0) { init_st = 1; atexit(stat_col); } #endif size = new_size(size); /* round up to prime number */ tbl = alloc(st_table); tbl->type = type; tbl->num_entries = 0; tbl->num_bins = size; tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*)); return tbl; } st_table* st_init_table(type) struct st_hash_type *type; { return st_init_table_with_size(type, 0); } st_table* st_init_numtable(void) { return st_init_table(&type_numhash); } st_table* st_init_numtable_with_size(size) int size; { return st_init_table_with_size(&type_numhash, size); } st_table* st_init_strtable(void) { return st_init_table(&type_strhash); } st_table* st_init_strtable_with_size(size) int size; { return st_init_table_with_size(&type_strhash, size); } void st_free_table(table) st_table *table; { register st_table_entry *ptr, *next; int i; for(i = 0; i < table->num_bins; i++) { ptr = table->bins[i]; while (ptr != 0) { next = ptr->next; free(ptr); ptr = next; } } free(table->bins); free(table); } #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) #ifdef HASH_LOG #define COLLISION collision++ #else #define COLLISION #endif #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins;\ ptr = (table)->bins[bin_pos];\ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\ COLLISION;\ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ ptr = ptr->next;\ }\ ptr = ptr->next;\ }\ } while (0) int st_lookup(table, key, value) st_table *table; register st_data_t key; st_data_t *value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); if (ptr == 0) { return 0; } else { if (value != 0) *value = ptr->record; return 1; } } #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ do {\ st_table_entry *entry;\ if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) {\ rehash(table);\ bin_pos = hash_val % table->num_bins;\ }\ \ entry = alloc(st_table_entry);\ \ entry->hash = hash_val;\ entry->key = key;\ entry->record = value;\ entry->next = table->bins[bin_pos];\ table->bins[bin_pos] = entry;\ table->num_entries++;\ } while (0) int st_insert(table, key, value) register st_table *table; register st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); if (ptr == 0) { ADD_DIRECT(table, key, value, hash_val, bin_pos); return 0; } else { ptr->record = value; return 1; } } void st_add_direct(table, key, value) st_table *table; st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; hash_val = do_hash(key, table); bin_pos = hash_val % table->num_bins; ADD_DIRECT(table, key, value, hash_val, bin_pos); } static void rehash(table) register st_table *table; { register st_table_entry *ptr, *next, **new_bins; int i, old_num_bins = table->num_bins, new_num_bins; unsigned int hash_val; new_num_bins = new_size(old_num_bins+1); new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*)); for(i = 0; i < old_num_bins; i++) { ptr = table->bins[i]; while (ptr != 0) { next = ptr->next; hash_val = ptr->hash % new_num_bins; ptr->next = new_bins[hash_val]; new_bins[hash_val] = ptr; ptr = next; } } free(table->bins); table->num_bins = new_num_bins; table->bins = new_bins; } st_table* st_copy(old_table) st_table *old_table; { st_table *new_table; st_table_entry *ptr, *entry; int i, num_bins = old_table->num_bins; new_table = alloc(st_table); if (new_table == 0) { return 0; } *new_table = *old_table; new_table->bins = (st_table_entry**) Calloc((unsigned)num_bins, sizeof(st_table_entry*)); if (new_table->bins == 0) { free(new_table); return 0; } for(i = 0; i < num_bins; i++) { new_table->bins[i] = 0; ptr = old_table->bins[i]; while (ptr != 0) { entry = alloc(st_table_entry); if (entry == 0) { free(new_table->bins); free(new_table); return 0; } *entry = *ptr; entry->next = new_table->bins[i]; new_table->bins[i] = entry; ptr = ptr->next; } } return new_table; } int st_delete(table, key, value) register st_table *table; register st_data_t *key; st_data_t *value; { unsigned int hash_val; st_table_entry *tmp; register st_table_entry *ptr; hash_val = do_hash_bin(*key, table); ptr = table->bins[hash_val]; if (ptr == 0) { if (value != 0) *value = 0; return 0; } if (EQUAL(table, *key, ptr->key)) { table->bins[hash_val] = ptr->next; table->num_entries--; if (value != 0) *value = ptr->record; *key = ptr->key; free(ptr); return 1; } for(; ptr->next != 0; ptr = ptr->next) { if (EQUAL(table, ptr->next->key, *key)) { tmp = ptr->next; ptr->next = ptr->next->next; table->num_entries--; if (value != 0) *value = tmp->record; *key = tmp->key; free(tmp); return 1; } } return 0; } int st_delete_safe(table, key, value, never) register st_table *table; register st_data_t *key; st_data_t *value; st_data_t never; { unsigned int hash_val; register st_table_entry *ptr; hash_val = do_hash_bin(*key, table); ptr = table->bins[hash_val]; if (ptr == 0) { if (value != 0) *value = 0; return 0; } for(; ptr != 0; ptr = ptr->next) { if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { table->num_entries--; *key = ptr->key; if (value != 0) *value = ptr->record; ptr->key = ptr->record = never; return 1; } } return 0; } static int #if defined(__GNUC__) delete_never(st_data_t key __attribute__ ((unused)), st_data_t value, st_data_t never) #else delete_never(key, value, never) st_data_t key, value, never; #endif { if (value == never) return ST_DELETE; return ST_CONTINUE; } void st_cleanup_safe(table, never) st_table *table; st_data_t never; { int num_entries = table->num_entries; st_foreach(table, delete_never, never); table->num_entries = num_entries; } int st_foreach(table, func, arg) st_table *table; int (*func)(); st_data_t arg; { st_table_entry *ptr, *last, *tmp; enum st_retval retval; int i; for(i = 0; i < table->num_bins; i++) { last = 0; for(ptr = table->bins[i]; ptr != 0;) { retval = (*func)(ptr->key, ptr->record, arg); switch (retval) { case ST_CHECK: /* check if hash is modified during iteration */ tmp = 0; if (i < table->num_bins) { for (tmp = table->bins[i]; tmp; tmp=tmp->next) { if (tmp == ptr) break; } } if (!tmp) { /* call func with error notice */ return 1; } /* fall through */ case ST_CONTINUE: last = ptr; ptr = ptr->next; break; case ST_STOP: return 0; case ST_DELETE: tmp = ptr; if (last == 0) { table->bins[i] = ptr->next; } else { last->next = ptr->next; } ptr = ptr->next; free(tmp); table->num_entries--; } } } return 0; } static int strhash(string) register const char *string; { register int c; #ifdef HASH_ELFHASH register unsigned int h = 0, g; while ((c = *string++) != '\0') { h = ( h << 4 ) + c; if ( g = h & 0xF0000000 ) h ^= g >> 24; h &= ~g; } return h; #elif HASH_PERL register int val = 0; while ((c = *string++) != '\0') { val += c; val += (val << 10); val ^= (val >> 6); } val += (val << 3); val ^= (val >> 11); return val + (val << 15); #else register int val = 0; while ((c = *string++) != '\0') { val = val*997 + c; } return val + (val>>5); #endif } static int numcmp(x, y) long x, y; { return x != y; } static int numhash(n) long n; { return n; } ================================================ FILE: src/Onigmo/st.h ================================================ /* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */ /* @(#) st.h 5.1 89/12/14 */ #ifndef ST_INCLUDED #define ST_INCLUDED typedef uintptr_t st_data_t; #define ST_DATA_T_DEFINED typedef struct st_table st_table; struct st_hash_type { int (*compare)(); int (*hash)(); }; struct st_table { struct st_hash_type *type; int num_bins; int num_entries; struct st_table_entry **bins; }; #define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0) enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK}; #ifndef _ # define _(args) args #endif #ifndef ANYARGS # ifdef __cplusplus # define ANYARGS ... # else # define ANYARGS # endif #endif st_table *st_init_table _((struct st_hash_type *)); st_table *st_init_table_with_size _((struct st_hash_type *, int)); st_table *st_init_numtable _((void)); st_table *st_init_numtable_with_size _((int)); st_table *st_init_strtable _((void)); st_table *st_init_strtable_with_size _((int)); int st_delete _((st_table *, st_data_t *, st_data_t *)); int st_delete_safe _((st_table *, st_data_t *, st_data_t *, st_data_t)); int st_insert _((st_table *, st_data_t, st_data_t)); int st_lookup _((st_table *, st_data_t, st_data_t *)); int st_foreach _((st_table *, int (*)(ANYARGS), st_data_t)); void st_add_direct _((st_table *, st_data_t, st_data_t)); void st_free_table _((st_table *)); void st_cleanup_safe _((st_table *, st_data_t)); st_table *st_copy _((st_table *)); #define ST_NUMCMP ((int (*)()) 0) #define ST_NUMHASH ((int (*)()) -2) #define st_numcmp ST_NUMCMP #define st_numhash ST_NUMHASH #endif /* ST_INCLUDED */ ================================================ FILE: src/Onigmo/test.rb ================================================ # test.rb # Copyright (C) 2003-2006 K.Kosako (sndgk393 AT ybb DOT ne DOT jp) $SILENT = false if (ARGV.size > 0 and ARGV[0] == '-s') $SILENT = true end def pr(result, reg, str, n = 0, *range) printf("%s /%s/:'%s'", result, reg.source, str) if (n.class == Fixnum) printf(":%d", n) if n != 0 if (range.size > 0) if (range[3].nil?) printf(" (%d-%d : X-X)", range[0], range[1]) else printf(" (%d-%d : %d-%d)", range[0], range[1], range[2], range[3]) end end else printf(" %s", n) end printf("\n") end def rok(result_opt, reg, str, n = 0, *range) result = "OK" + result_opt result += " " * (7 - result.length) pr(result, reg, str, n, *range) unless $SILENT $rok += 1 end def rfail(result_opt, reg, str, n = 0, *range) result = "FAIL" + result_opt result += " " * (7 - result.length) pr(result, reg, str, n, *range) $rfail += 1 end def x(reg, str, s, e, n = 0) m = reg.match(str) if m if (m.size() <= n) rfail("(%d)" % (m.size()-1), reg, str, n) else if (m.begin(n) == s && m.end(n) == e) rok("", reg, str, n) else rfail("", reg, str, n, s, e, m.begin(n), m.end(n)) end end else rfail("", reg, str, n) end end def n(reg, str) m = reg.match(str) if m rfail("(N)", reg, str, 0) else rok("(N)", reg, str, 0) end end def r(reg, str, index, pos = nil) if (pos) res = str.rindex(reg, pos) else res = str.rindex(reg) end if res if (res == index) rok("(r)", reg, str) else rfail("(r)", reg, str, [res, '-', index]) end else rfail("(r)", reg, str) end end def i(reg, str, s = 0, e = 0, n = 0) # ignore end ### main ### $rok = $rfail = 0 x(/\M-Z/n, "\xDA", 0, 1) # from URI::ABS_URI n(/^ ([a-zA-Z][-+.a-zA-Z\d]*): (?# 1: scheme) (?: ((?:[-_.!~*'()a-zA-Z\d;?:@&=+$,]|%[a-fA-F\d]{2})(?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*) (?# 2: opaque) | (?:(?: \/\/(?: (?:(?:((?:[-_.!~*'()a-zA-Z\d;:&=+$,]|%[a-fA-F\d]{2})*)@)? (?# 3: userinfo) (?:((?:(?:(?:[a-zA-Z\d](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:[-a-zA-Z\d]*[a-zA-Z\d])?)\.?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-fA-F\d]{1,4}:)*[a-fA-F\d]{1,4})?::(?:(?:[a-fA-F\d]{1,4}:)*(?:[a-fA-F\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)\]))(?::(\d*))?))?(?# 4: host, 5: port) | ((?:[-_.!~*'()a-zA-Z\d$,;+@&=+]|%[a-fA-F\d]{2})+) (?# 6: registry) ) | (?!\/\/)) (?# XXX: '\/\/' is the mark for hostport) (\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*(?:\/(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*(?:;(?:[-_.!~*'()a-zA-Z\d:@&=+$,]|%[a-fA-F\d]{2})*)*)*)? (?# 7: path) )(?:\?((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 8: query) ) (?:\#((?:[-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]]|%[a-fA-F\d]{2})*))? (?# 9: fragment) $/xn, "http://example.org/Andr\xC3\xA9") def test_sb(enc) $KCODE = enc x(//, '', 0, 0) x(/^/, '', 0, 0) x(/$/, '', 0, 0) x(/\G/, '', 0, 0) x(/\A/, '', 0, 0) x(/\Z/, '', 0, 0) x(/\z/, '', 0, 0) x(/^$/, '', 0, 0) x(/\ca/, "\001", 0, 1) x(/\C-b/, "\002", 0, 1) x(/\c\\/, "\034", 0, 1) x(/q[\c\\]/, "q\034", 0, 2) x(//, 'a', 0, 0) x(/a/, 'a', 0, 1) x(/\x61/, 'a', 0, 1) x(/aa/, 'aa', 0, 2) x(/aaa/, 'aaa', 0, 3) x(/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 0, 35) x(/ab/, 'ab', 0, 2) x(/b/, 'ab', 1, 2) x(/bc/, 'abc', 1, 3) x(/(?i:#RET#)/, '#INS##RET#', 5, 10) x(/\17/, "\017", 0, 1) x(/\x1f/, "\x1f", 0, 1) x(/a(?#....\\JJJJ)b/, 'ab', 0, 2) x(Regexp.new("(?x)\ta .\n+b"), '0a123b4', 1, 6) x(/(?x) G (o O(?-x)oO) g L/, "GoOoOgLe", 0, 7) x(/./, 'a', 0, 1) n(/./, '') x(/../, 'ab', 0, 2) x(/\w/, 'e', 0, 1) n(/\W/, 'e') x(/\s/, ' ', 0, 1) x(/\S/, 'b', 0, 1) x(/\d/, '4', 0, 1) n(/\D/, '4') x(/\b/, 'z ', 0, 0) x(/\b/, ' z', 1, 1) x(/\B/, 'zz ', 1, 1) x(/\B/, 'z ', 2, 2) x(/\B/, ' z', 0, 0) x(/[ab]/, 'b', 0, 1) n(/[ab]/, 'c') x(/[a-z]/, 't', 0, 1) n(/[^a]/, 'a') x(/[^a]/, "\n", 0, 1) x(/[]]/, ']', 0, 1) n(/[^]]/, ']') x(/[\^]+/, '0^^1', 1, 3) x(/[b-]/, 'b', 0, 1) x(/[b-]/, '-', 0, 1) x(/[\w]/, 'z', 0, 1) n(/[\w]/, ' ') x(/[\W]/, 'b$', 1, 2) x(/[\d]/, '5', 0, 1) n(/[\d]/, 'e') x(/[\D]/, 't', 0, 1) n(/[\D]/, '3') x(/[\s]/, ' ', 0, 1) n(/[\s]/, 'a') x(/[\S]/, 'b', 0, 1) n(/[\S]/, ' ') x(/[\w\d]/, '2', 0, 1) n(/[\w\d]/, ' ') x(/[[:upper:]]/, 'B', 0, 1) x(/[*[:xdigit:]+]/, '+', 0, 1) x(/[*[:xdigit:]+]/, 'GHIKK-9+*', 6, 7) x(/[*[:xdigit:]+]/, '-@^+', 3, 4) n(/[[:upper]]/, 'A') x(/[[:upper]]/, ':', 0, 1) x(/[\044-\047]/, "\046", 0, 1) x(/[\x5a-\x5c]/, "\x5b", 0, 1) x(/[\x6A-\x6D]/, "\x6c", 0, 1) n(/[\x6A-\x6D]/, "\x6E") n(/^[0-9A-F]+ 0+ UNDEF /, '75F 00000000 SECT14A notype () External | _rb_apply') x(/[\[]/, '[', 0, 1) x(/[\]]/, ']', 0, 1) x(/[&]/, '&', 0, 1) x(/[[ab]]/, 'b', 0, 1) x(/[[ab]c]/, 'c', 0, 1) n(/[[^a]]/, 'a') n(/[^[a]]/, 'a') x(/[[ab]&&bc]/, 'b', 0, 1) n(/[[ab]&&bc]/, 'a') n(/[[ab]&&bc]/, 'c') x(/[a-z&&b-y&&c-x]/, 'w', 0, 1) n(/[^a-z&&b-y&&c-x]/, 'w') x(/[[^a&&a]&&a-z]/, 'b', 0, 1) n(/[[^a&&a]&&a-z]/, 'a') x(/[[^a-z&&bcdef]&&[^c-g]]/, 'h', 0, 1) n(/[[^a-z&&bcdef]&&[^c-g]]/, 'c') x(/[^[^abc]&&[^cde]]/, 'c', 0, 1) x(/[^[^abc]&&[^cde]]/, 'e', 0, 1) n(/[^[^abc]&&[^cde]]/, 'f') x(/[a-&&-a]/, '-', 0, 1) n(/[a\-&&\-a]/, '&') n(/\wabc/, ' abc') x(/a\Wbc/, 'a bc', 0, 4) x(/a.b.c/, 'aabbc', 0, 5) x(/.\wb\W..c/, 'abb bcc', 0, 7) x(/\s\wzzz/, ' zzzz', 0, 5) x(/aa.b/, 'aabb', 0, 4) n(/.a/, 'ab') x(/.a/, 'aa', 0, 2) x(/^a/, 'a', 0, 1) x(/^a$/, 'a', 0, 1) x(/^\w$/, 'a', 0, 1) n(/^\w$/, ' ') x(/^\wab$/, 'zab', 0, 3) x(/^\wabcdef$/, 'zabcdef', 0, 7) x(/^\w...def$/, 'zabcdef', 0, 7) x(/\w\w\s\Waaa\d/, 'aa aaa4', 0, 8) x(/\A\Z/, '', 0, 0) x(/\Axyz/, 'xyz', 0, 3) x(/xyz\Z/, 'xyz', 0, 3) x(/xyz\z/, 'xyz', 0, 3) x(/a\Z/, 'a', 0, 1) x(/\Gaz/, 'az', 0, 2) n(/\Gz/, 'bza') n(/az\G/, 'az') n(/az\A/, 'az') n(/a\Az/, 'az') x(/\^\$/, '^$', 0, 2) x(/^x?y/, 'xy', 0, 2) x(/^(x?y)/, 'xy', 0, 2) x(/\w/, '_', 0, 1) n(/\W/, '_') x(/(?=z)z/, 'z', 0, 1) n(/(?=z)./, 'a') x(/(?!z)a/, 'a', 0, 1) n(/(?!z)a/, 'z') x(/(?i:a)/, 'a', 0, 1) x(/(?i:a)/, 'A', 0, 1) x(/(?i:A)/, 'a', 0, 1) n(/(?i:A)/, 'b') x(/(?i:[A-Z])/, 'a', 0, 1) x(/(?i:[f-m])/, 'H', 0, 1) x(/(?i:[f-m])/, 'h', 0, 1) n(/(?i:[f-m])/, 'e') x(/(?i:[A-c])/, 'D', 0, 1) #n(/(?i:[a-C])/, 'D') # changed spec.(error) 2003/09/17 #n(/(?i:[b-C])/, 'A') #x(/(?i:[a-C])/, 'B', 0, 1) #n(/(?i:[c-X])/, '[') n(/(?i:[^a-z])/, 'A') n(/(?i:[^a-z])/, 'a') x(/(?i:[!-k])/, 'Z', 0, 1) x(/(?i:[!-k])/, '7', 0, 1) x(/(?i:[T-}])/, 'b', 0, 1) x(/(?i:[T-}])/, '{', 0, 1) x(/(?i:\?a)/, '?A', 0, 2) x(/(?i:\*A)/, '*a', 0, 2) n(/./, "\n") x(/(?m:.)/, "\n", 0, 1) x(/(?m:a.)/, "a\n", 0, 2) x(/(?m:.b)/, "a\nb", 1, 3) x(/.*abc/, "dddabdd\nddabc", 8, 13) x(/(?m:.*abc)/, "dddabddabc", 0, 10) n(/(?i)(?-i)a/, "A") n(/(?i)(?-i:a)/, "A") x(/a?/, '', 0, 0) x(/a?/, 'b', 0, 0) x(/a?/, 'a', 0, 1) x(/a*/, '', 0, 0) x(/a*/, 'a', 0, 1) x(/a*/, 'aaa', 0, 3) x(/a*/, 'baaaa', 0, 0) n(/a+/, '') x(/a+/, 'a', 0, 1) x(/a+/, 'aaaa', 0, 4) x(/a+/, 'aabbb', 0, 2) x(/a+/, 'baaaa', 1, 5) x(/.?/, '', 0, 0) x(/.?/, 'f', 0, 1) x(/.?/, "\n", 0, 0) x(/.*/, '', 0, 0) x(/.*/, 'abcde', 0, 5) x(/.+/, 'z', 0, 1) x(/.+/, "zdswer\n", 0, 6) x(/(.*)a\1f/, "babfbac", 0, 4) x(/(.*)a\1f/, "bacbabf", 3, 7) x(/((.*)a\2f)/, "bacbabf", 3, 7) x(/(.*)a\1f/, "baczzzzzz\nbazz\nzzzzbabf", 19, 23) x(/a|b/, 'a', 0, 1) x(/a|b/, 'b', 0, 1) x(/|a/, 'a', 0, 0) x(/(|a)/, 'a', 0, 0) x(/ab|bc/, 'ab', 0, 2) x(/ab|bc/, 'bc', 0, 2) x(/z(?:ab|bc)/, 'zbc', 0, 3) x(/a(?:ab|bc)c/, 'aabc', 0, 4) x(/ab|(?:ac|az)/, 'az', 0, 2) x(/a|b|c/, 'dc', 1, 2) x(/a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz/, 'pqr', 0, 2) n(/a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz/, 'mn') x(/a|^z/, 'ba', 1, 2) x(/a|^z/, 'za', 0, 1) x(/a|\Gz/, 'bza', 2, 3) x(/a|\Gz/, 'za', 0, 1) x(/a|\Az/, 'bza', 2, 3) x(/a|\Az/, 'za', 0, 1) x(/a|b\Z/, 'ba', 1, 2) x(/a|b\Z/, 'b', 0, 1) x(/a|b\z/, 'ba', 1, 2) x(/a|b\z/, 'b', 0, 1) x(/\w|\s/, ' ', 0, 1) n(/\w|\w/, ' ') x(/\w|%/, '%', 0, 1) x(/\w|[&$]/, '&', 0, 1) x(/[b-d]|[^e-z]/, 'a', 0, 1) x(/(?:a|[c-f])|bz/, 'dz', 0, 1) x(/(?:a|[c-f])|bz/, 'bz', 0, 2) x(/abc|(?=zz)..f/, 'zzf', 0, 3) x(/abc|(?!zz)..f/, 'abf', 0, 3) x(/(?=za)..a|(?=zz)..a/, 'zza', 0, 3) n(/(?>a|abd)c/, 'abdc') x(/(?>abd|a)c/, 'abdc', 0, 4) x(/a?|b/, 'a', 0, 1) x(/a?|b/, 'b', 0, 0) x(/a?|b/, '', 0, 0) x(/a*|b/, 'aa', 0, 2) x(/a*|b*/, 'ba', 0, 0) x(/a*|b*/, 'ab', 0, 1) x(/a+|b*/, '', 0, 0) x(/a+|b*/, 'bbb', 0, 3) x(/a+|b*/, 'abbb', 0, 1) n(/a+|b+/, '') x(/(a|b)?/, 'b', 0, 1) x(/(a|b)*/, 'ba', 0, 2) x(/(a|b)+/, 'bab', 0, 3) x(/(ab|ca)+/, 'caabbc', 0, 4) x(/(ab|ca)+/, 'aabca', 1, 5) x(/(ab|ca)+/, 'abzca', 0, 2) x(/(a|bab)+/, 'ababa', 0, 5) x(/(a|bab)+/, 'ba', 1, 2) x(/(a|bab)+/, 'baaaba', 1, 4) x(/(?:a|b)(?:a|b)/, 'ab', 0, 2) x(/(?:a*|b*)(?:a*|b*)/, 'aaabbb', 0, 3) x(/(?:a*|b*)(?:a+|b+)/, 'aaabbb', 0, 6) x(/(?:a+|b+){2}/, 'aaabbb', 0, 6) x(/h{0,}/, 'hhhh', 0, 4) x(/(?:a+|b+){1,2}/, 'aaabbb', 0, 6) n(/ax{2}*a/, '0axxxa1') n(/a.{0,2}a/, "0aXXXa0") n(/a.{0,2}?a/, "0aXXXa0") n(/a.{0,2}?a/, "0aXXXXa0") x(/^a{2,}?a$/, "aaa", 0, 3) x(/^[a-z]{2,}?$/, "aaa", 0, 3) x(/(?:a+|\Ab*)cc/, 'cc', 0, 2) n(/(?:a+|\Ab*)cc/, 'abcc') x(/(?:^a+|b+)*c/, 'aabbbabc', 6, 8) x(/(?:^a+|b+)*c/, 'aabbbbc', 0, 7) x(/a|(?i)c/, 'C', 0, 1) x(/(?i)c|a/, 'C', 0, 1) i(/(?i)c|a/, 'A', 0, 1) # different spec. x(/(?i:c)|a/, 'C', 0, 1) n(/(?i:c)|a/, 'A') x(/[abc]?/, 'abc', 0, 1) x(/[abc]*/, 'abc', 0, 3) x(/[^abc]*/, 'abc', 0, 0) n(/[^abc]+/, 'abc') x(/a??/, 'aaa', 0, 0) x(/ba??b/, 'bab', 0, 3) x(/a*?/, 'aaa', 0, 0) x(/ba*?/, 'baa', 0, 1) x(/ba*?b/, 'baab', 0, 4) x(/a+?/, 'aaa', 0, 1) x(/ba+?/, 'baa', 0, 2) x(/ba+?b/, 'baab', 0, 4) x(/(?:a?)??/, 'a', 0, 0) x(/(?:a??)?/, 'a', 0, 0) x(/(?:a?)+?/, 'aaa', 0, 1) x(/(?:a+)??/, 'aaa', 0, 0) x(/(?:a+)??b/, 'aaab', 0, 4) i(/(?:ab)?{2}/, '', 0, 0) # GNU regex bug x(/(?:ab)?{2}/, 'ababa', 0, 4) x(/(?:ab)*{0}/, 'ababa', 0, 0) x(/(?:ab){3,}/, 'abababab', 0, 8) n(/(?:ab){3,}/, 'abab') x(/(?:ab){2,4}/, 'ababab', 0, 6) x(/(?:ab){2,4}/, 'ababababab', 0, 8) x(/(?:ab){2,4}?/, 'ababababab', 0, 4) x(/(?:ab){,}/, 'ab{,}', 0, 5) x(/(?:abc)+?{2}/, 'abcabcabc', 0, 6) x(/(?:X*)(?i:xa)/, 'XXXa', 0, 4) x(/(d+)([^abc]z)/, 'dddz', 0, 4) x(/([^abc]*)([^abc]z)/, 'dddz', 0, 4) x(/(\w+)(\wz)/, 'dddz', 0, 4) x(/(a)/, 'a', 0, 1, 1) x(/(ab)/, 'ab', 0, 2, 1) x(/((ab))/, 'ab', 0, 2) x(/((ab))/, 'ab', 0, 2, 1) x(/((ab))/, 'ab', 0, 2, 2) x(/((((((((((((((((((((ab))))))))))))))))))))/, 'ab', 0, 2, 20) x(/(ab)(cd)/, 'abcd', 0, 2, 1) x(/(ab)(cd)/, 'abcd', 2, 4, 2) x(/()(a)bc(def)ghijk/, 'abcdefghijk', 3, 6, 3) x(/(()(a)bc(def)ghijk)/, 'abcdefghijk', 3, 6, 4) x(/(^a)/, 'a', 0, 1) x(/(a)|(a)/, 'ba', 1, 2, 1) x(/(^a)|(a)/, 'ba', 1, 2, 2) x(/(a?)/, 'aaa', 0, 1, 1) x(/(a*)/, 'aaa', 0, 3, 1) x(/(a*)/, '', 0, 0, 1) x(/(a+)/, 'aaaaaaa', 0, 7, 1) x(/(a+|b*)/, 'bbbaa', 0, 3, 1) x(/(a+|b?)/, 'bbbaa', 0, 1, 1) x(/(abc)?/, 'abc', 0, 3, 1) x(/(abc)*/, 'abc', 0, 3, 1) x(/(abc)+/, 'abc', 0, 3, 1) x(/(xyz|abc)+/, 'abc', 0, 3, 1) x(/([xyz][abc]|abc)+/, 'abc', 0, 3, 1) x(/((?i:abc))/, 'AbC', 0, 3, 1) x(/(abc)(?i:\1)/, 'abcABC', 0, 6) x(/((?m:a.c))/, "a\nc", 0, 3, 1) x(/((?=az)a)/, 'azb', 0, 1, 1) x(/abc|(.abd)/, 'zabd', 0, 4, 1) x(/(?:abc)|(ABC)/, 'abc', 0, 3) x(/(?i:(abc))|(zzz)/, 'ABC', 0, 3, 1) x(/a*(.)/, 'aaaaz', 4, 5, 1) x(/a*?(.)/, 'aaaaz', 0, 1, 1) x(/a*?(c)/, 'aaaac', 4, 5, 1) x(/[bcd]a*(.)/, 'caaaaz', 5, 6, 1) x(/(\Abb)cc/, 'bbcc', 0, 2, 1) n(/(\Abb)cc/, 'zbbcc') x(/(^bb)cc/, 'bbcc', 0, 2, 1) n(/(^bb)cc/, 'zbbcc') x(/cc(bb$)/, 'ccbb', 2, 4, 1) n(/cc(bb$)/, 'ccbbb') #n(/\1/, 'a') # compile error on Oniguruma n(/(\1)/, '') n(/\1(a)/, 'aa') n(/(a(b)\1)\2+/, 'ababb') n(/(?:(?:\1|z)(a))+$/, 'zaa') x(/(?:(?:\1|z)(a))+$/, 'zaaa', 0, 4) x(/(a)(?=\1)/, 'aa', 0, 1) n(/(a)$|\1/, 'az') x(/(a)\1/, 'aa', 0, 2) n(/(a)\1/, 'ab') x(/(a?)\1/, 'aa', 0, 2) x(/(a??)\1/, 'aa', 0, 0) x(/(a*)\1/, 'aaaaa', 0, 4) x(/(a*)\1/, 'aaaaa', 0, 2, 1) x(/a(b*)\1/, 'abbbb', 0, 5) x(/a(b*)\1/, 'ab', 0, 1) x(/(a*)(b*)\1\2/, 'aaabbaaabb', 0, 10) x(/(a*)(b*)\2/, 'aaabbbb', 0, 7) x(/(((((((a*)b))))))c\7/, 'aaabcaaa', 0, 8) x(/(((((((a*)b))))))c\7/, 'aaabcaaa', 0, 3, 7) x(/(a)(b)(c)\2\1\3/, 'abcbac', 0, 6) x(/([a-d])\1/, 'cc', 0, 2) x(/(\w\d\s)\1/, 'f5 f5 ', 0, 6) n(/(\w\d\s)\1/, 'f5 f5') x(/(who|[a-c]{3})\1/, 'whowho', 0, 6) x(/...(who|[a-c]{3})\1/, 'abcwhowho', 0, 9) x(/(who|[a-c]{3})\1/, 'cbccbc', 0, 6) x(/(^a)\1/, 'aa', 0, 2) n(/(^a)\1/, 'baa') n(/(a$)\1/, 'aa') n(/(ab\Z)\1/, 'ab') x(/(a*\Z)\1/, 'a', 1, 1) x(/.(a*\Z)\1/, 'ba', 1, 2) x(/(.(abc)\2)/, 'zabcabc', 0, 7, 1) x(/(.(..\d.)\2)/, 'z12341234', 0, 9, 1) x(/((?i:az))\1/, 'AzAz', 0, 4) n(/((?i:az))\1/, 'Azaz') x(/(?<=a)b/, 'ab', 1, 2) n(/(?<=a)b/, 'bb') x(/(?<=a|b)b/, 'bb', 1, 2) x(/(?<=a|bc)b/, 'bcb', 2, 3) x(/(?<=a|bc)b/, 'ab', 1, 2) x(/(?<=a|bc||defghij|klmnopq|r)z/, 'rz', 1, 2) x(/(a)\g<1>/, 'aa', 0, 2) x(/(?a)/, 'a', 0, 1) x(/(?ab)\g/, 'abab', 0, 4) x(/(?.zv.)\k/, 'azvbazvb', 0, 8) x(/(?<=\g)|-\zEND (?XyZ)/, 'XyZ', 3, 3) x(/(?|a\g)+/, '', 0, 0) x(/(?|\(\g\))+$/, '()(())', 0, 6) x(/\g(?.){0}/, 'X', 0, 1, 1) x(/\g(abc|df(?.YZ){2,8}){0}/, 'XYZ', 0, 3) x(/\A(?(a\g)|)\z/, 'aaaa', 0, 4) x(/(?|\g\g)\z|\zEND (?a|(b)\g)/, 'bbbbabba', 0, 8) x(/(?\w+\sx)a+\k/, ' fg xaaaaaaaafg x', 2, 18) x(/(z)()()(?<_9>a)\g<_9>/, 'zaa', 2, 3, 1) x(/(.)(((?<_>a)))\k<_>/, 'zaa', 0, 3) x(/((?\d)|(?\w))(\k|\k)/, 'ff', 0, 2) x(/(?:(?)|(?efg))\k/, '', 0, 0) x(/(?:(?abc)|(?efg))\k/, 'abcefgefg', 3, 9) n(/(?:(?abc)|(?efg))\k/, 'abcefg') x(/(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\k$/, 'a-pyumpyum', 2, 10) x(/(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\k$/, 'xxxxabcdefghijklmnabcdefghijklmn', 4, 18, 14) x(/(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?aaa)(?)$/, 'aaa', 0, 3, 16) x(/(?a|\(\g\))/, 'a', 0, 1) x(/(?a|\(\g\))/, '((((((a))))))', 0, 13) x(/(?a|\(\g\))/, '((((((((a))))))))', 0, 17, 1) x(/\g|\zEND(?.*abc$)/, 'abcxxxabc', 0, 9) x(/\g<1>|\zEND(.a.)/, 'bac', 0, 3) x(/\g<_A>\g<_A>|\zEND(.a.)(?<_A>.b.)/, 'xbxyby', 3, 6, 1) x(/\A(?:\g|\g|\zEND (?a|c\gc)(?b|d\gd))$/, 'cdcbcdc', 0, 7) x(/\A(?|a\g)\z|\zEND (?\g)/, 'aaaa', 0, 4) x(/(?(a|b\gc){3,5})/, 'baaaaca', 1, 5) x(/(?(a|b\gc){3,5})/, 'baaaacaaaaa', 0, 10) x(/(?\(([^\(\)]++|\g)*+\))/, '((a))', 0, 5) x(/()*\1/, '', 0, 0) x(/(?:()|())*\1\2/, '', 0, 0) x(/(?:\1a|())*/, 'a', 0, 0, 1) x(/x((.)*)*x/, '0x1x2x3', 1, 6) x(/x((.)*)*x(?i:\1)\Z/, '0x1x2x1X2', 1, 9) x(/(?:()|()|()|()|()|())*\2\5/, '', 0, 0) x(/(?:()|()|()|(x)|()|())*\2b\5/, 'b', 0, 1) r(//, '', 0) r(/a/, 'a', 0) r(/a/, 'a', 0, 1) r(/b/, 'abc', 1) r(/b/, 'abc', 1, 2) r(/./, 'a', 0) r(/.*/, 'abcde fgh', 9) r(/a*/, 'aaabbc', 6) r(/a+/, 'aaabbc', 2) r(/a?/, 'bac', 3) r(/a??/, 'bac', 3) r(/abcde/, 'abcdeavcd', 0) r(/\w\d\s/, ' a2 aa $3 ', 2) r(/[c-f]aa[x-z]/, '3caaycaaa', 1) r(/(?i:fG)g/, 'fGgFggFgG', 3) r(/a|b/, 'b', 0) r(/ab|bc|cd/, 'bcc', 0) r(/(ffy)\1/, 'ffyffyffy', 3) r(/|z/, 'z', 1) r(/^az/, 'azaz', 0) r(/az$/, 'azaz', 2) r(/(((.a)))\3/, 'zazaaa', 0) r(/(ac*?z)\1/, 'aacczacczacz', 1) r(/aaz{3,4}/, 'bbaabbaazzzaazz', 6) r(/\000a/, "b\000a", 1) r(/ff\xfe/, "fff\xfe", 1) r(/...abcdefghijklmnopqrstuvwxyz/, 'zzzzzabcdefghijklmnopqrstuvwxyz', 2) end def test_euc(enc) $KCODE = enc x(/\xED\xF2/, "\xed\xf2", 0, 2) x(//, '', 0, 0) x(//, '', 0, 2) n(//, '') x(//, '', 0, 4) x(//, '', 0, 6) x(//, '', 0, 70) x(//, '', 2, 4) x(//, '', 2, 6) x(/\xca\xb8/, "\xca\xb8", 0, 2) x(/./, '', 0, 2) x(/../, '', 0, 4) x(/(?u)\w/, '', 0, 2) n(/(?u)\W/, '') x(/(?u)[\W]/, '$', 2, 3) x(/\S/, '', 0, 2) x(/\S/, '', 0, 2) x(/\b/, ' ', 0, 0) x(/\b/, ' ', 1, 1) x(/\B/, ' ', 2, 2) x(/\B/, ' ', 3, 3) x(/\B/, ' ', 0, 0) x(/[]/, '', 0, 2) n(/[ʤ]/, '') x(/[-]/, '', 0, 2) n(/[^]/, '') x(/(?u)[\w]/, '', 0, 2) n(/[\d]/, '') x(/[\D]/, '', 0, 2) n(/[\s]/, '') x(/[\S]/, '', 0, 2) x(/(?u)[\w\d]/, '', 0, 2) x(/(?u)[\w\d]/, ' ', 3, 5) #x(/[\xa4\xcf-\xa4\xd3]/, "\xa4\xd0", 0, 2) # diff spec with GNU regex. #n(/[\xb6\xe7-\xb6\xef]/, "\xb6\xe5") # diff spec with GNU regex. n(/(?u)\w/, ' ') x(/(?u)\W/, ' ', 0, 5) x(/../, '', 0, 10) x(/(?u).\w\W../, ' ', 0, 13) x(/(?u)\s\w/, ' ', 0, 9) x(/./, '', 0, 8) n(/./, '') x(/./, '', 0, 4) x(/^/, '', 0, 2) x(/^$/, '', 0, 2) x(/(?u)^\w$/, '', 0, 2) x(/(?u)^\w$/, 'z', 0, 11) x(/(?u)^\w...$/, 'z', 0, 13) x(/(?u)\w\w\s\W\d/, 'a 4', 0, 12) x(/\A/, '', 0, 6) x(/\Z/, '', 0, 6) x(/\z/, '', 0, 6) x(/\Z/, "\n", 0, 6) x(/\Gݤ/, 'ݤ', 0, 4) n(/\G/, '') n(/Ȥ\G/, 'Ȥ') n(/ޤ\A/, 'ޤ') n(/\A/, 'ޤ') x(/(?=)/, '', 0, 2) n(/(?=)./, '') x(/(?!)/, '', 0, 2) n(/(?!)/, '') x(/(?i:)/, '', 0, 2) x(/(?i:֤)/, '֤', 0, 4) n(/(?i:)/, '') x(/(?m:.)/, "\n", 0, 3) x(/(?m:.)/, "\n", 2, 5) x(/?/, '', 0, 0) x(/?/, '', 0, 0) x(/?/, '', 0, 2) x(/*/, '', 0, 0) x(/*/, '', 0, 2) x(/*/, 'һһ', 0, 6) x(/*/, '', 0, 0) n(/+/, '') x(/+/, '', 0, 2) x(/+/, '', 0, 8) x(/+/, '', 0, 4) x(/+/, '', 2, 10) x(/.?/, '', 0, 2) x(/.*/, 'ѤԤפ', 0, 8) x(/.+/, '', 0, 2) x(/.+/, "\n", 0, 8) x(/|/, '', 0, 2) x(/|/, '', 0, 2) x(/|/, '', 0, 4) x(/|/, '', 0, 4) x(/(?:|)/, '򤫤', 0, 6) x(/(?:|)/, '򤭤', 0, 8) x(/|(?:|)/, '', 0, 4) x(/||/, '', 2, 4) x(/|||||||||ĤƤȤʤ|̤/, '', 0, 6) n(/|||||||||ĤƤȤʤ|̤/, '') x(/|^/, '֤', 2, 4) x(/|^/, '', 0, 2) x(/|\G/, 'ֵ', 4, 6) x(/|\G/, 'ֵ', 0, 2) x(/|\A/, 'bֵ', 3, 5) x(/|\A/, '', 0, 2) x(/|\Z/, 'ֵ', 2, 4) x(/|\Z/, '', 0, 2) x(/|\Z/, "\n", 0, 2) x(/|\z/, 'ֵ', 2, 4) x(/|\z/, '', 0, 2) x(/(?u)\w|\s/, '', 0, 2) x(/(?u)\w|%/, '%', 0, 1) x(/(?u)\w|[&$]/, '&', 0, 2) x(/[-]/, '', 0, 2) x(/[-]|[^-]/, '', 0, 2) x(/[-]|[^-]/, '', 0, 2) x(/[^]/, "\n", 0, 1) x(/(?:|[-])|/, '', 0, 2) x(/(?:|[-])|/, '', 0, 4) x(/|(?=)../, '', 0, 6) x(/|(?!)../, '', 0, 6) x(/(?=)..|(?=)../, '', 0, 6) x(/(?<=|)/, '', 4, 6) n(/(?>|)/, '') x(/(?>|)/, '', 0, 8) x(/?|/, '', 0, 2) x(/?|/, '', 0, 0) x(/?|/, '', 0, 0) x(/*|/, '', 0, 4) x(/*|*/, '', 0, 0) x(/*|*/, '', 0, 2) x(/[a]*|*/, 'a', 0, 3) x(/+|*/, '', 0, 0) x(/+|*/, '', 0, 6) x(/+|*/, '', 0, 2) x(/+|*/, 'a', 0, 0) n(/+|+/, '') x(/(|)?/, '', 0, 2) x(/(|)*/, '', 0, 4) x(/(|)+/, '', 0, 6) x(/(|)+/, '', 0, 8) x(/(|)+/, '', 4, 12) x(/(|)+/, '', 2, 10) x(/(|)+/, '򤦤', 0, 4) x(/(|)+/, '$$zzzz򤦤', 6, 10) x(/(|)+/, '', 0, 10) x(/(|)+/, '', 2, 4) x(/(|)+/, '', 2, 8) x(/(?:|)(?:|)/, '', 0, 4) x(/(?:*|*)(?:*|*)/, '', 0, 6) x(/(?:*|*)(?:+|+)/, '', 0, 12) x(/(?:+|+){2}/, '', 0, 12) x(/(?:+|+){1,2}/, '', 0, 12) x(/(?:+|\A*)/, '', 0, 4) n(/(?:+|\A*)/, '') x(/(?:^+|+)*/, '', 12, 16) x(/(?:^+|+)*/, '', 0, 14) x(/{0,}/, '', 0, 8) x(/|(?i)c/, 'C', 0, 1) x(/(?i)c|/, 'C', 0, 1) x(/(?i:)|a/, 'a', 0, 1) n(/(?i:)|a/, 'A') x(/[]?/, '', 0, 2) x(/[]*/, '', 0, 6) x(/[^]*/, '', 0, 0) n(/[^]+/, '') x(/??/, '', 0, 0) x(/??/, '', 0, 6) x(/*?/, '', 0, 0) x(/*?/, '', 0, 2) x(/*?/, '', 0, 8) x(/+?/, '', 0, 2) x(/+?/, '', 0, 4) x(/+?/, '', 0, 8) x(/(?:ŷ?)??/, 'ŷ', 0, 0) x(/(?:ŷ??)?/, 'ŷ', 0, 0) x(/(?:̴?)+?/, '̴̴̴', 0, 2) x(/(?:+)??/, '', 0, 0) x(/(?:+)??/, '', 0, 8) i(/(?:)?{2}/, '', 0, 0) # GNU regex bug x(/(?:)?{2}/, 'ֵֵ', 0, 8) x(/(?:)*{0}/, 'ֵֵ', 0, 0) x(/(?:){3,}/, 'ֵֵֵ', 0, 16) n(/(?:){3,}/, 'ֵ') x(/(?:){2,4}/, 'ֵֵ', 0, 12) x(/(?:){2,4}/, 'ֵֵֵֵ', 0, 16) x(/(?:){2,4}?/, 'ֵֵֵֵ', 0, 8) x(/(?:){,}/, '{,}', 0, 7) x(/(?:)+?{2}/, '', 0, 12) x(/()/, '', 0, 2, 1) x(/(п)/, 'п', 0, 4, 1) x(/(())/, '', 0, 4) x(/(())/, '', 0, 4, 1) x(/(())/, '', 0, 4, 2) x(/((((((((((((((((((((̻))))))))))))))))))))/, '̻', 0, 4, 20) x(/()()/, '', 0, 4, 1) x(/()()/, '', 4, 8, 2) x(/()()()/, '', 6, 12, 3) x(/(()()())/, '', 6, 12, 4) x(/.*(ե)󡦥(()奿)/, 'ե󡦥ޥ󥷥奿', 10, 18, 2) x(/(^)/, '', 0, 2) x(/()|()/, '', 2, 4, 1) x(/(^)|()/, '', 2, 4, 2) x(/(?)/, '', 0, 2, 1) x(/(*)/, 'ޤޤ', 0, 6, 1) x(/(*)/, '', 0, 0, 1) x(/(+)/, '', 0, 14, 1) x(/(+|*)/, 'դդդؤ', 0, 6, 1) x(/(+|?)/, '', 0, 2, 1) x(/()?/, '', 0, 6, 1) x(/()*/, '', 0, 6, 1) x(/()+/, '', 0, 6, 1) x(/(|)+/, '', 0, 6, 1) x(/([ʤˤ][]|)+/, '', 0, 6, 1) x(/((?i:))/, '', 0, 6, 1) x(/((?m:.))/, "\n", 0, 5, 1) x(/((?=))/, '', 0, 2, 1) x(/|(.)/, '󤢤', 0, 8, 1) x(/*(.)/, '', 8, 10, 1) x(/*?(.)/, '', 0, 2, 1) x(/*?()/, '', 8, 10, 1) x(/[]*(.)/, '', 10, 12, 1) x(/(\A)/, '', 0, 4, 1) n(/(\A)/, '󤤤') x(/(^)/, '', 0, 4, 1) n(/(^)/, '󤤤') x(/($)/, '', 4, 8, 1) n(/($)/, '') x(/(̵)\1/, '̵̵', 0, 4) n(/(̵)\1/, '̵') x(/(?)\1/, '', 0, 4) x(/(??)\1/, '', 0, 0) x(/(*)\1/, '', 0, 8) x(/(*)\1/, '', 0, 4, 1) x(/(*)\1/, '', 0, 10) x(/(*)\1/, '', 0, 2) x(/(*)(*)\1\2/, '', 0, 20) x(/(*)(*)\2/, '', 0, 14) x(/(*)(*)\2/, '', 6, 10, 2) x(/(((((((*)))))))\7/, 'ݤݤݤڤԤݤݤ', 0, 16) x(/(((((((*)))))))\7/, 'ݤݤݤڤԤݤݤ', 0, 6, 7) x(/()()()\2\1\3/, 'ϤҤդҤϤ', 0, 12) x(/([-])\1/, '', 0, 4) x(/(?u)(\w\d\s)\1/, '5 5 ', 0, 8) n(/(?u)(\w\d\s)\1/, '5 5') x(/(ï|[-]{3})\1/, 'ïï', 0, 8) x(/...(ï|[-]{3})\1/, 'aïï', 0, 13) x(/(ï|[-]{3})\1/, '', 0, 12) x(/(^)\1/, '', 0, 4) n(/(^)\1/, '') n(/($)\1/, '') n(/(\Z)\1/, '') x(/(*\Z)\1/, '', 2, 2) x(/.(*\Z)\1/, '', 2, 4) x(/(.(䤤)\2)/, 'z䤤䤤', 0, 13, 1) x(/(.(..\d.)\2)/, '12341234', 0, 10, 1) x(/((?i:v))\1/, 'vv', 0, 10) x(/(?<>|\(\g<>\))/, '(((((())))))', 0, 14) x(/\A(?:\g<_1>|\g<_2>|\zλ (?<_1>|\g<_2>)(?<_2>|\g<_1>))$/, '߼', 0, 26) x(/[[Ҥ]]/, '', 0, 2) x(/[[]]/, '', 0, 2) n(/[[^]]/, '') n(/[^[]]/, '') x(/[^[^]]/, '', 0, 2) x(/[[]&&]/, '', 0, 2) n(/[[]&&]/, '') n(/[[]&&]/, '') x(/[-&&-&&-]/, '', 0, 2) n(/[^-&&-&&-]/, '') x(/[[^&&]&&-]/, '', 0, 2) n(/[[^&&]&&-]/, '') x(/[[^-&&]&&[^-]]/, '', 0, 2) n(/[[^-&&]&&[^-]]/, '') x(/[^[^]&&[^]]/, '', 0, 2) x(/[^[^]&&[^]]/, '', 0, 2) n(/[^[^]&&[^]]/, '') x(/[-&&-]/, '-', 0, 1) x(/[^[^a-z]&&[^bcdefg]q-w]/, '', 0, 2) x(/[^[^a-z]&&[^bcdefg]g-w]/, 'f', 0, 1) x(/[^[^a-z]&&[^bcdefg]g-w]/, 'g', 0, 1) n(/[^[^a-z]&&[^bcdefg]g-w]/, '2') x(/aСΥ<\/b>/, 'aСΥ', 0, 32) x(/.СΥ<\/b>/, 'aСΥ', 0, 32) r(//, '', 0) r(//, '', 0, 2) r(//, '', 2) r(//, '', 2, 4) r(/./, '', 0) r(/.*/, ' ', 17) r(/.*/, ' ', 6) r(/*/, '', 12) r(/+/, '', 4) r(/?/, '', 6) r(/??/, '', 6) r(/ace/, 'aceavcd', 0) r(/(?u)\w\d\s/, ' 2 $3 ', 2) r(/[-][-]/, '3ʤ', 1) r(/|/, '', 0) r(/||/, '', 0) r(/(ȤȤ)\1/, 'ȤȤȤȤȤȤ', 6) r(/|/, '', 2) r(/^/, '', 0) r(/$/, '', 4) r(/(((.)))\3/, 'zz', 0) r(/(*?)\1/, '󤢤󤢤', 2) r(/{3,4}/, 'ƤƤ󤢤󤢤', 12) r(/\000/, "\000", 2) r(/Ȥ\xfe\xfe/, "ȤȤ\xfe\xfe", 2) r(/.../, 'zzzzz', 2) end test_sb('ASCII') test_sb('EUC') test_sb('SJIS') test_sb('UTF-8') test_euc('EUC') # UTF-8 (by UENO Katsuhiro) $KCODE = 'UTF-8' x(/\w/u, "\xc3\x81", 0, 2) n(/\W/u, "\xc3\x81") x(/[\w]/u, "\xc3\x81", 0, 2) x(/./u, "\xfe", 0, 1) x(/\xfe/u, "\xfe", 0, 1) x(/\S*/u, "\xfe", 0, 1) x(/\s*/u, "\xfe", 0, 0) n(/\w+/u, "\xfe") x(/\W+/u, "\xfe\xff", 0, 2) x(/[\xfe]/u, "aaa\xfe", 3, 4) x(/[\xff\xfe]/u, "\xff\xfe", 0, 1) x(/[a-c\xff\xfe]+/u, "\xffabc\xfe", 0, 5) s = "\xe3\x81\x82\xe3\x81\x81\xf0\x90\x80\x85\xe3\x81\x8a\xe3\x81\x85" x(/[\xc2\x80-\xed\x9f\xbf]+/u, s, 0, 6) s = "\xf0\x90\x80\x85\xe3\x81\x82" x(/[\xc2\x80-\xed\x9f\xbf]/u, s, 4, 7) s = "\xed\x9f\xbf" n(/[\xc2\x80-\xed\x9f\xbe]/u, s) s = "\xed\x9f\xbf" n(/[\xc2\x80-\xed\x9f\xbe]/u, s) s = "\xed\x9f\xbf" n(/[\xc2\x80-\xed\x9f\xbe]/u, s) s = "\xed\x9f\xbf" n(/[\xc3\xad\xed\x9f\xbe]/u, s) s = "\xed\x9f\xbf" n(/[\xc4\x80-\xed\x9f\xbe]/u, s) s = "\xed\x9f\xbf\xf0\x90\x80\x85\xed\x9f\xbf" x(/[^\xc2\x80-\xed\x9f\xbe]/u, s, 0, 3) s = "\xed\x9f\xbf" x(/[^\xc3\xad\xed\x9f\xbe]/u, s, 0, 3) s = "\xed\x9f\xbf\xf0\x90\x80\x85\xed\x9f\xbf" x(/[^\xc4\x80-\xed\x9f\xbe]/u, s, 0, 3) s = "\xc3\xbe\xc3\xbf" n(/[\xfe\xff\xc3\x80]/u, s) s = "\xc3\xbe" x(/[\xc2\xa0-\xc3\xbe]/u, s, 0, 2) s = "sssss" x(/s+/iu, s, 0, 5) s = "SSSSS" x(/s+/iu, s, 0, 5) reg = Regexp.new("\\x{fb40}", nil, 'u') x(reg, "\357\255\200", 0, 3) x(/\A\w\z/u, "\357\255\200", 0, 3) x(/\A\W\z/u, "\357\255\202", 0, 3) n(/\A\w\z/u, "\357\255\202") x(/\303\200/iu, "\303\240", 0, 2) x(/\303\247/iu, "\303\207", 0, 2) # Japanese long text. $KCODE = 'EUC' s = < #ifdef POSIX_TEST #include "onigposix.h" #else #include "oniguruma.h" #endif #ifdef HAVE_STRING_H # include #else # include #endif #define SLEN(s) strlen(s) static int nsucc = 0; static int nfail = 0; static int nerror = 0; static FILE* err_file; #ifndef POSIX_TEST static OnigRegion* region; #endif static void xx(char* pattern, char* str, int from, int to, int mem, int not) { OnigPosition r; #ifdef POSIX_TEST regex_t reg; char buf[200]; regmatch_t pmatch[25]; r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } if (r == REG_NOMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); nfail++; } else { if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); nfail++; } } } regfree(®); #else regex_t* reg; OnigErrorInfo einfo; OnigSyntaxType syn = *ONIG_SYNTAX_DEFAULT; OnigIterator it = {onig_default_charat, str}; /* ONIG_OPTION_OFF(syn.options, ONIG_OPTION_ASCII_RANGE); */ r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + SLEN(pattern)), ONIG_OPTION_DEFAULT, ONIG_ENCODING_EUC_JP, &syn, &einfo); if (r) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r, &einfo); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } r = onig_search(&it, reg, 0, SLEN(str), 0, SLEN(str), region, ONIG_OPTION_NONE); if (r < ONIG_MISMATCH) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } if (r == ONIG_MISMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); nfail++; } else { if (region->beg[mem] == from && region->end[mem] == to) { fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, from, to, region->beg[mem], region->end[mem]); nfail++; } } } onig_free(reg); #endif } static void x2(char* pattern, char* str, int from, int to) { xx(pattern, str, from, to, 0, 0); } static void x3(char* pattern, char* str, int from, int to, int mem) { xx(pattern, str, from, to, mem, 0); } static void n(char* pattern, char* str) { xx(pattern, str, 0, 0, 0, 1); } extern int main(int argc, char* argv[]) { err_file = stdout; #ifdef POSIX_TEST reg_set_encoding(REG_POSIX_ENCODING_EUC_JP); #else region = onig_region_new(); #endif x2("", "", 0, 0); x2("^", "", 0, 0); x2("$", "", 0, 0); x2("\\G", "", 0, 0); x2("\\A", "", 0, 0); x2("\\Z", "", 0, 0); x2("\\z", "", 0, 0); x2("^$", "", 0, 0); x2("\\ca", "\001", 0, 1); x2("\\C-b", "\002", 0, 1); x2("\\c\\\\", "\034", 0, 1); x2("q[\\c\\\\]", "q\034", 0, 2); x2("", "a", 0, 0); x2("a", "a", 0, 1); x2("\\x61", "a", 0, 1); x2("aa", "aa", 0, 2); x2("aaa", "aaa", 0, 3); x2("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 35); x2("ab", "ab", 0, 2); x2("b", "ab", 1, 2); x2("bc", "abc", 1, 3); x2("(?i:#RET#)", "#INS##RET#", 5, 10); x2("\\17", "\017", 0, 1); x2("\\x1f", "\x1f", 0, 1); x2("a(?#....\\\\JJJJ)b", "ab", 0, 2); x2("(?x) G (o O(?-x)oO) g L", "GoOoOgLe", 0, 7); x2(".", "a", 0, 1); n(".", ""); x2("..", "ab", 0, 2); x2("\\w", "e", 0, 1); n("\\W", "e"); x2("\\s", " ", 0, 1); x2("\\S", "b", 0, 1); x2("\\d", "4", 0, 1); n("\\D", "4"); x2("\\b", "z ", 0, 0); x2("\\b", " z", 1, 1); x2("\\B", "zz ", 1, 1); x2("\\B", "z ", 2, 2); x2("\\B", " z", 0, 0); x2("[ab]", "b", 0, 1); n("[ab]", "c"); x2("[a-z]", "t", 0, 1); n("[^a]", "a"); x2("[^a]", "\n", 0, 1); x2("[]]", "]", 0, 1); n("[^]]", "]"); x2("[\\^]+", "0^^1", 1, 3); x2("[b-]", "b", 0, 1); x2("[b-]", "-", 0, 1); x2("[\\w]", "z", 0, 1); n("[\\w]", " "); x2("[\\W]", "b$", 1, 2); x2("[\\d]", "5", 0, 1); n("[\\d]", "e"); x2("[\\D]", "t", 0, 1); n("[\\D]", "3"); x2("[\\s]", " ", 0, 1); n("[\\s]", "a"); x2("[\\S]", "b", 0, 1); n("[\\S]", " "); x2("[\\w\\d]", "2", 0, 1); n("[\\w\\d]", " "); x2("[[:upper:]]", "B", 0, 1); x2("[*[:xdigit:]+]", "+", 0, 1); x2("[*[:xdigit:]+]", "GHIKK-9+*", 6, 7); x2("[*[:xdigit:]+]", "-@^+", 3, 4); n("[[:upper]]", "A"); x2("[[:upper]]", ":", 0, 1); x2("[\\044-\\047]", "\046", 0, 1); x2("[\\x5a-\\x5c]", "\x5b", 0, 1); x2("[\\x6A-\\x6D]", "\x6c", 0, 1); n("[\\x6A-\\x6D]", "\x6E"); n("^[0-9A-F]+ 0+ UNDEF ", "75F 00000000 SECT14A notype () External | _rb_apply"); x2("[\\[]", "[", 0, 1); x2("[\\]]", "]", 0, 1); x2("[&]", "&", 0, 1); x2("[[ab]]", "b", 0, 1); x2("[[ab]c]", "c", 0, 1); n("[[^a]]", "a"); n("[^[a]]", "a"); x2("[[ab]&&bc]", "b", 0, 1); n("[[ab]&&bc]", "a"); n("[[ab]&&bc]", "c"); x2("[a-z&&b-y&&c-x]", "w", 0, 1); n("[^a-z&&b-y&&c-x]", "w"); x2("[[^a&&a]&&a-z]", "b", 0, 1); n("[[^a&&a]&&a-z]", "a"); x2("[[^a-z&&bcdef]&&[^c-g]]", "h", 0, 1); n("[[^a-z&&bcdef]&&[^c-g]]", "c"); x2("[^[^abc]&&[^cde]]", "c", 0, 1); x2("[^[^abc]&&[^cde]]", "e", 0, 1); n("[^[^abc]&&[^cde]]", "f"); x2("[a-&&-a]", "-", 0, 1); n("[a\\-&&\\-a]", "&"); n("\\wabc", " abc"); x2("a\\Wbc", "a bc", 0, 4); x2("a.b.c", "aabbc", 0, 5); x2(".\\wb\\W..c", "abb bcc", 0, 7); x2("\\s\\wzzz", " zzzz", 0, 5); x2("aa.b", "aabb", 0, 4); n(".a", "ab"); x2(".a", "aa", 0, 2); x2("^a", "a", 0, 1); x2("^a$", "a", 0, 1); x2("^\\w$", "a", 0, 1); n("^\\w$", " "); x2("^\\wab$", "zab", 0, 3); x2("^\\wabcdef$", "zabcdef", 0, 7); x2("^\\w...def$", "zabcdef", 0, 7); x2("\\w\\w\\s\\Waaa\\d", "aa aaa4", 0, 8); x2("\\A\\Z", "", 0, 0); x2("\\Axyz", "xyz", 0, 3); x2("xyz\\Z", "xyz", 0, 3); x2("xyz\\z", "xyz", 0, 3); x2("a\\Z", "a", 0, 1); x2("\\Gaz", "az", 0, 2); n("\\Gz", "bza"); n("az\\G", "az"); n("az\\A", "az"); n("a\\Az", "az"); x2("\\^\\$", "^$", 0, 2); x2("^x?y", "xy", 0, 2); x2("^(x?y)", "xy", 0, 2); x2("\\w", "_", 0, 1); n("\\W", "_"); x2("(?=z)z", "z", 0, 1); n("(?=z).", "a"); x2("(?!z)a", "a", 0, 1); n("(?!z)a", "z"); x2("(?i:a)", "a", 0, 1); x2("(?i:a)", "A", 0, 1); x2("(?i:A)", "a", 0, 1); n("(?i:A)", "b"); x2("(?i:[A-Z])", "a", 0, 1); x2("(?i:[f-m])", "H", 0, 1); x2("(?i:[f-m])", "h", 0, 1); n("(?i:[f-m])", "e"); x2("(?i:[A-c])", "D", 0, 1); n("(?i:[^a-z])", "A"); n("(?i:[^a-z])", "a"); x2("(?i:[!-k])", "Z", 0, 1); x2("(?i:[!-k])", "7", 0, 1); x2("(?i:[T-}])", "b", 0, 1); x2("(?i:[T-}])", "{", 0, 1); x2("(?i:\\?a)", "?A", 0, 2); x2("(?i:\\*A)", "*a", 0, 2); n(".", "\n"); x2("(?m:.)", "\n", 0, 1); x2("(?m:a.)", "a\n", 0, 2); x2("(?m:.b)", "a\nb", 1, 3); x2(".*abc", "dddabdd\nddabc", 8, 13); x2("(?m:.*abc)", "dddabddabc", 0, 10); n("(?i)(?-i)a", "A"); n("(?i)(?-i:a)", "A"); x2("a?", "", 0, 0); x2("a?", "b", 0, 0); x2("a?", "a", 0, 1); x2("a*", "", 0, 0); x2("a*", "a", 0, 1); x2("a*", "aaa", 0, 3); x2("a*", "baaaa", 0, 0); n("a+", ""); x2("a+", "a", 0, 1); x2("a+", "aaaa", 0, 4); x2("a+", "aabbb", 0, 2); x2("a+", "baaaa", 1, 5); x2(".?", "", 0, 0); x2(".?", "f", 0, 1); x2(".?", "\n", 0, 0); x2(".*", "", 0, 0); x2(".*", "abcde", 0, 5); x2(".+", "z", 0, 1); x2(".+", "zdswer\n", 0, 6); x2("(.*)a\\1f", "babfbac", 0, 4); x2("(.*)a\\1f", "bacbabf", 3, 7); x2("((.*)a\\2f)", "bacbabf", 3, 7); x2("(.*)a\\1f", "baczzzzzz\nbazz\nzzzzbabf", 19, 23); x2("a|b", "a", 0, 1); x2("a|b", "b", 0, 1); x2("|a", "a", 0, 0); x2("(|a)", "a", 0, 0); x2("ab|bc", "ab", 0, 2); x2("ab|bc", "bc", 0, 2); x2("z(?:ab|bc)", "zbc", 0, 3); x2("a(?:ab|bc)c", "aabc", 0, 4); x2("ab|(?:ac|az)", "az", 0, 2); x2("a|b|c", "dc", 1, 2); x2("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "pqr", 0, 2); n("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "mn"); x2("a|^z", "ba", 1, 2); x2("a|^z", "za", 0, 1); x2("a|\\Gz", "bza", 2, 3); x2("a|\\Gz", "za", 0, 1); x2("a|\\Az", "bza", 2, 3); x2("a|\\Az", "za", 0, 1); x2("a|b\\Z", "ba", 1, 2); x2("a|b\\Z", "b", 0, 1); x2("a|b\\z", "ba", 1, 2); x2("a|b\\z", "b", 0, 1); x2("\\w|\\s", " ", 0, 1); n("\\w|\\w", " "); x2("\\w|%", "%", 0, 1); x2("\\w|[&$]", "&", 0, 1); x2("[b-d]|[^e-z]", "a", 0, 1); x2("(?:a|[c-f])|bz", "dz", 0, 1); x2("(?:a|[c-f])|bz", "bz", 0, 2); x2("abc|(?=zz)..f", "zzf", 0, 3); x2("abc|(?!zz)..f", "abf", 0, 3); x2("(?=za)..a|(?=zz)..a", "zza", 0, 3); n("(?>a|abd)c", "abdc"); x2("(?>abd|a)c", "abdc", 0, 4); x2("a?|b", "a", 0, 1); x2("a?|b", "b", 0, 0); x2("a?|b", "", 0, 0); x2("a*|b", "aa", 0, 2); x2("a*|b*", "ba", 0, 0); x2("a*|b*", "ab", 0, 1); x2("a+|b*", "", 0, 0); x2("a+|b*", "bbb", 0, 3); x2("a+|b*", "abbb", 0, 1); n("a+|b+", ""); x2("(a|b)?", "b", 0, 1); x2("(a|b)*", "ba", 0, 2); x2("(a|b)+", "bab", 0, 3); x2("(ab|ca)+", "caabbc", 0, 4); x2("(ab|ca)+", "aabca", 1, 5); x2("(ab|ca)+", "abzca", 0, 2); x2("(a|bab)+", "ababa", 0, 5); x2("(a|bab)+", "ba", 1, 2); x2("(a|bab)+", "baaaba", 1, 4); x2("(?:a|b)(?:a|b)", "ab", 0, 2); x2("(?:a*|b*)(?:a*|b*)", "aaabbb", 0, 3); x2("(?:a*|b*)(?:a+|b+)", "aaabbb", 0, 6); x2("(?:a+|b+){2}", "aaabbb", 0, 6); x2("h{0,}", "hhhh", 0, 4); x2("(?:a+|b+){1,2}", "aaabbb", 0, 6); n("ax{2}*a", "0axxxa1"); n("a.{0,2}a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXXa0"); x2("^a{2,}?a$", "aaa", 0, 3); x2("^[a-z]{2,}?$", "aaa", 0, 3); x2("(?:a+|\\Ab*)cc", "cc", 0, 2); n("(?:a+|\\Ab*)cc", "abcc"); x2("(?:^a+|b+)*c", "aabbbabc", 6, 8); x2("(?:^a+|b+)*c", "aabbbbc", 0, 7); x2("a|(?i)c", "C", 0, 1); x2("(?i)c|a", "C", 0, 1); x2("(?i)c|a", "A", 0, 1); x2("(?i:c)|a", "C", 0, 1); n("(?i:c)|a", "A"); x2("[abc]?", "abc", 0, 1); x2("[abc]*", "abc", 0, 3); x2("[^abc]*", "abc", 0, 0); n("[^abc]+", "abc"); x2("a?\?", "aaa", 0, 0); x2("ba?\?b", "bab", 0, 3); x2("a*?", "aaa", 0, 0); x2("ba*?", "baa", 0, 1); x2("ba*?b", "baab", 0, 4); x2("a+?", "aaa", 0, 1); x2("ba+?", "baa", 0, 2); x2("ba+?b", "baab", 0, 4); x2("(?:a?)?\?", "a", 0, 0); x2("(?:a?\?)?", "a", 0, 0); x2("(?:a?)+?", "aaa", 0, 1); x2("(?:a+)?\?", "aaa", 0, 0); x2("(?:a+)?\?b", "aaab", 0, 4); x2("(?:ab)?{2}", "", 0, 0); x2("(?:ab)?{2}", "ababa", 0, 4); x2("(?:ab)*{0}", "ababa", 0, 0); x2("(?:ab){3,}", "abababab", 0, 8); n("(?:ab){3,}", "abab"); x2("(?:ab){2,4}", "ababab", 0, 6); x2("(?:ab){2,4}", "ababababab", 0, 8); x2("(?:ab){2,4}?", "ababababab", 0, 4); x2("(?:ab){,}", "ab{,}", 0, 5); x2("(?:abc)+?{2}", "abcabcabc", 0, 6); x2("(?:X*)(?i:xa)", "XXXa", 0, 4); x2("(d+)([^abc]z)", "dddz", 0, 4); x2("([^abc]*)([^abc]z)", "dddz", 0, 4); x2("(\\w+)(\\wz)", "dddz", 0, 4); x3("(a)", "a", 0, 1, 1); x3("(ab)", "ab", 0, 2, 1); x2("((ab))", "ab", 0, 2); x3("((ab))", "ab", 0, 2, 1); x3("((ab))", "ab", 0, 2, 2); x3("((((((((((((((((((((ab))))))))))))))))))))", "ab", 0, 2, 20); x3("(ab)(cd)", "abcd", 0, 2, 1); x3("(ab)(cd)", "abcd", 2, 4, 2); x3("()(a)bc(def)ghijk", "abcdefghijk", 3, 6, 3); x3("(()(a)bc(def)ghijk)", "abcdefghijk", 3, 6, 4); x2("(^a)", "a", 0, 1); x3("(a)|(a)", "ba", 1, 2, 1); x3("(^a)|(a)", "ba", 1, 2, 2); x3("(a?)", "aaa", 0, 1, 1); x3("(a*)", "aaa", 0, 3, 1); x3("(a*)", "", 0, 0, 1); x3("(a+)", "aaaaaaa", 0, 7, 1); x3("(a+|b*)", "bbbaa", 0, 3, 1); x3("(a+|b?)", "bbbaa", 0, 1, 1); x3("(abc)?", "abc", 0, 3, 1); x3("(abc)*", "abc", 0, 3, 1); x3("(abc)+", "abc", 0, 3, 1); x3("(xyz|abc)+", "abc", 0, 3, 1); x3("([xyz][abc]|abc)+", "abc", 0, 3, 1); x3("((?i:abc))", "AbC", 0, 3, 1); x2("(abc)(?i:\\1)", "abcABC", 0, 6); x3("((?m:a.c))", "a\nc", 0, 3, 1); x3("((?=az)a)", "azb", 0, 1, 1); x3("abc|(.abd)", "zabd", 0, 4, 1); x2("(?:abc)|(ABC)", "abc", 0, 3); x3("(?i:(abc))|(zzz)", "ABC", 0, 3, 1); x3("a*(.)", "aaaaz", 4, 5, 1); x3("a*?(.)", "aaaaz", 0, 1, 1); x3("a*?(c)", "aaaac", 4, 5, 1); x3("[bcd]a*(.)", "caaaaz", 5, 6, 1); x3("(\\Abb)cc", "bbcc", 0, 2, 1); n("(\\Abb)cc", "zbbcc"); x3("(^bb)cc", "bbcc", 0, 2, 1); n("(^bb)cc", "zbbcc"); x3("cc(bb$)", "ccbb", 2, 4, 1); n("cc(bb$)", "ccbbb"); n("(\\1)", ""); n("\\1(a)", "aa"); n("(a(b)\\1)\\2+", "ababb"); n("(?:(?:\\1|z)(a))+$", "zaa"); x2("(?:(?:\\1|z)(a))+$", "zaaa", 0, 4); x2("(a)(?=\\1)", "aa", 0, 1); n("(a)$|\\1", "az"); x2("(a)\\1", "aa", 0, 2); n("(a)\\1", "ab"); x2("(a?)\\1", "aa", 0, 2); x2("(a?\?)\\1", "aa", 0, 0); x2("(a*)\\1", "aaaaa", 0, 4); x3("(a*)\\1", "aaaaa", 0, 2, 1); x2("a(b*)\\1", "abbbb", 0, 5); x2("a(b*)\\1", "ab", 0, 1); x2("(a*)(b*)\\1\\2", "aaabbaaabb", 0, 10); x2("(a*)(b*)\\2", "aaabbbb", 0, 7); x2("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 8); x3("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 3, 7); x2("(a)(b)(c)\\2\\1\\3", "abcbac", 0, 6); x2("([a-d])\\1", "cc", 0, 2); x2("(\\w\\d\\s)\\1", "f5 f5 ", 0, 6); n("(\\w\\d\\s)\\1", "f5 f5"); x2("(who|[a-c]{3})\\1", "whowho", 0, 6); x2("...(who|[a-c]{3})\\1", "abcwhowho", 0, 9); x2("(who|[a-c]{3})\\1", "cbccbc", 0, 6); x2("(^a)\\1", "aa", 0, 2); n("(^a)\\1", "baa"); n("(a$)\\1", "aa"); n("(ab\\Z)\\1", "ab"); x2("(a*\\Z)\\1", "a", 1, 1); x2(".(a*\\Z)\\1", "ba", 1, 2); x3("(.(abc)\\2)", "zabcabc", 0, 7, 1); x3("(.(..\\d.)\\2)", "z12341234", 0, 9, 1); x2("((?i:az))\\1", "AzAz", 0, 4); n("((?i:az))\\1", "Azaz"); x2("(?<=a)b", "ab", 1, 2); n("(?<=a)b", "bb"); x2("(?<=a|b)b", "bb", 1, 2); x2("(?<=a|bc)b", "bcb", 2, 3); x2("(?<=a|bc)b", "ab", 1, 2); x2("(?<=a|bc||defghij|klmnopq|r)z", "rz", 1, 2); x2("(a)\\g<1>", "aa", 0, 2); x2("(?a)", "a", 0, 1); x2("(?ab)\\g", "abab", 0, 4); x2("(?.zv.)\\k", "azvbazvb", 0, 8); x2("(?<=\\g)|-\\zEND (?XyZ)", "XyZ", 3, 3); x2("(?|a\\g)+", "", 0, 0); x2("(?|\\(\\g\\))+$", "()(())", 0, 6); x3("\\g(?.){0}", "X", 0, 1, 1); x2("\\g(abc|df(?.YZ){2,8}){0}", "XYZ", 0, 3); x2("\\A(?(a\\g)|)\\z", "aaaa", 0, 4); x2("(?|\\g\\g)\\z|\\zEND (?a|(b)\\g)", "bbbbabba", 0, 8); x2("(?\\w+\\sx)a+\\k", " fg xaaaaaaaafg x", 2, 18); x3("(z)()()(?<_9>a)\\g<_9>", "zaa", 2, 3, 1); x2("(.)(((?<_>a)))\\k<_>", "zaa", 0, 3); x2("((?\\d)|(?\\w))(\\k|\\k)", "ff", 0, 2); x2("(?:(?)|(?efg))\\k", "", 0, 0); x2("(?:(?abc)|(?efg))\\k", "abcefgefg", 3, 9); n("(?:(?abc)|(?efg))\\k", "abcefg"); x2("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "a-pyumpyum", 2, 10); x3("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "xxxxabcdefghijklmnabcdefghijklmn", 4, 18, 14); x3("(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?aaa)(?)$", "aaa", 0, 3, 16); x2("(?a|\\(\\g\\))", "a", 0, 1); x2("(?a|\\(\\g\\))", "((((((a))))))", 0, 13); x3("(?a|\\(\\g\\))", "((((((((a))))))))", 0, 17, 1); x2("\\g|\\zEND(?.*abc$)", "abcxxxabc", 0, 9); x2("\\g<1>|\\zEND(.a.)", "bac", 0, 3); x3("\\g<_A>\\g<_A>|\\zEND(.a.)(?<_A>.b.)", "xbxyby", 3, 6, 1); x2("\\A(?:\\g|\\g|\\zEND (?a|c\\gc)(?b|d\\gd))$", "cdcbcdc", 0, 7); x2("\\A(?|a\\g)\\z|\\zEND (?\\g)", "aaaa", 0, 4); x2("(?(a|b\\gc){3,5})", "baaaaca", 1, 5); x2("(?(a|b\\gc){3,5})", "baaaacaaaaa", 0, 10); x2("(?\\(([^\\(\\)]++|\\g)*+\\))", "((a))", 0, 5); x2("()*\\1", "", 0, 0); x2("(?:()|())*\\1\\2", "", 0, 0); x3("(?:\\1a|())*", "a", 0, 0, 1); x2("x((.)*)*x", "0x1x2x3", 1, 6); x2("x((.)*)*x(?i:\\1)\\Z", "0x1x2x1X2", 1, 9); x2("(?:()|()|()|()|()|())*\\2\\5", "", 0, 0); x2("(?:()|()|()|(x)|()|())*\\2b\\5", "b", 0, 1); x2("\\xED\\xF2", "\xed\xf2", 0, 2); x2("", "", 0, 0); x2("", "", 0, 2); n("", ""); x2("", "", 0, 4); x2("", "", 0, 6); x2("", "", 0, 70); x2("", "", 2, 4); x2("", "", 2, 6); x2("\\xca\\xb8", "\xca\xb8", 0, 2); x2(".", "", 0, 2); x2("..", "", 0, 4); x2("(?u)\\w", "", 0, 2); n("(?u)\\W", ""); x2("(?u)[\\W]", "$", 2, 3); x2("\\S", "", 0, 2); x2("\\S", "", 0, 2); x2("\\b", " ", 0, 0); x2("\\b", " ", 1, 1); x2("\\B", " ", 2, 2); x2("\\B", " ", 3, 3); x2("\\B", " ", 0, 0); x2("[]", "", 0, 2); n("[ʤ]", ""); x2("[-]", "", 0, 2); n("[^]", ""); x2("(?u)[\\w]", "", 0, 2); n("[\\d]", ""); x2("[\\D]", "", 0, 2); n("[\\s]", ""); x2("[\\S]", "", 0, 2); x2("(?u)[\\w\\d]", "", 0, 2); x2("(?u)[\\w\\d]", " ", 3, 5); n("(?u)\\w", " "); x2("(?u)\\W", " ", 0, 5); x2("..", "", 0, 10); x2("(?u).\\w\\W..", " ", 0, 13); x2("(?u)\\s\\w", " ", 0, 9); x2(".", "", 0, 8); n(".", ""); x2(".", "", 0, 4); x2("^", "", 0, 2); x2("^$", "", 0, 2); x2("(?u)^\\w$", "", 0, 2); x2("(?u)^\\w$", "z", 0, 11); x2("(?u)^\\w...$", "z", 0, 13); x2("(?u)\\w\\w\\s\\W\\d", "a 4", 0, 12); x2("\\A", "", 0, 6); x2("\\Z", "", 0, 6); x2("\\z", "", 0, 6); x2("\\Z", "\n", 0, 6); x2("\\Gݤ", "ݤ", 0, 4); n("\\G", ""); n("Ȥ\\G", "Ȥ"); n("ޤ\\A", "ޤ"); n("\\A", "ޤ"); x2("(?=)", "", 0, 2); n("(?=).", ""); x2("(?!)", "", 0, 2); n("(?!)", ""); x2("(?i:)", "", 0, 2); x2("(?i:֤)", "֤", 0, 4); n("(?i:)", ""); x2("(?m:.)", "\n", 0, 3); x2("(?m:.)", "\n", 2, 5); x2("?", "", 0, 0); x2("?", "", 0, 0); x2("?", "", 0, 2); x2("*", "", 0, 0); x2("*", "", 0, 2); x2("*", "һһ", 0, 6); x2("*", "", 0, 0); n("+", ""); x2("+", "", 0, 2); x2("+", "", 0, 8); x2("+", "", 0, 4); x2("+", "", 2, 10); x2(".?", "", 0, 2); x2(".*", "ѤԤפ", 0, 8); x2(".+", "", 0, 2); x2(".+", "\n", 0, 8); x2("|", "", 0, 2); x2("|", "", 0, 2); x2("|", "", 0, 4); x2("|", "", 0, 4); x2("(?:|)", "򤫤", 0, 6); x2("(?:|)", "򤭤", 0, 8); x2("|(?:|)", "", 0, 4); x2("||", "", 2, 4); x2("|||||||||ĤƤȤʤ|̤", "", 0, 6); n("|||||||||ĤƤȤʤ|̤", ""); x2("|^", "֤", 2, 4); x2("|^", "", 0, 2); x2("|\\G", "ֵ", 4, 6); x2("|\\G", "ֵ", 0, 2); x2("|\\A", "bֵ", 3, 5); x2("|\\A", "", 0, 2); x2("|\\Z", "ֵ", 2, 4); x2("|\\Z", "", 0, 2); x2("|\\Z", "\n", 0, 2); x2("|\\z", "ֵ", 2, 4); x2("|\\z", "", 0, 2); x2("(?u)\\w|\\s", "", 0, 2); x2("(?u)\\w|%", "%", 0, 1); x2("(?u)\\w|[&$]", "&", 0, 2); x2("[-]", "", 0, 2); x2("[-]|[^-]", "", 0, 2); x2("[-]|[^-]", "", 0, 2); x2("[^]", "\n", 0, 1); x2("(?:|[-])|", "", 0, 2); x2("(?:|[-])|", "", 0, 4); x2("|(?=)..", "", 0, 6); x2("|(?!)..", "", 0, 6); x2("(?=)..|(?=)..", "", 0, 6); x2("(?<=|)", "", 4, 6); n("(?>|)", ""); x2("(?>|)", "", 0, 8); x2("?|", "", 0, 2); x2("?|", "", 0, 0); x2("?|", "", 0, 0); x2("*|", "", 0, 4); x2("*|*", "", 0, 0); x2("*|*", "", 0, 2); x2("[a]*|*", "a", 0, 3); x2("+|*", "", 0, 0); x2("+|*", "", 0, 6); x2("+|*", "", 0, 2); x2("+|*", "a", 0, 0); n("+|+", ""); x2("(|)?", "", 0, 2); x2("(|)*", "", 0, 4); x2("(|)+", "", 0, 6); x2("(|)+", "", 0, 8); x2("(|)+", "", 4, 12); x2("(|)+", "", 2, 10); x2("(|)+", "򤦤", 0, 4); x2("(|)+", "$$zzzz򤦤", 6, 10); x2("(|)+", "", 0, 10); x2("(|)+", "", 2, 4); x2("(|)+", "", 2, 8); x2("(?:|)(?:|)", "", 0, 4); x2("(?:*|*)(?:*|*)", "", 0, 6); x2("(?:*|*)(?:+|+)", "", 0, 12); x2("(?:+|+){2}", "", 0, 12); x2("(?:+|+){1,2}", "", 0, 12); x2("(?:+|\\A*)", "", 0, 4); n("(?:+|\\A*)", ""); x2("(?:^+|+)*", "", 12, 16); x2("(?:^+|+)*", "", 0, 14); x2("{0,}", "", 0, 8); x2("|(?i)c", "C", 0, 1); x2("(?i)c|", "C", 0, 1); x2("(?i:)|a", "a", 0, 1); n("(?i:)|a", "A"); x2("[]?", "", 0, 2); x2("[]*", "", 0, 6); x2("[^]*", "", 0, 0); n("[^]+", ""); x2("?\?", "", 0, 0); x2("?\?", "", 0, 6); x2("*?", "", 0, 0); x2("*?", "", 0, 2); x2("*?", "", 0, 8); x2("+?", "", 0, 2); x2("+?", "", 0, 4); x2("+?", "", 0, 8); x2("(?:ŷ?)?\?", "ŷ", 0, 0); x2("(?:ŷ?\?)?", "ŷ", 0, 0); x2("(?:̴?)+?", "̴̴̴", 0, 2); x2("(?:+)?\?", "", 0, 0); x2("(?:+)?\?", "", 0, 8); x2("(?:)?{2}", "", 0, 0); x2("(?:)?{2}", "ֵֵ", 0, 8); x2("(?:)*{0}", "ֵֵ", 0, 0); x2("(?:){3,}", "ֵֵֵ", 0, 16); n("(?:){3,}", "ֵ"); x2("(?:){2,4}", "ֵֵ", 0, 12); x2("(?:){2,4}", "ֵֵֵֵ", 0, 16); x2("(?:){2,4}?", "ֵֵֵֵ", 0, 8); x2("(?:){,}", "{,}", 0, 7); x2("(?:)+?{2}", "", 0, 12); x3("()", "", 0, 2, 1); x3("(п)", "п", 0, 4, 1); x2("(())", "", 0, 4); x3("(())", "", 0, 4, 1); x3("(())", "", 0, 4, 2); x3("((((((((((((((((((((̻))))))))))))))))))))", "̻", 0, 4, 20); x3("()()", "", 0, 4, 1); x3("()()", "", 4, 8, 2); x3("()()()", "", 6, 12, 3); x3("(()()())", "", 6, 12, 4); x3(".*(ե)󡦥(()奿)", "ե󡦥ޥ󥷥奿", 10, 18, 2); x2("(^)", "", 0, 2); x3("()|()", "", 2, 4, 1); x3("(^)|()", "", 2, 4, 2); x3("(?)", "", 0, 2, 1); x3("(*)", "ޤޤ", 0, 6, 1); x3("(*)", "", 0, 0, 1); x3("(+)", "", 0, 14, 1); x3("(+|*)", "դդդؤ", 0, 6, 1); x3("(+|?)", "", 0, 2, 1); x3("()?", "", 0, 6, 1); x3("()*", "", 0, 6, 1); x3("()+", "", 0, 6, 1); x3("(|)+", "", 0, 6, 1); x3("([ʤˤ][]|)+", "", 0, 6, 1); x3("((?i:))", "", 0, 6, 1); x3("((?m:.))", "\n", 0, 5, 1); x3("((?=))", "", 0, 2, 1); x3("|(.)", "󤢤", 0, 8, 1); x3("*(.)", "", 8, 10, 1); x3("*?(.)", "", 0, 2, 1); x3("*?()", "", 8, 10, 1); x3("[]*(.)", "", 10, 12, 1); x3("(\\A)", "", 0, 4, 1); n("(\\A)", "󤤤"); x3("(^)", "", 0, 4, 1); n("(^)", "󤤤"); x3("($)", "", 4, 8, 1); n("($)", ""); x2("(̵)\\1", "̵̵", 0, 4); n("(̵)\\1", "̵"); x2("(?)\\1", "", 0, 4); x2("(?\?)\\1", "", 0, 0); x2("(*)\\1", "", 0, 8); x3("(*)\\1", "", 0, 4, 1); x2("(*)\\1", "", 0, 10); x2("(*)\\1", "", 0, 2); x2("(*)(*)\\1\\2", "", 0, 20); x2("(*)(*)\\2", "", 0, 14); x3("(*)(*)\\2", "", 6, 10, 2); x2("(((((((*)))))))\\7", "ݤݤݤڤԤݤݤ", 0, 16); x3("(((((((*)))))))\\7", "ݤݤݤڤԤݤݤ", 0, 6, 7); x2("()()()\\2\\1\\3", "ϤҤդҤϤ", 0, 12); x2("([-])\\1", "", 0, 4); x2("(?u)(\\w\\d\\s)\\1", "5 5 ", 0, 8); n("(?u)(\\w\\d\\s)\\1", "5 5"); x2("(ï|[-]{3})\\1", "ïï", 0, 8); x2("...(ï|[-]{3})\\1", "aïï", 0, 13); x2("(ï|[-]{3})\\1", "", 0, 12); x2("(^)\\1", "", 0, 4); n("(^)\\1", ""); n("($)\\1", ""); n("(\\Z)\\1", ""); x2("(*\\Z)\\1", "", 2, 2); x2(".(*\\Z)\\1", "", 2, 4); x3("(.(䤤)\\2)", "z䤤䤤", 0, 13, 1); x3("(.(..\\d.)\\2)", "12341234", 0, 10, 1); x2("((?i:v))\\1", "vv", 0, 10); x2("(?<>|\\(\\g<>\\))", "(((((())))))", 0, 14); x2("\\A(?:\\g<_1>|\\g<_2>|\\zλ (?<_1>|\\g<_2>)(?<_2>|\\g<_1>))$", "߼", 0, 26); x2("[[Ҥ]]", "", 0, 2); x2("[[]]", "", 0, 2); n("[[^]]", ""); n("[^[]]", ""); x2("[^[^]]", "", 0, 2); x2("[[]&&]", "", 0, 2); n("[[]&&]", ""); n("[[]&&]", ""); x2("[-&&-&&-]", "", 0, 2); n("[^-&&-&&-]", ""); x2("[[^&&]&&-]", "", 0, 2); n("[[^&&]&&-]", ""); x2("[[^-&&]&&[^-]]", "", 0, 2); n("[[^-&&]&&[^-]]", ""); x2("[^[^]&&[^]]", "", 0, 2); x2("[^[^]&&[^]]", "", 0, 2); n("[^[^]&&[^]]", ""); x2("[-&&-]", "-", 0, 1); x2("[^[^a-z]&&[^bcdefg]q-w]", "", 0, 2); x2("[^[^a-z]&&[^bcdefg]g-w]", "f", 0, 1); x2("[^[^a-z]&&[^bcdefg]g-w]", "g", 0, 1); n("[^[^a-z]&&[^bcdefg]g-w]", "2"); x2("aСΥ<\\/b>", "aСΥ", 0, 32); x2(".СΥ<\\/b>", "aСΥ", 0, 32); fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d (by Onigmo %s)\n", nsucc, nfail, nerror, onig_version()); #ifndef POSIX_TEST onig_region_free(region, 1); onig_end(); #endif return ((nfail == 0 && nerror == 0) ? 0 : -1); } ================================================ FILE: src/Onigmo/testconv.rb ================================================ #!/usr/local/bin/ruby -Ke # testconv.rb # Copyright (C) 2003-2006 K.Kosako (sndgk393 AT ybb DOT ne DOT jp) WINDOWS = (ARGV.size > 0 && /^-win/i =~ ARGV[0]) ARGV.shift if WINDOWS if WINDOWS REGENC = 'ONIG_ENCODING_SJIS' else REGENC = 'ONIG_ENCODING_EUC_JP' end def conv_reg(s) s.gsub!(/\\/, '\\\\\\\\') #' s.gsub!(/\?\?/, '?\\\\?') # escape ANSI trigraph (??) s end def conv_str(s) if (s[0] == ?') s = s[1..-2] return s.gsub(/\\/, '\\\\\\\\') #' else return s[1..-2] end end print(<<"EOS") /* * This program was generated by testconv.rb. */ #include "config.h" #ifdef ONIG_ESCAPE_UCHAR_COLLISION #undef ONIG_ESCAPE_UCHAR_COLLISION #endif #include #ifdef POSIX_TEST #include "onigposix.h" #else #include "oniguruma.h" #endif #ifdef HAVE_STRING_H # include #else # include #endif #define SLEN(s) strlen(s) static int nsucc = 0; static int nfail = 0; static int nerror = 0; static FILE* err_file; #ifndef POSIX_TEST static OnigRegion* region; #endif static void xx(char* pattern, char* str, int from, int to, int mem, int not) { int r; #ifdef POSIX_TEST regex_t reg; char buf[200]; regmatch_t pmatch[25]; r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\\n", buf); nerror++; return ; } r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\\n", buf); nerror++; return ; } if (r == REG_NOMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\\n", pattern, str); nfail++; } else { if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { fprintf(stdout, "OK: /%s/ '%s'\\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\\n", pattern, str, from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); nfail++; } } } regfree(®); #else regex_t* reg; OnigErrorInfo einfo; OnigSyntaxType syn = *ONIG_SYNTAX_DEFAULT; /* ONIG_OPTION_OFF(syn.options, ONIG_OPTION_ASCII_RANGE); */ r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + SLEN(pattern)), ONIG_OPTION_DEFAULT, #{REGENC}, &syn, &einfo); if (r) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r, &einfo); fprintf(err_file, "ERROR: %s\\n", s); nerror++; return ; } r = onig_search(reg, (UChar* )str, (UChar* )(str + SLEN(str)), (UChar* )str, (UChar* )(str + SLEN(str)), region, ONIG_OPTION_NONE); if (r < ONIG_MISMATCH) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r); fprintf(err_file, "ERROR: %s\\n", s); nerror++; return ; } if (r == ONIG_MISMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\\n", pattern, str); nfail++; } else { if (region->beg[mem] == from && region->end[mem] == to) { fprintf(stdout, "OK: /%s/ '%s'\\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\\n", pattern, str, from, to, region->beg[mem], region->end[mem]); nfail++; } } } onig_free(reg); #endif } static void x2(char* pattern, char* str, int from, int to) { xx(pattern, str, from, to, 0, 0); } static void x3(char* pattern, char* str, int from, int to, int mem) { xx(pattern, str, from, to, mem, 0); } static void n(char* pattern, char* str) { xx(pattern, str, 0, 0, 0, 1); } extern int main(int argc, char* argv[]) { err_file = stdout; #ifdef POSIX_TEST reg_set_encoding(#{REGENC.sub(/\AONIG_/, 'REG_POSIX_')}); #else region = onig_region_new(); #endif EOS PAT = '\\/([^\\\\\\/]*(?:\\\\.[^\\\\\\/]*)*)\\/' CM = '\s*,\s*' RX2 = %r{\Ax\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)\)} RI2 = %r{\Ai\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)\)} RX3 = %r{\Ax\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)#{CM}(\S+)\)} RN = %r{\An\(#{PAT}#{CM}('[^']*'|"[^"]*")\)} #' while line = gets() if (m = RX2.match(line)) reg = conv_reg(m[1]) str = conv_str(m[2]) printf(" x2(\"%s\", \"%s\", %s, %s);\n", reg, str, m[3], m[4]) elsif (m = RI2.match(line)) reg = conv_reg(m[1]) str = conv_str(m[2]) printf(" x2(\"%s\", \"%s\", %s, %s);\n", reg, str, m[3], m[4]) elsif (m = RX3.match(line)) reg = conv_reg(m[1]) str = conv_str(m[2]) printf(" x3(\"%s\", \"%s\", %s, %s, %s);\n", reg, str, m[3], m[4], m[5]) elsif (m = RN.match(line)) reg = conv_reg(m[1]) str = conv_str(m[2]) printf(" n(\"%s\", \"%s\");\n", reg, str) else end end print(<<'EOS') fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d (by Onigmo %s)\n", nsucc, nfail, nerror, onig_version()); #ifndef POSIX_TEST onig_region_free(region, 1); onig_end(); #endif return ((nfail == 0 && nerror == 0) ? 0 : -1); } EOS # END OF SCRIPT ================================================ FILE: src/Onigmo/testconvu.rb ================================================ #!/usr/local/bin/ruby -Ke # testconvu.rb # Copyright (C) 2004-2006 K.Kosako (sndgk393 AT ybb DOT ne DOT jp) require 'iconv' WINDOWS = (ARGV.size > 0 && /^-win/i =~ ARGV[0]) ARGV.shift if WINDOWS BIG_ENDIAN = 1 LITTLE_ENDIAN = 2 ICV_BE = Iconv.new('UTF-16BE', 'EUC-JP') ICV_LE = Iconv.new('UTF-16LE', 'EUC-JP') def eucjp_char_pos(s, byte_pos) pos = 0 i = 0 while (i < byte_pos) x = s[i] if ((x >= 0xa1 && x <= 0xfe) || x == 0x8e) i += 2 elsif (x == 0x8f) i += 3 else i += 1 end pos += 1 end return pos end def utf16_byte_pos(endian, s, char_pos) i = 0 while (char_pos > 0) x = (endian == BIG_ENDIAN ? s[i] : s[i+1]) if (x >= 0xd8 && x <= 0xdb) i += 4 else i += 2 end char_pos -= 1 end return i end def s_escape(s) q = '' s.each_byte { |b| if (b < 0x20 || b >= 0x7f || b == 0x22 || b == 0x5c) q << sprintf("\\%03o", b) else q << b.chr end } q end def conv_to_utf16(endian, s) begin if (endian == BIG_ENDIAN) q = ICV_BE.iconv(s) else q = ICV_LE.iconv(s) end rescue Iconv::InvalidCharacter q = 'Invalid character' rescue Iconv::IllegalSequence STDERR.printf("Iconv::IllegalSequence: [%s]\n", s) return '' end q << "\000\000" s_escape(q) end def conv_reg(endian, s) s = s.gsub(/\\([0-7]{2,3})\\([0-7]{2,3})/) { $1.to_i(8).chr + $2.to_i(8).chr } s = s.gsub(/\\x([0-9A-Fa-f]{2})\\x([0-9A-Fa-f]{2})/) { $1.to_i(16).chr + $2.to_i(16).chr } if (endian == BIG_ENDIAN) s = s.gsub(/(\\[0-7]{2,3})/) { "\\000" + $1 } s = s.gsub(/(\\x[0-9A-Fa-f]{2})/) { "\\x00" + $1 } else s = s.gsub(/(\\[0-7]{2,3})/) { $1 + "\\000" } s = s.gsub(/(\\x[0-9A-Fa-f]{2})/) { $1 + "\\x00" } end s = s.gsub(/\\/, '\\\\') #' if (WINDOWS) s = s.gsub(/\?\?/, '?\\?') # escape ANSI trigraph end conv_to_utf16(endian, s) end def conv_str(endian, s, from, to) if (s[0] == ?') s = s[1..-2] q = s.gsub(/\\/, '\\\\') #' else q = s[1..-2] q.gsub!(/\\n/, "\x0a") q.gsub!(/\\t/, "\x09") q.gsub!(/\\v/, "\x0b") q.gsub!(/\\r/, "\x0d") q.gsub!(/\\f/, "\x0c") q.gsub!(/\\a/, "\x07") q.gsub!(/\\e/, "\x1b") q.gsub!(/\\([0-7]{2,3})/) { $1.to_i(8).chr } q.gsub!(/\\x([0-9A-Fa-f]{2})/) { $1.to_i(16).chr } end from = from.to_i to = to.to_i eucjp_from = eucjp_char_pos(q, from) eucjp_to = eucjp_char_pos(q, to) s = conv_to_utf16(endian, q) from = utf16_byte_pos(endian, s, eucjp_from) to = utf16_byte_pos(endian, s, eucjp_to) return s, from, to end print(<<"EOS") /* * This program was generated by testconv.rb. */ #include #ifdef POSIX_TEST #include "onigposix.h" #else #include "oniguruma.h" #endif static int nsucc = 0; static int nfail = 0; static int nerror = 0; static FILE* err_file; #ifndef POSIX_TEST static OnigRegion* region; static OnigEncoding ENC; #endif #define ulen(p) onigenc_str_bytelen_null(ENC, (UChar* )p) static void uconv(char* from, char* to, int len) { int i; unsigned char c; char *q; q = to; for (i = 0; i < len; i += 2) { c = (unsigned char )from[i]; if (c == 0) { c = (unsigned char )from[i+1]; if (c < 0x20 || c >= 0x7f || c == 0x5c || c == 0x22) { sprintf(q, "\\\\%03o", c); q += 4; } else { sprintf(q, "%c", c); q++; } } else { sprintf(q, "\\\\%03o", c); q += 4; c = (unsigned char )from[i+1]; sprintf(q, "\\\\%03o", c); q += 4; } } *q = 0; } static void xx(char* pattern, char* str, int from, int to, int mem, int not) { int r; char cpat[4000], cstr[4000]; #ifdef POSIX_TEST regex_t reg; char buf[200]; regmatch_t pmatch[20]; uconv(pattern, cpat, ulen(pattern)); uconv(str, cstr, ulen(str)); r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\\n", buf); nerror++; return ; } r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\\n", buf); nerror++; return ; } if (r == REG_NOMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\\n", cpat, cstr); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\\n", cpat, cstr); nfail++; } else { if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { fprintf(stdout, "OK: /%s/ '%s'\\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\\n", cpat, cstr, from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); nfail++; } } } regfree(®); #else regex_t* reg; OnigCompileInfo ci; OnigErrorInfo einfo; OnigSyntaxType syn = *ONIG_SYNTAX_DEFAULT; /* ONIG_OPTION_OFF(syn.options, ONIG_OPTION_ASCII_RANGE); */ uconv(pattern, cpat, ulen(pattern)); uconv(str, cstr, ulen(str)); #if 0 r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + ulen(pattern)), ONIG_OPTION_DEFAULT, ENC, &syn, &einfo); #else ci.num_of_elements = 5; ci.pattern_enc = ENC; ci.target_enc = ENC; ci.syntax = &syn; ci.option = ONIG_OPTION_DEFAULT; ci.case_fold_flag = ONIGENC_CASE_FOLD_DEFAULT; r = onig_new_deluxe(®, (UChar* )pattern, (UChar* )(pattern + ulen(pattern)), &ci, &einfo); #endif if (r) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(err_file, "ERROR: %s\\n", s); nerror++; return ; } r = onig_search(reg, (UChar* )str, (UChar* )(str + ulen(str)), (UChar* )str, (UChar* )(str + ulen(str)), region, ONIG_OPTION_NONE); if (r < ONIG_MISMATCH) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(err_file, "ERROR: %s\\n", s); nerror++; return ; } if (r == ONIG_MISMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\\n", cpat, cstr); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\\n", cpat, cstr); nfail++; } else { if (region->beg[mem] == from && region->end[mem] == to) { fprintf(stdout, "OK: /%s/ '%s'\\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\\n", cpat, cstr, from, to, region->beg[mem], region->end[mem]); nfail++; } } } onig_free(reg); #endif } static void x2(char* pattern, char* str, int from, int to) { xx(pattern, str, from, to, 0, 0); } static void x3(char* pattern, char* str, int from, int to, int mem) { xx(pattern, str, from, to, mem, 0); } static void n(char* pattern, char* str) { xx(pattern, str, 0, 0, 0, 1); } extern int main(int argc, char* argv[]) { err_file = stdout; #ifndef POSIX_TEST region = onig_region_new(); #endif EOS PAT = '\\/([^\\\\\\/]*(?:\\\\.[^\\\\\\/]*)*)\\/' CM = /\s*,\s*/ RX2 = %r{\Ax\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)\)} RI2 = %r{\Ai\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)\)} RX3 = %r{\Ax\(#{PAT}#{CM}('[^']*'|"[^"]*")#{CM}(\S+)#{CM}(\S+)#{CM}(\S+)\)} RN = %r{\An\(#{PAT}#{CM}('[^']*'|"[^"]*")\)} #' def convert(endian, fp) if (endian == BIG_ENDIAN) se = 'BE' else se = 'LE' end print(<<"EOS") #ifdef POSIX_TEST reg_set_encoding(REG_POSIX_ENCODING_UTF16_#{se}); #else ENC = ONIG_ENCODING_UTF16_#{se}; #endif EOS while line = fp.gets() if (m = RX2.match(line)) reg = conv_reg(endian, m[1]) str, from, to = conv_str(endian, m[2], m[3], m[4]) printf(" x2(\"%s\", \"%s\", %s, %s);\n", reg, str, from, to) elsif (m = RI2.match(line)) reg = conv_reg(endian, m[1]) str, from, to = conv_str(endian, m[2], m[3], m[4]) printf(" x2(\"%s\", \"%s\", %s, %s);\n", reg, str, from, to) elsif (m = RX3.match(line)) reg = conv_reg(endian, m[1]) str, from, to = conv_str(endian, m[2], m[3], m[4]) printf(" x3(\"%s\", \"%s\", %s, %s, %s);\n", reg, str, from, to, m[5]) elsif (m = RN.match(line)) reg = conv_reg(endian, m[1]) str, from, to = conv_str(endian, m[2], 0, 0) printf(" n(\"%s\", \"%s\");\n", reg, str) else end end end File::open(ARGV[0]) { |fp| convert(BIG_ENDIAN, fp) } #File::open(ARGV[0]) { |fp| # convert(LITTLE_ENDIAN, fp) #} ICV_BE.close ICV_LE.close print(<<'EOS') fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d (by Onigmo %s)\n", nsucc, nfail, nerror, onig_version()); #ifndef POSIX_TEST onig_region_free(region, 1); onig_end(); #endif return ((nfail == 0 && nerror == 0) ? 0 : -1); } EOS # END OF SCRIPT ================================================ FILE: src/Onigmo/testpy.py ================================================ #!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function, unicode_literals from ctypes import * import onig import sys import io import locale nerror = 0 nsucc = 0 nfail = 0 region = 0 onig_encoding = onig.ONIG_ENCODING_EUC_JP encoding = onig_encoding[0].name.decode() class strptr: """a helper class to get a pointer to a string""" def __init__(self, s): if not isinstance(s, bytes): raise TypeError self._str = s try: self._ptr = cast(self._str, c_void_p) # CPython 2.x/3.x except TypeError: self._ptr = c_void_p(self._str) # PyPy 1.x def getptr(self, offset=0): if offset == -1: # -1 means the end of the string offset = len(self._str) elif offset > len(self._str): raise IndexError return self._ptr.value + offset def cc_to_cb(s, enc, cc): """convert char count to byte count arguments: s -- unicode string enc -- encoding name cc -- char count """ s = s.encode('UTF-32LE') clen = cc * 4 if clen > len(s): raise IndexError return len(s[:clen].decode('UTF-32LE').encode(enc)) def print_result(result, pattern, file=None): if not file: file = sys.stdout print(result + ": ", end='', file=file) try: print(pattern, file=file) except UnicodeEncodeError as e: print('(' + str(e) + ')') def xx(pattern, target, s_from, s_to, mem, not_match): global nerror global nsucc global nfail global region reg = onig.OnigRegex() einfo = onig.OnigErrorInfo() syn = onig.OnigSyntaxType() msg = create_string_buffer(onig.ONIG_MAX_ERROR_MESSAGE_LEN) pattern2 = pattern if not isinstance(pattern, bytes): pattern2 = pattern.encode(encoding) patternp = strptr(pattern2) target2 = target if not isinstance(target, bytes): s_from = cc_to_cb(target, encoding, s_from) s_to = cc_to_cb(target, encoding, s_to) target2 = target.encode(encoding) targetp = strptr(target2) # special syntactic settings onig.onig_copy_syntax(byref(syn), onig.ONIG_SYNTAX_DEFAULT) syn.options &= ~onig.ONIG_OPTION_ASCII_RANGE syn.behavior &= ~onig.ONIG_SYN_POSIX_BRACKET_ALWAYS_ALL_RANGE r = onig.onig_new(byref(reg), patternp.getptr(), patternp.getptr(-1), onig.ONIG_OPTION_DEFAULT, onig_encoding, byref(syn), byref(einfo)); if r != 0: onig.onig_error_code_to_str(msg, r, byref(einfo)) nerror += 1 print_result("ERROR", "%s (/%s/ '%s')" % (msg.value, pattern, target), file=sys.stderr) return r = onig.onig_search(reg, targetp.getptr(), targetp.getptr(-1), targetp.getptr(), targetp.getptr(-1), region, onig.ONIG_OPTION_NONE); if r < onig.ONIG_MISMATCH: onig.onig_error_code_to_str(msg, r) nerror += 1 print_result("ERROR", "%s (/%s/ '%s')" % (msg.value, pattern, target), file=sys.stderr) return if r == onig.ONIG_MISMATCH: if not_match: nsucc += 1 print_result("OK(N)", "/%s/ '%s'" % (pattern, target)) else: nfail += 1 print_result("FAIL", "/%s/ '%s'" % (pattern, target)) else: if not_match: nfail += 1 print_result("FAIL(N)", "/%s/ '%s'" % (pattern, target)) else: start = region[0].beg[mem] end = region[0].end[mem] if (start == s_from) and (end == s_to): nsucc += 1 print_result("OK", "/%s/ '%s'" % (pattern, target)) else: nfail += 1 print_result("FAIL", "/%s/ '%s' %d-%d : %d-%d" % (pattern, target, s_from, s_to, start, end)) onig.onig_free(reg) def x2(pattern, target, s_from, s_to): xx(pattern, target, s_from, s_to, 0, False) def x3(pattern, target, s_from, s_to, mem): xx(pattern, target, s_from, s_to, mem, False) def n(pattern, target): xx(pattern, target, 0, 0, 0, True) def is_unicode_encoding(enc): return enc in (onig.ONIG_ENCODING_UTF16_LE, onig.ONIG_ENCODING_UTF16_BE, onig.ONIG_ENCODING_UTF8) def main(): global region global onig_encoding global encoding region = onig.onig_region_new() # set encoding of the test target if len(sys.argv) > 1: encs = {"EUC-JP": onig.ONIG_ENCODING_EUC_JP, "SJIS": onig.ONIG_ENCODING_SJIS, "UTF-8": onig.ONIG_ENCODING_UTF8, "UTF-16LE": onig.ONIG_ENCODING_UTF16_LE, "UTF-16BE": onig.ONIG_ENCODING_UTF16_BE} try: onig_encoding = encs[sys.argv[1]] except KeyError: print("test target encoding error") print("Usage: python testpy.py [test target encoding] [output encoding]") sys.exit() encoding = onig_encoding[0].name.decode() # set encoding of stdout/stderr if len(sys.argv) > 2: outenc = sys.argv[2] else: outenc = locale.getpreferredencoding() def get_text_writer(fileno, **kwargs): kw = dict(kwargs) kw.setdefault('errors', 'backslashreplace') kw.setdefault('closefd', False) writer = io.open(fileno, mode='w', **kw) # work around for Python 2.x write = writer.write # save the original write() function enc = locale.getpreferredencoding() writer.write = lambda s: write(s.decode(enc)) \ if isinstance(s, bytes) else write(s) # convert to unistr return writer sys.stdout = get_text_writer(sys.stdout.fileno(), encoding=outenc) sys.stderr = get_text_writer(sys.stderr.fileno(), encoding=outenc) # Copied from onig-5.9.2/testc.c # '?\?' which is used to avoid trigraph is replaced by '??'. # Match positions are specified by unit of character instead of byte. x2("", "", 0, 0); x2("^", "", 0, 0); x2("$", "", 0, 0); x2("\\G", "", 0, 0); x2("\\A", "", 0, 0); x2("\\Z", "", 0, 0); x2("\\z", "", 0, 0); x2("^$", "", 0, 0); x2("\\ca", "\001", 0, 1); x2("\\C-b", "\002", 0, 1); x2("\\c\\\\", "\034", 0, 1); x2("q[\\c\\\\]", "q\034", 0, 2); x2("", "a", 0, 0); x2("a", "a", 0, 1); if onig_encoding == onig.ONIG_ENCODING_UTF16_LE: x2("\\x61\\x00", "a", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_UTF16_BE: x2("\\x00\\x61", "a", 0, 1); else: x2("\\x61", "a", 0, 1); x2("aa", "aa", 0, 2); x2("aaa", "aaa", 0, 3); x2("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 35); x2("ab", "ab", 0, 2); x2("b", "ab", 1, 2); x2("bc", "abc", 1, 3); x2("(?i:#RET#)", "#INS##RET#", 5, 10); if onig_encoding == onig.ONIG_ENCODING_UTF16_LE: x2("\\17\\00", "\017", 0, 1); x2("\\x1f\\x00", "\x1f", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_UTF16_BE: x2("\\00\\17", "\017", 0, 1); x2("\\x00\\x1f", "\x1f", 0, 1); else: x2("\\17", "\017", 0, 1); x2("\\x1f", "\x1f", 0, 1); x2("a(?#....\\\\JJJJ)b", "ab", 0, 2); x2("(?x) G (o O(?-x)oO) g L", "GoOoOgLe", 0, 7); x2(".", "a", 0, 1); n(".", ""); x2("..", "ab", 0, 2); x2("\\w", "e", 0, 1); n("\\W", "e"); x2("\\s", " ", 0, 1); x2("\\S", "b", 0, 1); x2("\\d", "4", 0, 1); n("\\D", "4"); x2("\\b", "z ", 0, 0); x2("\\b", " z", 1, 1); x2("\\B", "zz ", 1, 1); x2("\\B", "z ", 2, 2); x2("\\B", " z", 0, 0); x2("[ab]", "b", 0, 1); n("[ab]", "c"); x2("[a-z]", "t", 0, 1); n("[^a]", "a"); x2("[^a]", "\n", 0, 1); x2("[]]", "]", 0, 1); n("[^]]", "]"); x2("[\\^]+", "0^^1", 1, 3); x2("[b-]", "b", 0, 1); x2("[b-]", "-", 0, 1); x2("[\\w]", "z", 0, 1); n("[\\w]", " "); x2("[\\W]", "b$", 1, 2); x2("[\\d]", "5", 0, 1); n("[\\d]", "e"); x2("[\\D]", "t", 0, 1); n("[\\D]", "3"); x2("[\\s]", " ", 0, 1); n("[\\s]", "a"); x2("[\\S]", "b", 0, 1); n("[\\S]", " "); x2("[\\w\\d]", "2", 0, 1); n("[\\w\\d]", " "); x2("[[:upper:]]", "B", 0, 1); x2("[*[:xdigit:]+]", "+", 0, 1); x2("[*[:xdigit:]+]", "GHIKK-9+*", 6, 7); x2("[*[:xdigit:]+]", "-@^+", 3, 4); n("[[:upper]]", "A"); x2("[[:upper]]", ":", 0, 1); if onig_encoding == onig.ONIG_ENCODING_UTF16_LE: x2("[\\044\\000-\\047\\000]", "\046", 0, 1); x2("[\\x5a\\x00-\\x5c\\x00]", "\x5b", 0, 1); x2("[\\x6A\\x00-\\x6D\\x00]", "\x6c", 0, 1); n("[\\x6A\\x00-\\x6D\\x00]", "\x6E"); elif onig_encoding == onig.ONIG_ENCODING_UTF16_BE: x2("[\\000\\044-\\000\\047]", "\046", 0, 1); x2("[\\x00\\x5a-\\x00\\x5c]", "\x5b", 0, 1); x2("[\\x00\\x6A-\\x00\\x6D]", "\x6c", 0, 1); n("[\\x00\\x6A-\\x00\\x6D]", "\x6E"); else: x2("[\\044-\\047]", "\046", 0, 1); x2("[\\x5a-\\x5c]", "\x5b", 0, 1); x2("[\\x6A-\\x6D]", "\x6c", 0, 1); n("[\\x6A-\\x6D]", "\x6E"); n("^[0-9A-F]+ 0+ UNDEF ", "75F 00000000 SECT14A notype () External | _rb_apply"); x2("[\\[]", "[", 0, 1); x2("[\\]]", "]", 0, 1); x2("[&]", "&", 0, 1); x2("[[ab]]", "b", 0, 1); x2("[[ab]c]", "c", 0, 1); n("[[^a]]", "a"); n("[^[a]]", "a"); x2("[[ab]&&bc]", "b", 0, 1); n("[[ab]&&bc]", "a"); n("[[ab]&&bc]", "c"); x2("[a-z&&b-y&&c-x]", "w", 0, 1); n("[^a-z&&b-y&&c-x]", "w"); x2("[[^a&&a]&&a-z]", "b", 0, 1); n("[[^a&&a]&&a-z]", "a"); x2("[[^a-z&&bcdef]&&[^c-g]]", "h", 0, 1); n("[[^a-z&&bcdef]&&[^c-g]]", "c"); x2("[^[^abc]&&[^cde]]", "c", 0, 1); x2("[^[^abc]&&[^cde]]", "e", 0, 1); n("[^[^abc]&&[^cde]]", "f"); x2("[a-&&-a]", "-", 0, 1); n("[a\\-&&\\-a]", "&"); n("\\wabc", " abc"); x2("a\\Wbc", "a bc", 0, 4); x2("a.b.c", "aabbc", 0, 5); x2(".\\wb\\W..c", "abb bcc", 0, 7); x2("\\s\\wzzz", " zzzz", 0, 5); x2("aa.b", "aabb", 0, 4); n(".a", "ab"); x2(".a", "aa", 0, 2); x2("^a", "a", 0, 1); x2("^a$", "a", 0, 1); x2("^\\w$", "a", 0, 1); n("^\\w$", " "); x2("^\\wab$", "zab", 0, 3); x2("^\\wabcdef$", "zabcdef", 0, 7); x2("^\\w...def$", "zabcdef", 0, 7); x2("\\w\\w\\s\\Waaa\\d", "aa aaa4", 0, 8); x2("\\A\\Z", "", 0, 0); x2("\\Axyz", "xyz", 0, 3); x2("xyz\\Z", "xyz", 0, 3); x2("xyz\\z", "xyz", 0, 3); x2("a\\Z", "a", 0, 1); x2("\\Gaz", "az", 0, 2); n("\\Gz", "bza"); n("az\\G", "az"); n("az\\A", "az"); n("a\\Az", "az"); x2("\\^\\$", "^$", 0, 2); x2("^x?y", "xy", 0, 2); x2("^(x?y)", "xy", 0, 2); x2("\\w", "_", 0, 1); n("\\W", "_"); x2("(?=z)z", "z", 0, 1); n("(?=z).", "a"); x2("(?!z)a", "a", 0, 1); n("(?!z)a", "z"); x2("(?i:a)", "a", 0, 1); x2("(?i:a)", "A", 0, 1); x2("(?i:A)", "a", 0, 1); n("(?i:A)", "b"); x2("(?i:[A-Z])", "a", 0, 1); x2("(?i:[f-m])", "H", 0, 1); x2("(?i:[f-m])", "h", 0, 1); n("(?i:[f-m])", "e"); x2("(?i:[A-c])", "D", 0, 1); n("(?i:[^a-z])", "A"); n("(?i:[^a-z])", "a"); x2("(?i:[!-k])", "Z", 0, 1); x2("(?i:[!-k])", "7", 0, 1); x2("(?i:[T-}])", "b", 0, 1); x2("(?i:[T-}])", "{", 0, 1); x2("(?i:\\?a)", "?A", 0, 2); x2("(?i:\\*A)", "*a", 0, 2); n(".", "\n"); x2("(?m:.)", "\n", 0, 1); x2("(?m:a.)", "a\n", 0, 2); x2("(?m:.b)", "a\nb", 1, 3); x2(".*abc", "dddabdd\nddabc", 8, 13); x2("(?m:.*abc)", "dddabddabc", 0, 10); n("(?i)(?-i)a", "A"); n("(?i)(?-i:a)", "A"); x2("a?", "", 0, 0); x2("a?", "b", 0, 0); x2("a?", "a", 0, 1); x2("a*", "", 0, 0); x2("a*", "a", 0, 1); x2("a*", "aaa", 0, 3); x2("a*", "baaaa", 0, 0); n("a+", ""); x2("a+", "a", 0, 1); x2("a+", "aaaa", 0, 4); x2("a+", "aabbb", 0, 2); x2("a+", "baaaa", 1, 5); x2(".?", "", 0, 0); x2(".?", "f", 0, 1); x2(".?", "\n", 0, 0); x2(".*", "", 0, 0); x2(".*", "abcde", 0, 5); x2(".+", "z", 0, 1); x2(".+", "zdswer\n", 0, 6); x2("(.*)a\\1f", "babfbac", 0, 4); x2("(.*)a\\1f", "bacbabf", 3, 7); x2("((.*)a\\2f)", "bacbabf", 3, 7); x2("(.*)a\\1f", "baczzzzzz\nbazz\nzzzzbabf", 19, 23); x2("a|b", "a", 0, 1); x2("a|b", "b", 0, 1); x2("|a", "a", 0, 0); x2("(|a)", "a", 0, 0); x2("ab|bc", "ab", 0, 2); x2("ab|bc", "bc", 0, 2); x2("z(?:ab|bc)", "zbc", 0, 3); x2("a(?:ab|bc)c", "aabc", 0, 4); x2("ab|(?:ac|az)", "az", 0, 2); x2("a|b|c", "dc", 1, 2); x2("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "pqr", 0, 2); n("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "mn"); x2("a|^z", "ba", 1, 2); x2("a|^z", "za", 0, 1); x2("a|\\Gz", "bza", 2, 3); x2("a|\\Gz", "za", 0, 1); x2("a|\\Az", "bza", 2, 3); x2("a|\\Az", "za", 0, 1); x2("a|b\\Z", "ba", 1, 2); x2("a|b\\Z", "b", 0, 1); x2("a|b\\z", "ba", 1, 2); x2("a|b\\z", "b", 0, 1); x2("\\w|\\s", " ", 0, 1); n("\\w|\\w", " "); x2("\\w|%", "%", 0, 1); x2("\\w|[&$]", "&", 0, 1); x2("[b-d]|[^e-z]", "a", 0, 1); x2("(?:a|[c-f])|bz", "dz", 0, 1); x2("(?:a|[c-f])|bz", "bz", 0, 2); x2("abc|(?=zz)..f", "zzf", 0, 3); x2("abc|(?!zz)..f", "abf", 0, 3); x2("(?=za)..a|(?=zz)..a", "zza", 0, 3); n("(?>a|abd)c", "abdc"); x2("(?>abd|a)c", "abdc", 0, 4); x2("a?|b", "a", 0, 1); x2("a?|b", "b", 0, 0); x2("a?|b", "", 0, 0); x2("a*|b", "aa", 0, 2); x2("a*|b*", "ba", 0, 0); x2("a*|b*", "ab", 0, 1); x2("a+|b*", "", 0, 0); x2("a+|b*", "bbb", 0, 3); x2("a+|b*", "abbb", 0, 1); n("a+|b+", ""); x2("(a|b)?", "b", 0, 1); x2("(a|b)*", "ba", 0, 2); x2("(a|b)+", "bab", 0, 3); x2("(ab|ca)+", "caabbc", 0, 4); x2("(ab|ca)+", "aabca", 1, 5); x2("(ab|ca)+", "abzca", 0, 2); x2("(a|bab)+", "ababa", 0, 5); x2("(a|bab)+", "ba", 1, 2); x2("(a|bab)+", "baaaba", 1, 4); x2("(?:a|b)(?:a|b)", "ab", 0, 2); x2("(?:a*|b*)(?:a*|b*)", "aaabbb", 0, 3); x2("(?:a*|b*)(?:a+|b+)", "aaabbb", 0, 6); x2("(?:a+|b+){2}", "aaabbb", 0, 6); x2("h{0,}", "hhhh", 0, 4); x2("(?:a+|b+){1,2}", "aaabbb", 0, 6); n("ax{2}*a", "0axxxa1"); n("a.{0,2}a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXXa0"); x2("^a{2,}?a$", "aaa", 0, 3); x2("^[a-z]{2,}?$", "aaa", 0, 3); x2("(?:a+|\\Ab*)cc", "cc", 0, 2); n("(?:a+|\\Ab*)cc", "abcc"); x2("(?:^a+|b+)*c", "aabbbabc", 6, 8); x2("(?:^a+|b+)*c", "aabbbbc", 0, 7); x2("a|(?i)c", "C", 0, 1); x2("(?i)c|a", "C", 0, 1); x2("(?i)c|a", "A", 0, 1); x2("(?i:c)|a", "C", 0, 1); n("(?i:c)|a", "A"); x2("[abc]?", "abc", 0, 1); x2("[abc]*", "abc", 0, 3); x2("[^abc]*", "abc", 0, 0); n("[^abc]+", "abc"); x2("a??", "aaa", 0, 0); x2("ba??b", "bab", 0, 3); x2("a*?", "aaa", 0, 0); x2("ba*?", "baa", 0, 1); x2("ba*?b", "baab", 0, 4); x2("a+?", "aaa", 0, 1); x2("ba+?", "baa", 0, 2); x2("ba+?b", "baab", 0, 4); x2("(?:a?)??", "a", 0, 0); x2("(?:a??)?", "a", 0, 0); x2("(?:a?)+?", "aaa", 0, 1); x2("(?:a+)??", "aaa", 0, 0); x2("(?:a+)??b", "aaab", 0, 4); x2("(?:ab)?{2}", "", 0, 0); x2("(?:ab)?{2}", "ababa", 0, 4); x2("(?:ab)*{0}", "ababa", 0, 0); x2("(?:ab){3,}", "abababab", 0, 8); n("(?:ab){3,}", "abab"); x2("(?:ab){2,4}", "ababab", 0, 6); x2("(?:ab){2,4}", "ababababab", 0, 8); x2("(?:ab){2,4}?", "ababababab", 0, 4); x2("(?:ab){,}", "ab{,}", 0, 5); x2("(?:abc)+?{2}", "abcabcabc", 0, 6); x2("(?:X*)(?i:xa)", "XXXa", 0, 4); x2("(d+)([^abc]z)", "dddz", 0, 4); x2("([^abc]*)([^abc]z)", "dddz", 0, 4); x2("(\\w+)(\\wz)", "dddz", 0, 4); x3("(a)", "a", 0, 1, 1); x3("(ab)", "ab", 0, 2, 1); x2("((ab))", "ab", 0, 2); x3("((ab))", "ab", 0, 2, 1); x3("((ab))", "ab", 0, 2, 2); x3("((((((((((((((((((((ab))))))))))))))))))))", "ab", 0, 2, 20); x3("(ab)(cd)", "abcd", 0, 2, 1); x3("(ab)(cd)", "abcd", 2, 4, 2); x3("()(a)bc(def)ghijk", "abcdefghijk", 3, 6, 3); x3("(()(a)bc(def)ghijk)", "abcdefghijk", 3, 6, 4); x2("(^a)", "a", 0, 1); x3("(a)|(a)", "ba", 1, 2, 1); x3("(^a)|(a)", "ba", 1, 2, 2); x3("(a?)", "aaa", 0, 1, 1); x3("(a*)", "aaa", 0, 3, 1); x3("(a*)", "", 0, 0, 1); x3("(a+)", "aaaaaaa", 0, 7, 1); x3("(a+|b*)", "bbbaa", 0, 3, 1); x3("(a+|b?)", "bbbaa", 0, 1, 1); x3("(abc)?", "abc", 0, 3, 1); x3("(abc)*", "abc", 0, 3, 1); x3("(abc)+", "abc", 0, 3, 1); x3("(xyz|abc)+", "abc", 0, 3, 1); x3("([xyz][abc]|abc)+", "abc", 0, 3, 1); x3("((?i:abc))", "AbC", 0, 3, 1); x2("(abc)(?i:\\1)", "abcABC", 0, 6); x3("((?m:a.c))", "a\nc", 0, 3, 1); x3("((?=az)a)", "azb", 0, 1, 1); x3("abc|(.abd)", "zabd", 0, 4, 1); x2("(?:abc)|(ABC)", "abc", 0, 3); x3("(?i:(abc))|(zzz)", "ABC", 0, 3, 1); x3("a*(.)", "aaaaz", 4, 5, 1); x3("a*?(.)", "aaaaz", 0, 1, 1); x3("a*?(c)", "aaaac", 4, 5, 1); x3("[bcd]a*(.)", "caaaaz", 5, 6, 1); x3("(\\Abb)cc", "bbcc", 0, 2, 1); n("(\\Abb)cc", "zbbcc"); x3("(^bb)cc", "bbcc", 0, 2, 1); n("(^bb)cc", "zbbcc"); x3("cc(bb$)", "ccbb", 2, 4, 1); n("cc(bb$)", "ccbbb"); n("(\\1)", ""); n("\\1(a)", "aa"); n("(a(b)\\1)\\2+", "ababb"); n("(?:(?:\\1|z)(a))+$", "zaa"); x2("(?:(?:\\1|z)(a))+$", "zaaa", 0, 4); x2("(a)(?=\\1)", "aa", 0, 1); n("(a)$|\\1", "az"); x2("(a)\\1", "aa", 0, 2); n("(a)\\1", "ab"); x2("(a?)\\1", "aa", 0, 2); x2("(a??)\\1", "aa", 0, 0); x2("(a*)\\1", "aaaaa", 0, 4); x3("(a*)\\1", "aaaaa", 0, 2, 1); x2("a(b*)\\1", "abbbb", 0, 5); x2("a(b*)\\1", "ab", 0, 1); x2("(a*)(b*)\\1\\2", "aaabbaaabb", 0, 10); x2("(a*)(b*)\\2", "aaabbbb", 0, 7); x2("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 8); x3("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 3, 7); x2("(a)(b)(c)\\2\\1\\3", "abcbac", 0, 6); x2("([a-d])\\1", "cc", 0, 2); x2("(\\w\\d\\s)\\1", "f5 f5 ", 0, 6); n("(\\w\\d\\s)\\1", "f5 f5"); x2("(who|[a-c]{3})\\1", "whowho", 0, 6); x2("...(who|[a-c]{3})\\1", "abcwhowho", 0, 9); x2("(who|[a-c]{3})\\1", "cbccbc", 0, 6); x2("(^a)\\1", "aa", 0, 2); n("(^a)\\1", "baa"); n("(a$)\\1", "aa"); n("(ab\\Z)\\1", "ab"); x2("(a*\\Z)\\1", "a", 1, 1); x2(".(a*\\Z)\\1", "ba", 1, 2); x3("(.(abc)\\2)", "zabcabc", 0, 7, 1); x3("(.(..\\d.)\\2)", "z12341234", 0, 9, 1); x2("((?i:az))\\1", "AzAz", 0, 4); n("((?i:az))\\1", "Azaz"); x2("(?<=a)b", "ab", 1, 2); n("(?<=a)b", "bb"); x2("(?<=a|b)b", "bb", 1, 2); x2("(?<=a|bc)b", "bcb", 2, 3); x2("(?<=a|bc)b", "ab", 1, 2); x2("(?<=a|bc||defghij|klmnopq|r)z", "rz", 1, 2); x2("(a)\\g<1>", "aa", 0, 2); x2("(?a)", "a", 0, 1); x2("(?ab)\\g", "abab", 0, 4); x2("(?.zv.)\\k", "azvbazvb", 0, 8); x2("(?<=\\g)|-\\zEND (?XyZ)", "XyZ", 3, 3); x2("(?|a\\g)+", "", 0, 0); x2("(?|\\(\\g\\))+$", "()(())", 0, 6); x3("\\g(?.){0}", "X", 0, 1, 1); x2("\\g(abc|df(?.YZ){2,8}){0}", "XYZ", 0, 3); x2("\\A(?(a\\g)|)\\z", "aaaa", 0, 4); x2("(?|\\g\\g)\\z|\\zEND (?a|(b)\\g)", "bbbbabba", 0, 8); x2("(?\\w+\\sx)a+\\k", " fg xaaaaaaaafg x", 2, 18); x3("(z)()()(?<_9>a)\\g<_9>", "zaa", 2, 3, 1); x2("(.)(((?<_>a)))\\k<_>", "zaa", 0, 3); x2("((?\\d)|(?\\w))(\\k|\\k)", "ff", 0, 2); x2("(?:(?)|(?efg))\\k", "", 0, 0); x2("(?:(?abc)|(?efg))\\k", "abcefgefg", 3, 9); n("(?:(?abc)|(?efg))\\k", "abcefg"); x2("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "a-pyumpyum", 2, 10); x3("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "xxxxabcdefghijklmnabcdefghijklmn", 4, 18, 14); x3("(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?aaa)(?)$", "aaa", 0, 3, 16); x2("(?a|\\(\\g\\))", "a", 0, 1); x2("(?a|\\(\\g\\))", "((((((a))))))", 0, 13); x3("(?a|\\(\\g\\))", "((((((((a))))))))", 0, 17, 1); x2("\\g|\\zEND(?.*abc$)", "abcxxxabc", 0, 9); x2("\\g<1>|\\zEND(.a.)", "bac", 0, 3); x3("\\g<_A>\\g<_A>|\\zEND(.a.)(?<_A>.b.)", "xbxyby", 3, 6, 1); x2("\\A(?:\\g|\\g|\\zEND (?a|c\\gc)(?b|d\\gd))$", "cdcbcdc", 0, 7); x2("\\A(?|a\\g)\\z|\\zEND (?\\g)", "aaaa", 0, 4); x2("(?(a|b\\gc){3,5})", "baaaaca", 1, 5); x2("(?(a|b\\gc){3,5})", "baaaacaaaaa", 0, 10); x2("(?\\(([^\\(\\)]++|\\g)*+\\))", "((a))", 0, 5); x2("()*\\1", "", 0, 0); x2("(?:()|())*\\1\\2", "", 0, 0); x3("(?:\\1a|())*", "a", 0, 0, 1); x2("x((.)*)*x", "0x1x2x3", 1, 6); x2("x((.)*)*x(?i:\\1)\\Z", "0x1x2x1X2", 1, 9); x2("(?:()|()|()|()|()|())*\\2\\5", "", 0, 0); x2("(?:()|()|()|(x)|()|())*\\2b\\5", "b", 0, 1); if onig_encoding == onig.ONIG_ENCODING_UTF16_LE: x2("\\xFA\\x8F", "\u8ffa", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_UTF16_BE: x2("\\x8F\\xFA", "\u8ffa", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_UTF8: x2("\\xE8\\xBF\\xBA", "\u8ffa", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_SJIS: x2("\\xE7\\x92", "\u8ffa", 0, 1); elif onig_encoding == onig.ONIG_ENCODING_EUC_JP: x2("\\xED\\xF2", "\u8ffa", 0, 1); # "迺" x2("", "あ", 0, 0); x2("あ", "あ", 0, 1); n("い", "あ"); x2("うう", "うう", 0, 2); x2("あいう", "あいう", 0, 3); x2("こここここここここここここここここここここここここここここここここここ", "こここここここここここここここここここここここここここここここここここ", 0, 35); x2("あ", "いあ", 1, 2); x2("いう", "あいう", 1, 3); # x2(b"\\xca\\xb8", b"\xca\xb8", 0, 2); # "文" x2(".", "あ", 0, 1); x2("..", "かき", 0, 2); x2("\\w", "お", 0, 1); n("\\W", "あ"); x2("[\\W]", "う$", 1, 2); x2("\\S", "そ", 0, 1); x2("\\S", "漢", 0, 1); x2("\\b", "気 ", 0, 0); x2("\\b", " ほ", 1, 1); x2("\\B", "せそ ", 1, 1); x2("\\B", "う ", 2, 2); x2("\\B", " い", 0, 0); x2("[たち]", "ち", 0, 1); n("[なに]", "ぬ"); x2("[う-お]", "え", 0, 1); n("[^け]", "け"); x2("[\\w]", "ね", 0, 1); n("[\\d]", "ふ"); x2("[\\D]", "は", 0, 1); n("[\\s]", "く"); x2("[\\S]", "へ", 0, 1); x2("[\\w\\d]", "よ", 0, 1); x2("[\\w\\d]", " よ", 3, 4); n("\\w鬼車", " 鬼車"); x2("鬼\\W車", "鬼 車", 0, 3); x2("あ.い.う", "ああいいう", 0, 5); x2(".\\wう\\W..ぞ", "えうう うぞぞ", 0, 7); x2("\\s\\wこここ", " ここここ", 0, 5); x2("ああ.け", "ああけけ", 0, 4); n(".い", "いえ"); x2(".お", "おお", 0, 2); x2("^あ", "あ", 0, 1); x2("^む$", "む", 0, 1); x2("^\\w$", "に", 0, 1); x2("^\\wかきくけこ$", "zかきくけこ", 0, 6); x2("^\\w...うえお$", "zあいううえお", 0, 7); x2("\\w\\w\\s\\Wおおお\\d", "aお おおお4", 0, 8); x2("\\Aたちつ", "たちつ", 0, 3); x2("むめも\\Z", "むめも", 0, 3); x2("かきく\\z", "かきく", 0, 3); x2("かきく\\Z", "かきく\n", 0, 3); x2("\\Gぽぴ", "ぽぴ", 0, 2); n("\\Gえ", "うえお"); n("とて\\G", "とて"); n("まみ\\A", "まみ"); n("ま\\Aみ", "まみ"); x2("(?=せ)せ", "せ", 0, 1); n("(?=う).", "い"); x2("(?!う)か", "か", 0, 1); n("(?!と)あ", "と"); x2("(?i:あ)", "あ", 0, 1); x2("(?i:ぶべ)", "ぶべ", 0, 2); n("(?i:い)", "う"); x2("(?m:よ.)", "よ\n", 0, 2); x2("(?m:.め)", "ま\nめ", 1, 3); x2("あ?", "", 0, 0); x2("変?", "化", 0, 0); x2("変?", "変", 0, 1); x2("量*", "", 0, 0); x2("量*", "量", 0, 1); x2("子*", "子子子", 0, 3); x2("馬*", "鹿馬馬馬馬", 0, 0); n("山+", ""); x2("河+", "河", 0, 1); x2("時+", "時時時時", 0, 4); x2("え+", "ええううう", 0, 2); x2("う+", "おうううう", 1, 5); x2(".?", "た", 0, 1); x2(".*", "ぱぴぷぺ", 0, 4); x2(".+", "ろ", 0, 1); x2(".+", "いうえか\n", 0, 4); x2("あ|い", "あ", 0, 1); x2("あ|い", "い", 0, 1); x2("あい|いう", "あい", 0, 2); x2("あい|いう", "いう", 0, 2); x2("を(?:かき|きく)", "をかき", 0, 3); x2("を(?:かき|きく)け", "をきくけ", 0, 4); x2("あい|(?:あう|あを)", "あを", 0, 2); x2("あ|い|う", "えう", 1, 2); x2("あ|い|うえ|おかき|く|けこさ|しすせ|そ|たち|つてとなに|ぬね", "しすせ", 0, 3); n("あ|い|うえ|おかき|く|けこさ|しすせ|そ|たち|つてとなに|ぬね", "すせ"); x2("あ|^わ", "ぶあ", 1, 2); x2("あ|^を", "をあ", 0, 1); x2("鬼|\\G車", "け車鬼", 2, 3); x2("鬼|\\G車", "車鬼", 0, 1); x2("鬼|\\A車", "b車鬼", 2, 3); x2("鬼|\\A車", "車", 0, 1); x2("鬼|車\\Z", "車鬼", 1, 2); x2("鬼|車\\Z", "車", 0, 1); x2("鬼|車\\Z", "車\n", 0, 1); x2("鬼|車\\z", "車鬼", 1, 2); x2("鬼|車\\z", "車", 0, 1); x2("\\w|\\s", "お", 0, 1); x2("\\w|%", "%お", 0, 1); x2("\\w|[&$]", "う&", 0, 1); x2("[い-け]", "う", 0, 1); x2("[い-け]|[^か-こ]", "あ", 0, 1); x2("[い-け]|[^か-こ]", "か", 0, 1); x2("[^あ]", "\n", 0, 1); x2("(?:あ|[う-き])|いを", "うを", 0, 1); x2("(?:あ|[う-き])|いを", "いを", 0, 2); x2("あいう|(?=けけ)..ほ", "けけほ", 0, 3); x2("あいう|(?!けけ)..ほ", "あいほ", 0, 3); x2("(?=をあ)..あ|(?=をを)..あ", "ををあ", 0, 3); x2("(?<=あ|いう)い", "いうい", 2, 3); n("(?>あ|あいえ)う", "あいえう"); x2("(?>あいえ|あ)う", "あいえう", 0, 4); x2("あ?|い", "あ", 0, 1); x2("あ?|い", "い", 0, 0); x2("あ?|い", "", 0, 0); x2("あ*|い", "ああ", 0, 2); x2("あ*|い*", "いあ", 0, 0); x2("あ*|い*", "あい", 0, 1); x2("[aあ]*|い*", "aあいいい", 0, 2); x2("あ+|い*", "", 0, 0); x2("あ+|い*", "いいい", 0, 3); x2("あ+|い*", "あいいい", 0, 1); x2("あ+|い*", "aあいいい", 0, 0); n("あ+|い+", ""); x2("(あ|い)?", "い", 0, 1); x2("(あ|い)*", "いあ", 0, 2); x2("(あ|い)+", "いあい", 0, 3); x2("(あい|うあ)+", "うああいうえ", 0, 4); x2("(あい|うえ)+", "うああいうえ", 2, 6); x2("(あい|うあ)+", "ああいうあ", 1, 5); x2("(あい|うあ)+", "あいをうあ", 0, 2); x2("(あい|うあ)+", "$$zzzzあいをうあ", 6, 8); x2("(あ|いあい)+", "あいあいあ", 0, 5); x2("(あ|いあい)+", "いあ", 1, 2); x2("(あ|いあい)+", "いあああいあ", 1, 4); x2("(?:あ|い)(?:あ|い)", "あい", 0, 2); x2("(?:あ*|い*)(?:あ*|い*)", "あああいいい", 0, 3); x2("(?:あ*|い*)(?:あ+|い+)", "あああいいい", 0, 6); x2("(?:あ+|い+){2}", "あああいいい", 0, 6); x2("(?:あ+|い+){1,2}", "あああいいい", 0, 6); x2("(?:あ+|\\Aい*)うう", "うう", 0, 2); n("(?:あ+|\\Aい*)うう", "あいうう"); x2("(?:^あ+|い+)*う", "ああいいいあいう", 6, 8); x2("(?:^あ+|い+)*う", "ああいいいいう", 0, 7); x2("う{0,}", "うううう", 0, 4); x2("あ|(?i)c", "C", 0, 1); x2("(?i)c|あ", "C", 0, 1); x2("(?i:あ)|a", "a", 0, 1); n("(?i:あ)|a", "A"); x2("[あいう]?", "あいう", 0, 1); x2("[あいう]*", "あいう", 0, 3); x2("[^あいう]*", "あいう", 0, 0); n("[^あいう]+", "あいう"); x2("あ??", "あああ", 0, 0); x2("いあ??い", "いあい", 0, 3); x2("あ*?", "あああ", 0, 0); x2("いあ*?", "いああ", 0, 1); x2("いあ*?い", "いああい", 0, 4); x2("あ+?", "あああ", 0, 1); x2("いあ+?", "いああ", 0, 2); x2("いあ+?い", "いああい", 0, 4); x2("(?:天?)??", "天", 0, 0); x2("(?:天??)?", "天", 0, 0); x2("(?:夢?)+?", "夢夢夢", 0, 1); x2("(?:風+)??", "風風風", 0, 0); x2("(?:雪+)??霜", "雪雪雪霜", 0, 4); x2("(?:あい)?{2}", "", 0, 0); x2("(?:鬼車)?{2}", "鬼車鬼車鬼", 0, 4); x2("(?:鬼車)*{0}", "鬼車鬼車鬼", 0, 0); x2("(?:鬼車){3,}", "鬼車鬼車鬼車鬼車", 0, 8); n("(?:鬼車){3,}", "鬼車鬼車"); x2("(?:鬼車){2,4}", "鬼車鬼車鬼車", 0, 6); x2("(?:鬼車){2,4}", "鬼車鬼車鬼車鬼車鬼車", 0, 8); x2("(?:鬼車){2,4}?", "鬼車鬼車鬼車鬼車鬼車", 0, 4); x2("(?:鬼車){,}", "鬼車{,}", 0, 5); x2("(?:かきく)+?{2}", "かきくかきくかきく", 0, 6); x3("(火)", "火", 0, 1, 1); x3("(火水)", "火水", 0, 2, 1); x2("((時間))", "時間", 0, 2); x3("((風水))", "風水", 0, 2, 1); x3("((昨日))", "昨日", 0, 2, 2); x3("((((((((((((((((((((量子))))))))))))))))))))", "量子", 0, 2, 20); x3("(あい)(うえ)", "あいうえ", 0, 2, 1); x3("(あい)(うえ)", "あいうえ", 2, 4, 2); x3("()(あ)いう(えおか)きくけこ", "あいうえおかきくけこ", 3, 6, 3); x3("(()(あ)いう(えおか)きくけこ)", "あいうえおかきくけこ", 3, 6, 4); x3(".*(フォ)ン・マ(ン()シュタ)イン", "フォン・マンシュタイン", 5, 9, 2); x2("(^あ)", "あ", 0, 1); x3("(あ)|(あ)", "いあ", 1, 2, 1); x3("(^あ)|(あ)", "いあ", 1, 2, 2); x3("(あ?)", "あああ", 0, 1, 1); x3("(ま*)", "ままま", 0, 3, 1); x3("(と*)", "", 0, 0, 1); x3("(る+)", "るるるるるるる", 0, 7, 1); x3("(ふ+|へ*)", "ふふふへへ", 0, 3, 1); x3("(あ+|い?)", "いいいああ", 0, 1, 1); x3("(あいう)?", "あいう", 0, 3, 1); x3("(あいう)*", "あいう", 0, 3, 1); x3("(あいう)+", "あいう", 0, 3, 1); x3("(さしす|あいう)+", "あいう", 0, 3, 1); x3("([なにぬ][かきく]|かきく)+", "かきく", 0, 3, 1); x3("((?i:あいう))", "あいう", 0, 3, 1); x3("((?m:あ.う))", "あ\nう", 0, 3, 1); x3("((?=あん)あ)", "あんい", 0, 1, 1); x3("あいう|(.あいえ)", "んあいえ", 0, 4, 1); x3("あ*(.)", "ああああん", 4, 5, 1); x3("あ*?(.)", "ああああん", 0, 1, 1); x3("あ*?(ん)", "ああああん", 4, 5, 1); x3("[いうえ]あ*(.)", "えああああん", 5, 6, 1); x3("(\\Aいい)うう", "いいうう", 0, 2, 1); n("(\\Aいい)うう", "んいいうう"); x3("(^いい)うう", "いいうう", 0, 2, 1); n("(^いい)うう", "んいいうう"); x3("ろろ(るる$)", "ろろるる", 2, 4, 1); n("ろろ(るる$)", "ろろるるる"); x2("(無)\\1", "無無", 0, 2); n("(無)\\1", "無武"); x2("(空?)\\1", "空空", 0, 2); x2("(空??)\\1", "空空", 0, 0); x2("(空*)\\1", "空空空空空", 0, 4); x3("(空*)\\1", "空空空空空", 0, 2, 1); x2("あ(い*)\\1", "あいいいい", 0, 5); x2("あ(い*)\\1", "あい", 0, 1); x2("(あ*)(い*)\\1\\2", "あああいいあああいい", 0, 10); x2("(あ*)(い*)\\2", "あああいいいい", 0, 7); x3("(あ*)(い*)\\2", "あああいいいい", 3, 5, 2); x2("(((((((ぽ*)ぺ))))))ぴ\\7", "ぽぽぽぺぴぽぽぽ", 0, 8); x3("(((((((ぽ*)ぺ))))))ぴ\\7", "ぽぽぽぺぴぽぽぽ", 0, 3, 7); x2("(は)(ひ)(ふ)\\2\\1\\3", "はひふひはふ", 0, 6); x2("([き-け])\\1", "くく", 0, 2); x2("(\\w\\d\\s)\\1", "あ5 あ5 ", 0, 6); n("(\\w\\d\\s)\\1", "あ5 あ5"); x2("(誰?|[あ-う]{3})\\1", "誰?誰?", 0, 4); x2("...(誰?|[あ-う]{3})\\1", "あaあ誰?誰?", 0, 7); x2("(誰?|[あ-う]{3})\\1", "ういうういう", 0, 6); x2("(^こ)\\1", "ここ", 0, 2); n("(^む)\\1", "めむむ"); n("(あ$)\\1", "ああ"); n("(あい\\Z)\\1", "あい"); x2("(あ*\\Z)\\1", "あ", 1, 1); x2(".(あ*\\Z)\\1", "いあ", 1, 2); x3("(.(やいゆ)\\2)", "zやいゆやいゆ", 0, 7, 1); x3("(.(..\\d.)\\2)", "あ12341234", 0, 9, 1); x2("((?i:あvず))\\1", "あvずあvず", 0, 6); x2("(?<愚か>変|\\(\\g<愚か>\\))", "((((((変))))))", 0, 13); x2("\\A(?:\\g<阿_1>|\\g<云_2>|\\z終了 (?<阿_1>観|自\\g<云_2>自)(?<云_2>在|菩薩\\g<阿_1>菩薩))$", "菩薩自菩薩自在自菩薩自菩薩", 0, 13); x2("[[ひふ]]", "ふ", 0, 1); x2("[[いおう]か]", "か", 0, 1); n("[[^あ]]", "あ"); n("[^[あ]]", "あ"); x2("[^[^あ]]", "あ", 0, 1); x2("[[かきく]&&きく]", "く", 0, 1); n("[[かきく]&&きく]", "か"); n("[[かきく]&&きく]", "け"); x2("[あ-ん&&い-を&&う-ゑ]", "ゑ", 0, 1); n("[^あ-ん&&い-を&&う-ゑ]", "ゑ"); x2("[[^あ&&あ]&&あ-ん]", "い", 0, 1); n("[[^あ&&あ]&&あ-ん]", "あ"); x2("[[^あ-ん&&いうえお]&&[^う-か]]", "き", 0, 1); n("[[^あ-ん&&いうえお]&&[^う-か]]", "い"); x2("[^[^あいう]&&[^うえお]]", "う", 0, 1); x2("[^[^あいう]&&[^うえお]]", "え", 0, 1); n("[^[^あいう]&&[^うえお]]", "か"); x2("[あ-&&-あ]", "-", 0, 1); x2("[^[^a-zあいう]&&[^bcdefgうえお]q-w]", "え", 0, 1); x2("[^[^a-zあいう]&&[^bcdefgうえお]g-w]", "f", 0, 1); x2("[^[^a-zあいう]&&[^bcdefgうえお]g-w]", "g", 0, 1); n("[^[^a-zあいう]&&[^bcdefgうえお]g-w]", "2"); x2("aバージョンのダウンロード<\\/b>", "aバージョンのダウンロード", 0, 20); x2(".バージョンのダウンロード<\\/b>", "aバージョンのダウンロード", 0, 20); # additional test patterns if is_unicode_encoding(onig_encoding): x2("\\x{3042}\\x{3044}", "あい", 0, 2) elif onig_encoding == onig.ONIG_ENCODING_SJIS: x2("\\x{82a0}\\x{82A2}", "あい", 0, 2) elif onig_encoding == onig.ONIG_ENCODING_EUC_JP: x2("\\x{a4a2}\\x{A4A4}", "あい", 0, 2) x2("\\p{Hiragana}\\p{Katakana}", "あイ", 0, 2) x2("(?m)^A.B$", "X\nA\nB\nZ", 2, 5) n("(?ab)(?&name_2)", "abab", 0, 4); # x2("(?ab)(?1)", "abab", 0, 4); # x2("(?|\\((?&n)\\))+$", "()(())", 0, 6); # x2("(a|x(?-1)x)", "xax", 0, 3); # x2("(a|(x(?-2)x))", "xax", 0, 3); # x2("a|x(?0)x", "xax", 0, 3); # x2("a|x(?R)x", "xax", 0, 3); x2("(a|x\g<0>x)", "xax", 0, 3); x2("(a|x\g'0'x)", "xax", 0, 3); # x2("(?-i:(?+1))(?i:(a)){0}", "A", 0, 1); x2("(?-i:\g<+1>)(?i:(a)){0}", "A", 0, 1); x2("(?-i:\g'+1')(?i:(a)){0}", "A", 0, 1); # character set modifiers x2("(?u)\\w+", "あa#", 0, 2); x2("(?a)\\w+", "あa#", 1, 2); x2("(?u)\\W+", "あa#", 2, 3); x2("(?a)\\W+", "あa#", 0, 1); x2("(?a)\\b", "あa", 1, 1); x2("(?a)\\w\\b", "aあ", 0, 1); x2("(?a)\\B", "a ああ ", 2, 2); x2("(?u)\\B", "あ ", 2, 2); x2("(?a)\\B", "あ ", 0, 0); x2("(?a)\\B", "aあ ", 2, 2); x2("(?a)\\p{Alpha}\\P{Alpha}", "a。", 0, 2); x2("(?u)\\p{Alpha}\\P{Alpha}", "a。", 0, 2); x2("(?a)[[:word:]]+", "aあ", 0, 1); x2("(?a)[[:^word:]]+", "aあ", 1, 2); x2("(?u)[[:word:]]+", "aあ", 0, 2); n("(?u)[[:^word:]]+", "aあ"); # \g{} backref # x2("((?\\d)|(?\\w))(\\g{name1}|\\g{name2})", "ff", 0, 2); # x2("(?:(?)|(?efg))\\g{x}", "", 0, 0); # x2("(?:(?abc)|(?efg))\\g{x}", "abcefgefg", 3, 9); # n("(?:(?abc)|(?efg))\\g{x}", "abcefg"); # x2("((.*)a\\g{2}f)", "bacbabf", 3, 7); # x2("(.*)a\\g{1}f", "baczzzzzz\nbazz\nzzzzbabf", 19, 23); # x2("((.*)a\\g{-1}f)", "bacbabf", 3, 7); # x2("(.*)a\\g{-1}f", "baczzzzzz\nbazz\nzzzzbabf", 19, 23); # x2("(あ*)(い*)\\g{-2}\\g{-1}", "あああいいあああいい", 0, 10); # Python/PCRE compatible named group # x2("(?Pab)(?P>name_2)", "abab", 0, 4); # x2("(?P|\\((?P>n)\\))+$", "()(())", 0, 6); # x2("((?P\\d)|(?P\\w))((?P=name1)|(?P=name2))", "ff", 0, 2); # Fullwidth Alphabet n("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); x2("(?i)abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", 0, 26); x2("(?i)abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 26); x2("(?i)ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", 0, 26); x2("(?i)ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 26); # Greek n("αβγδεζηθικλμνξοπρστυφχψω", "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"); x2("(?i)αβγδεζηθικλμνξοπρστυφχψω", "αβγδεζηθικλμνξοπρστυφχψω", 0, 24); x2("(?i)αβγδεζηθικλμνξοπρστυφχψω", "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ", 0, 24); x2("(?i)ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ", "αβγδεζηθικλμνξοπρστυφχψω", 0, 24); x2("(?i)ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ", "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ", 0, 24); # Cyrillic n("абвгдеёжзийклмнопрстуфхцчшщъыьэюя", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"); x2("(?i)абвгдеёжзийклмнопрстуфхцчшщъыьэюя", "абвгдеёжзийклмнопрстуфхцчшщъыьэюя", 0, 33); x2("(?i)абвгдеёжзийклмнопрстуфхцчшщъыьэюя", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", 0, 33); x2("(?i)АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", "абвгдеёжзийклмнопрстуфхцчшщъыьэюя", 0, 33); x2("(?i)АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", 0, 33); # multiple name definition x2("(?a)(?b)\\k", "aba", 0, 3) # x2("(?a)(?b)(?&a)", "aba", 0, 3) # x2("(?(a|.)(?b))(?&a)", "abcb", 0, 4) # branch reset # x3("(?|(c)|(?:(b)|(a)))", "a", 0, 1, 2) # x3("(?|(c)|(?|(b)|(a)))", "a", 0, 1, 1) # conditional expression x2("(?:(a)|(b))(?(1)cd)e", "acde", 0, 4) n("(?:(a)|(b))(?(1)cd)e", "ae") x2("(?:(a)|(b))(?(2)cd)e", "ae", 0, 2) n("(?:(a)|(b))(?(2)cd)e", "acde") x2("(?:(a)|(b))(?(1)c|d)", "ac", 0, 2) x2("(?:(a)|(b))(?(1)c|d)", "bd", 0, 2) n("(?:(a)|(b))(?(1)c|d)", "ad") n("(?:(a)|(b))(?(1)c|d)", "bc") x2("(?:(a)|(b))(?:(?(1)cd)e|fg)", "acde", 0, 4) x2("(?:(a)|(b))(?:(?(1)cd|x)e|fg)", "bxe", 0, 3) n("(?:(a)|(b))(?:(?(2)cd|x)e|fg)", "bxe") x2("(?:(?a)|(?b))(?:(?()cd|x)e|fg)", "bxe", 0, 3) n("(?:(?a)|(?b))(?:(?()cd|x)e|fg)", "bxe") x2("((?<=a))?(?(1)b|c)", "abc", 1, 2) x2("((?<=a))?(?(1)b|c)", "bc", 1, 2) x2("((?x)|(?y))(?()y|x)", "xy", 0, 2) x2("((?x)|(?y))(?()y|x)", "yx", 0, 2) n("((?x)|(?y))(?()y|x)", "xx") n("((?x)|(?y))(?()y|x)", "yy") # Implicit-anchor optimization x2("(?m:.*abc)", "dddabdd\nddabc", 0, 13) # optimized /(?m:.*abc)/ ==> /\A(?m:.*abc)/ x2("(?m:.+abc)", "dddabdd\nddabc", 0, 13) # optimized x2("(?-m:.*abc)", "dddabdd\nddabc", 8, 13) # optimized /(?-m:.*abc)/ ==> /(?:^|\A)(?m:.*abc)/ x2("(?-m:.+abc)", "dddabdd\nddabc", 8, 13) # optimized x2("(?-m:.*abc)", "dddabdd\nabc", 8, 11) # optimized n("(?-m:.+abc)", "dddabdd\nabc") # optimized x2("(?m:.*\\Z)", "dddabdd\nddabc", 0, 13) # optimized /(?m:.*\Z)/ ==> /\A(?m:.*\Z)/ x2("(?-m:.*\\Z)", "dddabdd\nddabc", 8, 13) # optimized /(?-m:.*\Z)/ ==> /(?:^|\A)(?m:.*\Z)/ x2("(.*)X\\1", "1234X2345", 1, 8) # not optimized # Allow options in look-behind x2("(?<=(?i)ab)cd", "ABcd", 2, 4) x2("(?<=(?i:ab))cd", "ABcd", 2, 4) n("(?<=(?i)ab)cd", "ABCD") n("(?<=(?i:ab))cd", "ABCD") x2("(? #ifdef POSIX_TEST #include "onigposix.h" #else #include "oniguruma.h" #endif static int nsucc = 0; static int nfail = 0; static int nerror = 0; static FILE* err_file; #ifndef POSIX_TEST static OnigRegion* region; static OnigEncoding ENC; #endif #define ulen(p) onigenc_str_bytelen_null(ENC, (UChar* )p) static void uconv(char* from, char* to, int len) { int i; unsigned char c; char *q; q = to; for (i = 0; i < len; i += 2) { c = (unsigned char )from[i]; if (c == 0) { c = (unsigned char )from[i+1]; if (c < 0x20 || c >= 0x7f || c == 0x5c || c == 0x22) { sprintf(q, "\\%03o", c); q += 4; } else { sprintf(q, "%c", c); q++; } } else { sprintf(q, "\\%03o", c); q += 4; c = (unsigned char )from[i+1]; sprintf(q, "\\%03o", c); q += 4; } } *q = 0; } static void xx(char* pattern, char* str, int from, int to, int mem, int not) { OnigPosition r; char cpat[4000], cstr[4000]; #ifdef POSIX_TEST regex_t reg; char buf[200]; regmatch_t pmatch[20]; uconv(pattern, cpat, ulen(pattern)); uconv(str, cstr, ulen(str)); r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } if (r == REG_NOMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", cpat, cstr); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", cpat, cstr); nfail++; } else { if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { fprintf(stdout, "OK: /%s/ '%s'\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", cpat, cstr, from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); nfail++; } } } regfree(®); #else regex_t* reg; OnigCompileInfo ci; OnigErrorInfo einfo; OnigSyntaxType syn = *ONIG_SYNTAX_DEFAULT; OnigIterator it = {onig_default_charat, str}; /* ONIG_OPTION_OFF(syn.options, ONIG_OPTION_ASCII_RANGE); */ uconv(pattern, cpat, ulen(pattern)); uconv(str, cstr, ulen(str)); #if 0 r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + ulen(pattern)), ONIG_OPTION_DEFAULT, ENC, &syn, &einfo); #else ci.num_of_elements = 5; ci.pattern_enc = ENC; ci.target_enc = ENC; ci.syntax = &syn; ci.option = ONIG_OPTION_DEFAULT; ci.case_fold_flag = ONIGENC_CASE_FOLD_DEFAULT; r = onig_new_deluxe(®, (UChar* )pattern, (UChar* )(pattern + ulen(pattern)), &ci, &einfo); #endif if (r) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r, &einfo); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } r = onig_search(&it, reg, 0, ulen(str), 0, ulen(str), region, ONIG_OPTION_NONE); if (r < ONIG_MISMATCH) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str(s, r); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } if (r == ONIG_MISMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", cpat, cstr); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", cpat, cstr); nfail++; } else { if (region->beg[mem] == from && region->end[mem] == to) { fprintf(stdout, "OK: /%s/ '%s'\n", cpat, cstr); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", cpat, cstr, from, to, region->beg[mem], region->end[mem]); nfail++; } } } onig_free(reg); #endif } static void x2(char* pattern, char* str, int from, int to) { xx(pattern, str, from, to, 0, 0); } static void x3(char* pattern, char* str, int from, int to, int mem) { xx(pattern, str, from, to, mem, 0); } static void n(char* pattern, char* str) { xx(pattern, str, 0, 0, 0, 1); } extern int main(int argc, char* argv[]) { err_file = stdout; #ifndef POSIX_TEST region = onig_region_new(); #endif #ifdef POSIX_TEST reg_set_encoding(REG_POSIX_ENCODING_UTF16_BE); #else ENC = ONIG_ENCODING_UTF16_BE; #endif x2("\000\000", "\000\000", 0, 0); x2("\000^\000\000", "\000\000", 0, 0); x2("\000$\000\000", "\000\000", 0, 0); x2("\000\134\000G\000\000", "\000\000", 0, 0); x2("\000\134\000A\000\000", "\000\000", 0, 0); x2("\000\134\000Z\000\000", "\000\000", 0, 0); x2("\000\134\000z\000\000", "\000\000", 0, 0); x2("\000^\000$\000\000", "\000\000", 0, 0); x2("\000\134\000c\000a\000\000", "\000\001\000\000", 0, 2); x2("\000\134\000C\000-\000b\000\000", "\000\002\000\000", 0, 2); x2("\000\134\000c\000\134\000\134\000\000", "\000\034\000\000", 0, 2); x2("\000q\000[\000\134\000c\000\134\000\134\000]\000\000", "\000q\000\034\000\000", 0, 4); x2("\000\000", "\000a\000\000", 0, 0); x2("\000a\000\000", "\000a\000\000", 0, 2); x2("\000\134\000x\0000\0000\000\134\000x\0006\0001\000\000", "\000a\000\000", 0, 2); x2("\000a\000a\000\000", "\000a\000a\000\000", 0, 4); x2("\000a\000a\000a\000\000", "\000a\000a\000a\000\000", 0, 6); x2("\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000\000", "\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000a\000\000", 0, 70); x2("\000a\000b\000\000", "\000a\000b\000\000", 0, 4); x2("\000b\000\000", "\000a\000b\000\000", 2, 4); x2("\000b\000c\000\000", "\000a\000b\000c\000\000", 2, 6); x2("\000(\000?\000i\000:\000#\000R\000E\000T\000#\000)\000\000", "\000#\000I\000N\000S\000#\000#\000R\000E\000T\000#\000\000", 10, 20); x2("\000\134\0000\0000\0000\000\134\0001\0007\000\000", "\000\017\000\000", 0, 2); x2("\000\134\000x\0000\0000\000\134\000x\0001\000f\000\000", "\000\037\000\000", 0, 2); x2("\000a\000(\000?\000#\000.\000.\000.\000.\000\134\000\134\000J\000J\000J\000J\000)\000b\000\000", "\000a\000b\000\000", 0, 4); x2("\000(\000?\000x\000)\000 \000 \000G\000 \000(\000o\000 \000O\000(\000?\000-\000x\000)\000o\000O\000)\000 \000g\000 \000L\000\000", "\000G\000o\000O\000o\000O\000g\000L\000e\000\000", 0, 14); x2("\000.\000\000", "\000a\000\000", 0, 2); n("\000.\000\000", "\000\000"); x2("\000.\000.\000\000", "\000a\000b\000\000", 0, 4); x2("\000\134\000w\000\000", "\000e\000\000", 0, 2); n("\000\134\000W\000\000", "\000e\000\000"); x2("\000\134\000s\000\000", "\000 \000\000", 0, 2); x2("\000\134\000S\000\000", "\000b\000\000", 0, 2); x2("\000\134\000d\000\000", "\0004\000\000", 0, 2); n("\000\134\000D\000\000", "\0004\000\000"); x2("\000\134\000b\000\000", "\000z\000 \000\000", 0, 0); x2("\000\134\000b\000\000", "\000 \000z\000\000", 2, 2); x2("\000\134\000B\000\000", "\000z\000z\000 \000\000", 2, 2); x2("\000\134\000B\000\000", "\000z\000 \000\000", 4, 4); x2("\000\134\000B\000\000", "\000 \000z\000\000", 0, 0); x2("\000[\000a\000b\000]\000\000", "\000b\000\000", 0, 2); n("\000[\000a\000b\000]\000\000", "\000c\000\000"); x2("\000[\000a\000-\000z\000]\000\000", "\000t\000\000", 0, 2); n("\000[\000^\000a\000]\000\000", "\000a\000\000"); x2("\000[\000^\000a\000]\000\000", "\000\012\000\000", 0, 2); x2("\000[\000]\000]\000\000", "\000]\000\000", 0, 2); n("\000[\000^\000]\000]\000\000", "\000]\000\000"); x2("\000[\000\134\000^\000]\000+\000\000", "\0000\000^\000^\0001\000\000", 2, 6); x2("\000[\000b\000-\000]\000\000", "\000b\000\000", 0, 2); x2("\000[\000b\000-\000]\000\000", "\000-\000\000", 0, 2); x2("\000[\000\134\000w\000]\000\000", "\000z\000\000", 0, 2); n("\000[\000\134\000w\000]\000\000", "\000 \000\000"); x2("\000[\000\134\000W\000]\000\000", "\000b\000$\000\000", 2, 4); x2("\000[\000\134\000d\000]\000\000", "\0005\000\000", 0, 2); n("\000[\000\134\000d\000]\000\000", "\000e\000\000"); x2("\000[\000\134\000D\000]\000\000", "\000t\000\000", 0, 2); n("\000[\000\134\000D\000]\000\000", "\0003\000\000"); x2("\000[\000\134\000s\000]\000\000", "\000 \000\000", 0, 2); n("\000[\000\134\000s\000]\000\000", "\000a\000\000"); x2("\000[\000\134\000S\000]\000\000", "\000b\000\000", 0, 2); n("\000[\000\134\000S\000]\000\000", "\000 \000\000"); x2("\000[\000\134\000w\000\134\000d\000]\000\000", "\0002\000\000", 0, 2); n("\000[\000\134\000w\000\134\000d\000]\000\000", "\000 \000\000"); x2("\000[\000[\000:\000u\000p\000p\000e\000r\000:\000]\000]\000\000", "\000B\000\000", 0, 2); x2("\000[\000*\000[\000:\000x\000d\000i\000g\000i\000t\000:\000]\000+\000]\000\000", "\000+\000\000", 0, 2); x2("\000[\000*\000[\000:\000x\000d\000i\000g\000i\000t\000:\000]\000+\000]\000\000", "\000G\000H\000I\000K\000K\000-\0009\000+\000*\000\000", 12, 14); x2("\000[\000*\000[\000:\000x\000d\000i\000g\000i\000t\000:\000]\000+\000]\000\000", "\000-\000@\000^\000+\000\000", 6, 8); n("\000[\000[\000:\000u\000p\000p\000e\000r\000]\000]\000\000", "\000A\000\000"); x2("\000[\000[\000:\000u\000p\000p\000e\000r\000]\000]\000\000", "\000:\000\000", 0, 2); x2("\000[\000\134\0000\0000\0000\000\134\0000\0004\0004\000-\000\134\0000\0000\0000\000\134\0000\0004\0007\000]\000\000", "\000&\000\000", 0, 2); x2("\000[\000\134\000x\0000\0000\000\134\000x\0005\000a\000-\000\134\000x\0000\0000\000\134\000x\0005\000c\000]\000\000", "\000[\000\000", 0, 2); x2("\000[\000\134\000x\0000\0000\000\134\000x\0006\000A\000-\000\134\000x\0000\0000\000\134\000x\0006\000D\000]\000\000", "\000l\000\000", 0, 2); n("\000[\000\134\000x\0000\0000\000\134\000x\0006\000A\000-\000\134\000x\0000\0000\000\134\000x\0006\000D\000]\000\000", "\000n\000\000"); n("\000^\000[\0000\000-\0009\000A\000-\000F\000]\000+\000 \0000\000+\000 \000U\000N\000D\000E\000F\000 \000\000", "\0007\0005\000F\000 \0000\0000\0000\0000\0000\0000\0000\0000\000 \000S\000E\000C\000T\0001\0004\000A\000 \000n\000o\000t\000y\000p\000e\000 \000(\000)\000 \000 \000 \000 \000E\000x\000t\000e\000r\000n\000a\000l\000 \000 \000 \000 \000|\000 \000_\000r\000b\000_\000a\000p\000p\000l\000y\000\000"); x2("\000[\000\134\000[\000]\000\000", "\000[\000\000", 0, 2); x2("\000[\000\134\000]\000]\000\000", "\000]\000\000", 0, 2); x2("\000[\000&\000]\000\000", "\000&\000\000", 0, 2); x2("\000[\000[\000a\000b\000]\000]\000\000", "\000b\000\000", 0, 2); x2("\000[\000[\000a\000b\000]\000c\000]\000\000", "\000c\000\000", 0, 2); n("\000[\000[\000^\000a\000]\000]\000\000", "\000a\000\000"); n("\000[\000^\000[\000a\000]\000]\000\000", "\000a\000\000"); x2("\000[\000[\000a\000b\000]\000&\000&\000b\000c\000]\000\000", "\000b\000\000", 0, 2); n("\000[\000[\000a\000b\000]\000&\000&\000b\000c\000]\000\000", "\000a\000\000"); n("\000[\000[\000a\000b\000]\000&\000&\000b\000c\000]\000\000", "\000c\000\000"); x2("\000[\000a\000-\000z\000&\000&\000b\000-\000y\000&\000&\000c\000-\000x\000]\000\000", "\000w\000\000", 0, 2); n("\000[\000^\000a\000-\000z\000&\000&\000b\000-\000y\000&\000&\000c\000-\000x\000]\000\000", "\000w\000\000"); x2("\000[\000[\000^\000a\000&\000&\000a\000]\000&\000&\000a\000-\000z\000]\000\000", "\000b\000\000", 0, 2); n("\000[\000[\000^\000a\000&\000&\000a\000]\000&\000&\000a\000-\000z\000]\000\000", "\000a\000\000"); x2("\000[\000[\000^\000a\000-\000z\000&\000&\000b\000c\000d\000e\000f\000]\000&\000&\000[\000^\000c\000-\000g\000]\000]\000\000", "\000h\000\000", 0, 2); n("\000[\000[\000^\000a\000-\000z\000&\000&\000b\000c\000d\000e\000f\000]\000&\000&\000[\000^\000c\000-\000g\000]\000]\000\000", "\000c\000\000"); x2("\000[\000^\000[\000^\000a\000b\000c\000]\000&\000&\000[\000^\000c\000d\000e\000]\000]\000\000", "\000c\000\000", 0, 2); x2("\000[\000^\000[\000^\000a\000b\000c\000]\000&\000&\000[\000^\000c\000d\000e\000]\000]\000\000", "\000e\000\000", 0, 2); n("\000[\000^\000[\000^\000a\000b\000c\000]\000&\000&\000[\000^\000c\000d\000e\000]\000]\000\000", "\000f\000\000"); x2("\000[\000a\000-\000&\000&\000-\000a\000]\000\000", "\000-\000\000", 0, 2); n("\000[\000a\000\134\000-\000&\000&\000\134\000-\000a\000]\000\000", "\000&\000\000"); n("\000\134\000w\000a\000b\000c\000\000", "\000 \000a\000b\000c\000\000"); x2("\000a\000\134\000W\000b\000c\000\000", "\000a\000 \000b\000c\000\000", 0, 8); x2("\000a\000.\000b\000.\000c\000\000", "\000a\000a\000b\000b\000c\000\000", 0, 10); x2("\000.\000\134\000w\000b\000\134\000W\000.\000.\000c\000\000", "\000a\000b\000b\000 \000b\000c\000c\000\000", 0, 14); x2("\000\134\000s\000\134\000w\000z\000z\000z\000\000", "\000 \000z\000z\000z\000z\000\000", 0, 10); x2("\000a\000a\000.\000b\000\000", "\000a\000a\000b\000b\000\000", 0, 8); n("\000.\000a\000\000", "\000a\000b\000\000"); x2("\000.\000a\000\000", "\000a\000a\000\000", 0, 4); x2("\000^\000a\000\000", "\000a\000\000", 0, 2); x2("\000^\000a\000$\000\000", "\000a\000\000", 0, 2); x2("\000^\000\134\000w\000$\000\000", "\000a\000\000", 0, 2); n("\000^\000\134\000w\000$\000\000", "\000 \000\000"); x2("\000^\000\134\000w\000a\000b\000$\000\000", "\000z\000a\000b\000\000", 0, 6); x2("\000^\000\134\000w\000a\000b\000c\000d\000e\000f\000$\000\000", "\000z\000a\000b\000c\000d\000e\000f\000\000", 0, 14); x2("\000^\000\134\000w\000.\000.\000.\000d\000e\000f\000$\000\000", "\000z\000a\000b\000c\000d\000e\000f\000\000", 0, 14); x2("\000\134\000w\000\134\000w\000\134\000s\000\134\000W\000a\000a\000a\000\134\000d\000\000", "\000a\000a\000 \000 \000a\000a\000a\0004\000\000", 0, 16); x2("\000\134\000A\000\134\000Z\000\000", "\000\000", 0, 0); x2("\000\134\000A\000x\000y\000z\000\000", "\000x\000y\000z\000\000", 0, 6); x2("\000x\000y\000z\000\134\000Z\000\000", "\000x\000y\000z\000\000", 0, 6); x2("\000x\000y\000z\000\134\000z\000\000", "\000x\000y\000z\000\000", 0, 6); x2("\000a\000\134\000Z\000\000", "\000a\000\000", 0, 2); x2("\000\134\000G\000a\000z\000\000", "\000a\000z\000\000", 0, 4); n("\000\134\000G\000z\000\000", "\000b\000z\000a\000\000"); n("\000a\000z\000\134\000G\000\000", "\000a\000z\000\000"); n("\000a\000z\000\134\000A\000\000", "\000a\000z\000\000"); n("\000a\000\134\000A\000z\000\000", "\000a\000z\000\000"); x2("\000\134\000^\000\134\000$\000\000", "\000^\000$\000\000", 0, 4); x2("\000^\000x\000?\000y\000\000", "\000x\000y\000\000", 0, 4); x2("\000^\000(\000x\000?\000y\000)\000\000", "\000x\000y\000\000", 0, 4); x2("\000\134\000w\000\000", "\000_\000\000", 0, 2); n("\000\134\000W\000\000", "\000_\000\000"); x2("\000(\000?\000=\000z\000)\000z\000\000", "\000z\000\000", 0, 2); n("\000(\000?\000=\000z\000)\000.\000\000", "\000a\000\000"); x2("\000(\000?\000!\000z\000)\000a\000\000", "\000a\000\000", 0, 2); n("\000(\000?\000!\000z\000)\000a\000\000", "\000z\000\000"); x2("\000(\000?\000i\000:\000a\000)\000\000", "\000a\000\000", 0, 2); x2("\000(\000?\000i\000:\000a\000)\000\000", "\000A\000\000", 0, 2); x2("\000(\000?\000i\000:\000A\000)\000\000", "\000a\000\000", 0, 2); n("\000(\000?\000i\000:\000A\000)\000\000", "\000b\000\000"); x2("\000(\000?\000i\000:\000[\000A\000-\000Z\000]\000)\000\000", "\000a\000\000", 0, 2); x2("\000(\000?\000i\000:\000[\000f\000-\000m\000]\000)\000\000", "\000H\000\000", 0, 2); x2("\000(\000?\000i\000:\000[\000f\000-\000m\000]\000)\000\000", "\000h\000\000", 0, 2); n("\000(\000?\000i\000:\000[\000f\000-\000m\000]\000)\000\000", "\000e\000\000"); x2("\000(\000?\000i\000:\000[\000A\000-\000c\000]\000)\000\000", "\000D\000\000", 0, 2); n("\000(\000?\000i\000:\000[\000^\000a\000-\000z\000]\000)\000\000", "\000A\000\000"); n("\000(\000?\000i\000:\000[\000^\000a\000-\000z\000]\000)\000\000", "\000a\000\000"); x2("\000(\000?\000i\000:\000[\000!\000-\000k\000]\000)\000\000", "\000Z\000\000", 0, 2); x2("\000(\000?\000i\000:\000[\000!\000-\000k\000]\000)\000\000", "\0007\000\000", 0, 2); x2("\000(\000?\000i\000:\000[\000T\000-\000}\000]\000)\000\000", "\000b\000\000", 0, 2); x2("\000(\000?\000i\000:\000[\000T\000-\000}\000]\000)\000\000", "\000{\000\000", 0, 2); x2("\000(\000?\000i\000:\000\134\000?\000a\000)\000\000", "\000?\000A\000\000", 0, 4); x2("\000(\000?\000i\000:\000\134\000*\000A\000)\000\000", "\000*\000a\000\000", 0, 4); n("\000.\000\000", "\000\012\000\000"); x2("\000(\000?\000m\000:\000.\000)\000\000", "\000\012\000\000", 0, 2); x2("\000(\000?\000m\000:\000a\000.\000)\000\000", "\000a\000\012\000\000", 0, 4); x2("\000(\000?\000m\000:\000.\000b\000)\000\000", "\000a\000\012\000b\000\000", 2, 6); x2("\000.\000*\000a\000b\000c\000\000", "\000d\000d\000d\000a\000b\000d\000d\000\012\000d\000d\000a\000b\000c\000\000", 16, 26); x2("\000(\000?\000m\000:\000.\000*\000a\000b\000c\000)\000\000", "\000d\000d\000d\000a\000b\000d\000d\000a\000b\000c\000\000", 0, 20); n("\000(\000?\000i\000)\000(\000?\000-\000i\000)\000a\000\000", "\000A\000\000"); n("\000(\000?\000i\000)\000(\000?\000-\000i\000:\000a\000)\000\000", "\000A\000\000"); x2("\000a\000?\000\000", "\000\000", 0, 0); x2("\000a\000?\000\000", "\000b\000\000", 0, 0); x2("\000a\000?\000\000", "\000a\000\000", 0, 2); x2("\000a\000*\000\000", "\000\000", 0, 0); x2("\000a\000*\000\000", "\000a\000\000", 0, 2); x2("\000a\000*\000\000", "\000a\000a\000a\000\000", 0, 6); x2("\000a\000*\000\000", "\000b\000a\000a\000a\000a\000\000", 0, 0); n("\000a\000+\000\000", "\000\000"); x2("\000a\000+\000\000", "\000a\000\000", 0, 2); x2("\000a\000+\000\000", "\000a\000a\000a\000a\000\000", 0, 8); x2("\000a\000+\000\000", "\000a\000a\000b\000b\000b\000\000", 0, 4); x2("\000a\000+\000\000", "\000b\000a\000a\000a\000a\000\000", 2, 10); x2("\000.\000?\000\000", "\000\000", 0, 0); x2("\000.\000?\000\000", "\000f\000\000", 0, 2); x2("\000.\000?\000\000", "\000\012\000\000", 0, 0); x2("\000.\000*\000\000", "\000\000", 0, 0); x2("\000.\000*\000\000", "\000a\000b\000c\000d\000e\000\000", 0, 10); x2("\000.\000+\000\000", "\000z\000\000", 0, 2); x2("\000.\000+\000\000", "\000z\000d\000s\000w\000e\000r\000\012\000\000", 0, 12); x2("\000(\000.\000*\000)\000a\000\134\0001\000f\000\000", "\000b\000a\000b\000f\000b\000a\000c\000\000", 0, 8); x2("\000(\000.\000*\000)\000a\000\134\0001\000f\000\000", "\000b\000a\000c\000b\000a\000b\000f\000\000", 6, 14); x2("\000(\000(\000.\000*\000)\000a\000\134\0002\000f\000)\000\000", "\000b\000a\000c\000b\000a\000b\000f\000\000", 6, 14); x2("\000(\000.\000*\000)\000a\000\134\0001\000f\000\000", "\000b\000a\000c\000z\000z\000z\000z\000z\000z\000\012\000b\000a\000z\000z\000\012\000z\000z\000z\000z\000b\000a\000b\000f\000\000", 38, 46); x2("\000a\000|\000b\000\000", "\000a\000\000", 0, 2); x2("\000a\000|\000b\000\000", "\000b\000\000", 0, 2); x2("\000|\000a\000\000", "\000a\000\000", 0, 0); x2("\000(\000|\000a\000)\000\000", "\000a\000\000", 0, 0); x2("\000a\000b\000|\000b\000c\000\000", "\000a\000b\000\000", 0, 4); x2("\000a\000b\000|\000b\000c\000\000", "\000b\000c\000\000", 0, 4); x2("\000z\000(\000?\000:\000a\000b\000|\000b\000c\000)\000\000", "\000z\000b\000c\000\000", 0, 6); x2("\000a\000(\000?\000:\000a\000b\000|\000b\000c\000)\000c\000\000", "\000a\000a\000b\000c\000\000", 0, 8); x2("\000a\000b\000|\000(\000?\000:\000a\000c\000|\000a\000z\000)\000\000", "\000a\000z\000\000", 0, 4); x2("\000a\000|\000b\000|\000c\000\000", "\000d\000c\000\000", 2, 4); x2("\000a\000|\000b\000|\000c\000d\000|\000e\000f\000g\000|\000h\000|\000i\000j\000k\000|\000l\000m\000n\000|\000o\000|\000p\000q\000|\000r\000s\000t\000u\000v\000w\000x\000|\000y\000z\000\000", "\000p\000q\000r\000\000", 0, 4); n("\000a\000|\000b\000|\000c\000d\000|\000e\000f\000g\000|\000h\000|\000i\000j\000k\000|\000l\000m\000n\000|\000o\000|\000p\000q\000|\000r\000s\000t\000u\000v\000w\000x\000|\000y\000z\000\000", "\000m\000n\000\000"); x2("\000a\000|\000^\000z\000\000", "\000b\000a\000\000", 2, 4); x2("\000a\000|\000^\000z\000\000", "\000z\000a\000\000", 0, 2); x2("\000a\000|\000\134\000G\000z\000\000", "\000b\000z\000a\000\000", 4, 6); x2("\000a\000|\000\134\000G\000z\000\000", "\000z\000a\000\000", 0, 2); x2("\000a\000|\000\134\000A\000z\000\000", "\000b\000z\000a\000\000", 4, 6); x2("\000a\000|\000\134\000A\000z\000\000", "\000z\000a\000\000", 0, 2); x2("\000a\000|\000b\000\134\000Z\000\000", "\000b\000a\000\000", 2, 4); x2("\000a\000|\000b\000\134\000Z\000\000", "\000b\000\000", 0, 2); x2("\000a\000|\000b\000\134\000z\000\000", "\000b\000a\000\000", 2, 4); x2("\000a\000|\000b\000\134\000z\000\000", "\000b\000\000", 0, 2); x2("\000\134\000w\000|\000\134\000s\000\000", "\000 \000\000", 0, 2); n("\000\134\000w\000|\000\134\000w\000\000", "\000 \000\000"); x2("\000\134\000w\000|\000%\000\000", "\000%\000\000", 0, 2); x2("\000\134\000w\000|\000[\000&\000$\000]\000\000", "\000&\000\000", 0, 2); x2("\000[\000b\000-\000d\000]\000|\000[\000^\000e\000-\000z\000]\000\000", "\000a\000\000", 0, 2); x2("\000(\000?\000:\000a\000|\000[\000c\000-\000f\000]\000)\000|\000b\000z\000\000", "\000d\000z\000\000", 0, 2); x2("\000(\000?\000:\000a\000|\000[\000c\000-\000f\000]\000)\000|\000b\000z\000\000", "\000b\000z\000\000", 0, 4); x2("\000a\000b\000c\000|\000(\000?\000=\000z\000z\000)\000.\000.\000f\000\000", "\000z\000z\000f\000\000", 0, 6); x2("\000a\000b\000c\000|\000(\000?\000!\000z\000z\000)\000.\000.\000f\000\000", "\000a\000b\000f\000\000", 0, 6); x2("\000(\000?\000=\000z\000a\000)\000.\000.\000a\000|\000(\000?\000=\000z\000z\000)\000.\000.\000a\000\000", "\000z\000z\000a\000\000", 0, 6); n("\000(\000?\000>\000a\000|\000a\000b\000d\000)\000c\000\000", "\000a\000b\000d\000c\000\000"); x2("\000(\000?\000>\000a\000b\000d\000|\000a\000)\000c\000\000", "\000a\000b\000d\000c\000\000", 0, 8); x2("\000a\000?\000|\000b\000\000", "\000a\000\000", 0, 2); x2("\000a\000?\000|\000b\000\000", "\000b\000\000", 0, 0); x2("\000a\000?\000|\000b\000\000", "\000\000", 0, 0); x2("\000a\000*\000|\000b\000\000", "\000a\000a\000\000", 0, 4); x2("\000a\000*\000|\000b\000*\000\000", "\000b\000a\000\000", 0, 0); x2("\000a\000*\000|\000b\000*\000\000", "\000a\000b\000\000", 0, 2); x2("\000a\000+\000|\000b\000*\000\000", "\000\000", 0, 0); x2("\000a\000+\000|\000b\000*\000\000", "\000b\000b\000b\000\000", 0, 6); x2("\000a\000+\000|\000b\000*\000\000", "\000a\000b\000b\000b\000\000", 0, 2); n("\000a\000+\000|\000b\000+\000\000", "\000\000"); x2("\000(\000a\000|\000b\000)\000?\000\000", "\000b\000\000", 0, 2); x2("\000(\000a\000|\000b\000)\000*\000\000", "\000b\000a\000\000", 0, 4); x2("\000(\000a\000|\000b\000)\000+\000\000", "\000b\000a\000b\000\000", 0, 6); x2("\000(\000a\000b\000|\000c\000a\000)\000+\000\000", "\000c\000a\000a\000b\000b\000c\000\000", 0, 8); x2("\000(\000a\000b\000|\000c\000a\000)\000+\000\000", "\000a\000a\000b\000c\000a\000\000", 2, 10); x2("\000(\000a\000b\000|\000c\000a\000)\000+\000\000", "\000a\000b\000z\000c\000a\000\000", 0, 4); x2("\000(\000a\000|\000b\000a\000b\000)\000+\000\000", "\000a\000b\000a\000b\000a\000\000", 0, 10); x2("\000(\000a\000|\000b\000a\000b\000)\000+\000\000", "\000b\000a\000\000", 2, 4); x2("\000(\000a\000|\000b\000a\000b\000)\000+\000\000", "\000b\000a\000a\000a\000b\000a\000\000", 2, 8); x2("\000(\000?\000:\000a\000|\000b\000)\000(\000?\000:\000a\000|\000b\000)\000\000", "\000a\000b\000\000", 0, 4); x2("\000(\000?\000:\000a\000*\000|\000b\000*\000)\000(\000?\000:\000a\000*\000|\000b\000*\000)\000\000", "\000a\000a\000a\000b\000b\000b\000\000", 0, 6); x2("\000(\000?\000:\000a\000*\000|\000b\000*\000)\000(\000?\000:\000a\000+\000|\000b\000+\000)\000\000", "\000a\000a\000a\000b\000b\000b\000\000", 0, 12); x2("\000(\000?\000:\000a\000+\000|\000b\000+\000)\000{\0002\000}\000\000", "\000a\000a\000a\000b\000b\000b\000\000", 0, 12); x2("\000h\000{\0000\000,\000}\000\000", "\000h\000h\000h\000h\000\000", 0, 8); x2("\000(\000?\000:\000a\000+\000|\000b\000+\000)\000{\0001\000,\0002\000}\000\000", "\000a\000a\000a\000b\000b\000b\000\000", 0, 12); n("\000a\000x\000{\0002\000}\000*\000a\000\000", "\0000\000a\000x\000x\000x\000a\0001\000\000"); n("\000a\000.\000{\0000\000,\0002\000}\000a\000\000", "\0000\000a\000X\000X\000X\000a\0000\000\000"); n("\000a\000.\000{\0000\000,\0002\000}\000?\000a\000\000", "\0000\000a\000X\000X\000X\000a\0000\000\000"); n("\000a\000.\000{\0000\000,\0002\000}\000?\000a\000\000", "\0000\000a\000X\000X\000X\000X\000a\0000\000\000"); x2("\000^\000a\000{\0002\000,\000}\000?\000a\000$\000\000", "\000a\000a\000a\000\000", 0, 6); x2("\000^\000[\000a\000-\000z\000]\000{\0002\000,\000}\000?\000$\000\000", "\000a\000a\000a\000\000", 0, 6); x2("\000(\000?\000:\000a\000+\000|\000\134\000A\000b\000*\000)\000c\000c\000\000", "\000c\000c\000\000", 0, 4); n("\000(\000?\000:\000a\000+\000|\000\134\000A\000b\000*\000)\000c\000c\000\000", "\000a\000b\000c\000c\000\000"); x2("\000(\000?\000:\000^\000a\000+\000|\000b\000+\000)\000*\000c\000\000", "\000a\000a\000b\000b\000b\000a\000b\000c\000\000", 12, 16); x2("\000(\000?\000:\000^\000a\000+\000|\000b\000+\000)\000*\000c\000\000", "\000a\000a\000b\000b\000b\000b\000c\000\000", 0, 14); x2("\000a\000|\000(\000?\000i\000)\000c\000\000", "\000C\000\000", 0, 2); x2("\000(\000?\000i\000)\000c\000|\000a\000\000", "\000C\000\000", 0, 2); x2("\000(\000?\000i\000)\000c\000|\000a\000\000", "\000A\000\000", 0, 2); x2("\000(\000?\000i\000:\000c\000)\000|\000a\000\000", "\000C\000\000", 0, 2); n("\000(\000?\000i\000:\000c\000)\000|\000a\000\000", "\000A\000\000"); x2("\000[\000a\000b\000c\000]\000?\000\000", "\000a\000b\000c\000\000", 0, 2); x2("\000[\000a\000b\000c\000]\000*\000\000", "\000a\000b\000c\000\000", 0, 6); x2("\000[\000^\000a\000b\000c\000]\000*\000\000", "\000a\000b\000c\000\000", 0, 0); n("\000[\000^\000a\000b\000c\000]\000+\000\000", "\000a\000b\000c\000\000"); x2("\000a\000?\000?\000\000", "\000a\000a\000a\000\000", 0, 0); x2("\000b\000a\000?\000?\000b\000\000", "\000b\000a\000b\000\000", 0, 6); x2("\000a\000*\000?\000\000", "\000a\000a\000a\000\000", 0, 0); x2("\000b\000a\000*\000?\000\000", "\000b\000a\000a\000\000", 0, 2); x2("\000b\000a\000*\000?\000b\000\000", "\000b\000a\000a\000b\000\000", 0, 8); x2("\000a\000+\000?\000\000", "\000a\000a\000a\000\000", 0, 2); x2("\000b\000a\000+\000?\000\000", "\000b\000a\000a\000\000", 0, 4); x2("\000b\000a\000+\000?\000b\000\000", "\000b\000a\000a\000b\000\000", 0, 8); x2("\000(\000?\000:\000a\000?\000)\000?\000?\000\000", "\000a\000\000", 0, 0); x2("\000(\000?\000:\000a\000?\000?\000)\000?\000\000", "\000a\000\000", 0, 0); x2("\000(\000?\000:\000a\000?\000)\000+\000?\000\000", "\000a\000a\000a\000\000", 0, 2); x2("\000(\000?\000:\000a\000+\000)\000?\000?\000\000", "\000a\000a\000a\000\000", 0, 0); x2("\000(\000?\000:\000a\000+\000)\000?\000?\000b\000\000", "\000a\000a\000a\000b\000\000", 0, 8); x2("\000(\000?\000:\000a\000b\000)\000?\000{\0002\000}\000\000", "\000\000", 0, 0); x2("\000(\000?\000:\000a\000b\000)\000?\000{\0002\000}\000\000", "\000a\000b\000a\000b\000a\000\000", 0, 8); x2("\000(\000?\000:\000a\000b\000)\000*\000{\0000\000}\000\000", "\000a\000b\000a\000b\000a\000\000", 0, 0); x2("\000(\000?\000:\000a\000b\000)\000{\0003\000,\000}\000\000", "\000a\000b\000a\000b\000a\000b\000a\000b\000\000", 0, 16); n("\000(\000?\000:\000a\000b\000)\000{\0003\000,\000}\000\000", "\000a\000b\000a\000b\000\000"); x2("\000(\000?\000:\000a\000b\000)\000{\0002\000,\0004\000}\000\000", "\000a\000b\000a\000b\000a\000b\000\000", 0, 12); x2("\000(\000?\000:\000a\000b\000)\000{\0002\000,\0004\000}\000\000", "\000a\000b\000a\000b\000a\000b\000a\000b\000a\000b\000\000", 0, 16); x2("\000(\000?\000:\000a\000b\000)\000{\0002\000,\0004\000}\000?\000\000", "\000a\000b\000a\000b\000a\000b\000a\000b\000a\000b\000\000", 0, 8); x2("\000(\000?\000:\000a\000b\000)\000{\000,\000}\000\000", "\000a\000b\000{\000,\000}\000\000", 0, 10); x2("\000(\000?\000:\000a\000b\000c\000)\000+\000?\000{\0002\000}\000\000", "\000a\000b\000c\000a\000b\000c\000a\000b\000c\000\000", 0, 12); x2("\000(\000?\000:\000X\000*\000)\000(\000?\000i\000:\000x\000a\000)\000\000", "\000X\000X\000X\000a\000\000", 0, 8); x2("\000(\000d\000+\000)\000(\000[\000^\000a\000b\000c\000]\000z\000)\000\000", "\000d\000d\000d\000z\000\000", 0, 8); x2("\000(\000[\000^\000a\000b\000c\000]\000*\000)\000(\000[\000^\000a\000b\000c\000]\000z\000)\000\000", "\000d\000d\000d\000z\000\000", 0, 8); x2("\000(\000\134\000w\000+\000)\000(\000\134\000w\000z\000)\000\000", "\000d\000d\000d\000z\000\000", 0, 8); x3("\000(\000a\000)\000\000", "\000a\000\000", 0, 2, 1); x3("\000(\000a\000b\000)\000\000", "\000a\000b\000\000", 0, 4, 1); x2("\000(\000(\000a\000b\000)\000)\000\000", "\000a\000b\000\000", 0, 4); x3("\000(\000(\000a\000b\000)\000)\000\000", "\000a\000b\000\000", 0, 4, 1); x3("\000(\000(\000a\000b\000)\000)\000\000", "\000a\000b\000\000", 0, 4, 2); x3("\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000a\000b\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000\000", "\000a\000b\000\000", 0, 4, 20); x3("\000(\000a\000b\000)\000(\000c\000d\000)\000\000", "\000a\000b\000c\000d\000\000", 0, 4, 1); x3("\000(\000a\000b\000)\000(\000c\000d\000)\000\000", "\000a\000b\000c\000d\000\000", 4, 8, 2); x3("\000(\000)\000(\000a\000)\000b\000c\000(\000d\000e\000f\000)\000g\000h\000i\000j\000k\000\000", "\000a\000b\000c\000d\000e\000f\000g\000h\000i\000j\000k\000\000", 6, 12, 3); x3("\000(\000(\000)\000(\000a\000)\000b\000c\000(\000d\000e\000f\000)\000g\000h\000i\000j\000k\000)\000\000", "\000a\000b\000c\000d\000e\000f\000g\000h\000i\000j\000k\000\000", 6, 12, 4); x2("\000(\000^\000a\000)\000\000", "\000a\000\000", 0, 2); x3("\000(\000a\000)\000|\000(\000a\000)\000\000", "\000b\000a\000\000", 2, 4, 1); x3("\000(\000^\000a\000)\000|\000(\000a\000)\000\000", "\000b\000a\000\000", 2, 4, 2); x3("\000(\000a\000?\000)\000\000", "\000a\000a\000a\000\000", 0, 2, 1); x3("\000(\000a\000*\000)\000\000", "\000a\000a\000a\000\000", 0, 6, 1); x3("\000(\000a\000*\000)\000\000", "\000\000", 0, 0, 1); x3("\000(\000a\000+\000)\000\000", "\000a\000a\000a\000a\000a\000a\000a\000\000", 0, 14, 1); x3("\000(\000a\000+\000|\000b\000*\000)\000\000", "\000b\000b\000b\000a\000a\000\000", 0, 6, 1); x3("\000(\000a\000+\000|\000b\000?\000)\000\000", "\000b\000b\000b\000a\000a\000\000", 0, 2, 1); x3("\000(\000a\000b\000c\000)\000?\000\000", "\000a\000b\000c\000\000", 0, 6, 1); x3("\000(\000a\000b\000c\000)\000*\000\000", "\000a\000b\000c\000\000", 0, 6, 1); x3("\000(\000a\000b\000c\000)\000+\000\000", "\000a\000b\000c\000\000", 0, 6, 1); x3("\000(\000x\000y\000z\000|\000a\000b\000c\000)\000+\000\000", "\000a\000b\000c\000\000", 0, 6, 1); x3("\000(\000[\000x\000y\000z\000]\000[\000a\000b\000c\000]\000|\000a\000b\000c\000)\000+\000\000", "\000a\000b\000c\000\000", 0, 6, 1); x3("\000(\000(\000?\000i\000:\000a\000b\000c\000)\000)\000\000", "\000A\000b\000C\000\000", 0, 6, 1); x2("\000(\000a\000b\000c\000)\000(\000?\000i\000:\000\134\0001\000)\000\000", "\000a\000b\000c\000A\000B\000C\000\000", 0, 12); x3("\000(\000(\000?\000m\000:\000a\000.\000c\000)\000)\000\000", "\000a\000\012\000c\000\000", 0, 6, 1); x3("\000(\000(\000?\000=\000a\000z\000)\000a\000)\000\000", "\000a\000z\000b\000\000", 0, 2, 1); x3("\000a\000b\000c\000|\000(\000.\000a\000b\000d\000)\000\000", "\000z\000a\000b\000d\000\000", 0, 8, 1); x2("\000(\000?\000:\000a\000b\000c\000)\000|\000(\000A\000B\000C\000)\000\000", "\000a\000b\000c\000\000", 0, 6); x3("\000(\000?\000i\000:\000(\000a\000b\000c\000)\000)\000|\000(\000z\000z\000z\000)\000\000", "\000A\000B\000C\000\000", 0, 6, 1); x3("\000a\000*\000(\000.\000)\000\000", "\000a\000a\000a\000a\000z\000\000", 8, 10, 1); x3("\000a\000*\000?\000(\000.\000)\000\000", "\000a\000a\000a\000a\000z\000\000", 0, 2, 1); x3("\000a\000*\000?\000(\000c\000)\000\000", "\000a\000a\000a\000a\000c\000\000", 8, 10, 1); x3("\000[\000b\000c\000d\000]\000a\000*\000(\000.\000)\000\000", "\000c\000a\000a\000a\000a\000z\000\000", 10, 12, 1); x3("\000(\000\134\000A\000b\000b\000)\000c\000c\000\000", "\000b\000b\000c\000c\000\000", 0, 4, 1); n("\000(\000\134\000A\000b\000b\000)\000c\000c\000\000", "\000z\000b\000b\000c\000c\000\000"); x3("\000(\000^\000b\000b\000)\000c\000c\000\000", "\000b\000b\000c\000c\000\000", 0, 4, 1); n("\000(\000^\000b\000b\000)\000c\000c\000\000", "\000z\000b\000b\000c\000c\000\000"); x3("\000c\000c\000(\000b\000b\000$\000)\000\000", "\000c\000c\000b\000b\000\000", 4, 8, 1); n("\000c\000c\000(\000b\000b\000$\000)\000\000", "\000c\000c\000b\000b\000b\000\000"); n("\000(\000\134\0001\000)\000\000", "\000\000"); n("\000\134\0001\000(\000a\000)\000\000", "\000a\000a\000\000"); n("\000(\000a\000(\000b\000)\000\134\0001\000)\000\134\0002\000+\000\000", "\000a\000b\000a\000b\000b\000\000"); n("\000(\000?\000:\000(\000?\000:\000\134\0001\000|\000z\000)\000(\000a\000)\000)\000+\000$\000\000", "\000z\000a\000a\000\000"); x2("\000(\000?\000:\000(\000?\000:\000\134\0001\000|\000z\000)\000(\000a\000)\000)\000+\000$\000\000", "\000z\000a\000a\000a\000\000", 0, 8); x2("\000(\000a\000)\000(\000?\000=\000\134\0001\000)\000\000", "\000a\000a\000\000", 0, 2); n("\000(\000a\000)\000$\000|\000\134\0001\000\000", "\000a\000z\000\000"); x2("\000(\000a\000)\000\134\0001\000\000", "\000a\000a\000\000", 0, 4); n("\000(\000a\000)\000\134\0001\000\000", "\000a\000b\000\000"); x2("\000(\000a\000?\000)\000\134\0001\000\000", "\000a\000a\000\000", 0, 4); x2("\000(\000a\000?\000?\000)\000\134\0001\000\000", "\000a\000a\000\000", 0, 0); x2("\000(\000a\000*\000)\000\134\0001\000\000", "\000a\000a\000a\000a\000a\000\000", 0, 8); x3("\000(\000a\000*\000)\000\134\0001\000\000", "\000a\000a\000a\000a\000a\000\000", 0, 4, 1); x2("\000a\000(\000b\000*\000)\000\134\0001\000\000", "\000a\000b\000b\000b\000b\000\000", 0, 10); x2("\000a\000(\000b\000*\000)\000\134\0001\000\000", "\000a\000b\000\000", 0, 2); x2("\000(\000a\000*\000)\000(\000b\000*\000)\000\134\0001\000\134\0002\000\000", "\000a\000a\000a\000b\000b\000a\000a\000a\000b\000b\000\000", 0, 20); x2("\000(\000a\000*\000)\000(\000b\000*\000)\000\134\0002\000\000", "\000a\000a\000a\000b\000b\000b\000b\000\000", 0, 14); x2("\000(\000(\000(\000(\000(\000(\000(\000a\000*\000)\000b\000)\000)\000)\000)\000)\000)\000c\000\134\0007\000\000", "\000a\000a\000a\000b\000c\000a\000a\000a\000\000", 0, 16); x3("\000(\000(\000(\000(\000(\000(\000(\000a\000*\000)\000b\000)\000)\000)\000)\000)\000)\000c\000\134\0007\000\000", "\000a\000a\000a\000b\000c\000a\000a\000a\000\000", 0, 6, 7); x2("\000(\000a\000)\000(\000b\000)\000(\000c\000)\000\134\0002\000\134\0001\000\134\0003\000\000", "\000a\000b\000c\000b\000a\000c\000\000", 0, 12); x2("\000(\000[\000a\000-\000d\000]\000)\000\134\0001\000\000", "\000c\000c\000\000", 0, 4); x2("\000(\000\134\000w\000\134\000d\000\134\000s\000)\000\134\0001\000\000", "\000f\0005\000 \000f\0005\000 \000\000", 0, 12); n("\000(\000\134\000w\000\134\000d\000\134\000s\000)\000\134\0001\000\000", "\000f\0005\000 \000f\0005\000\000"); x2("\000(\000w\000h\000o\000|\000[\000a\000-\000c\000]\000{\0003\000}\000)\000\134\0001\000\000", "\000w\000h\000o\000w\000h\000o\000\000", 0, 12); x2("\000.\000.\000.\000(\000w\000h\000o\000|\000[\000a\000-\000c\000]\000{\0003\000}\000)\000\134\0001\000\000", "\000a\000b\000c\000w\000h\000o\000w\000h\000o\000\000", 0, 18); x2("\000(\000w\000h\000o\000|\000[\000a\000-\000c\000]\000{\0003\000}\000)\000\134\0001\000\000", "\000c\000b\000c\000c\000b\000c\000\000", 0, 12); x2("\000(\000^\000a\000)\000\134\0001\000\000", "\000a\000a\000\000", 0, 4); n("\000(\000^\000a\000)\000\134\0001\000\000", "\000b\000a\000a\000\000"); n("\000(\000a\000$\000)\000\134\0001\000\000", "\000a\000a\000\000"); n("\000(\000a\000b\000\134\000Z\000)\000\134\0001\000\000", "\000a\000b\000\000"); x2("\000(\000a\000*\000\134\000Z\000)\000\134\0001\000\000", "\000a\000\000", 2, 2); x2("\000.\000(\000a\000*\000\134\000Z\000)\000\134\0001\000\000", "\000b\000a\000\000", 2, 4); x3("\000(\000.\000(\000a\000b\000c\000)\000\134\0002\000)\000\000", "\000z\000a\000b\000c\000a\000b\000c\000\000", 0, 14, 1); x3("\000(\000.\000(\000.\000.\000\134\000d\000.\000)\000\134\0002\000)\000\000", "\000z\0001\0002\0003\0004\0001\0002\0003\0004\000\000", 0, 18, 1); x2("\000(\000(\000?\000i\000:\000a\000z\000)\000)\000\134\0001\000\000", "\000A\000z\000A\000z\000\000", 0, 8); n("\000(\000(\000?\000i\000:\000a\000z\000)\000)\000\134\0001\000\000", "\000A\000z\000a\000z\000\000"); x2("\000(\000?\000<\000=\000a\000)\000b\000\000", "\000a\000b\000\000", 2, 4); n("\000(\000?\000<\000=\000a\000)\000b\000\000", "\000b\000b\000\000"); x2("\000(\000?\000<\000=\000a\000|\000b\000)\000b\000\000", "\000b\000b\000\000", 2, 4); x2("\000(\000?\000<\000=\000a\000|\000b\000c\000)\000b\000\000", "\000b\000c\000b\000\000", 4, 6); x2("\000(\000?\000<\000=\000a\000|\000b\000c\000)\000b\000\000", "\000a\000b\000\000", 2, 4); x2("\000(\000?\000<\000=\000a\000|\000b\000c\000|\000|\000d\000e\000f\000g\000h\000i\000j\000|\000k\000l\000m\000n\000o\000p\000q\000|\000r\000)\000z\000\000", "\000r\000z\000\000", 2, 4); x2("\000(\000a\000)\000\134\000g\000<\0001\000>\000\000", "\000a\000a\000\000", 0, 4); x2("\000(\000?\000<\000!\000a\000)\000b\000\000", "\000c\000b\000\000", 2, 4); n("\000(\000?\000<\000!\000a\000)\000b\000\000", "\000a\000b\000\000"); x2("\000(\000?\000<\000!\000a\000|\000b\000c\000)\000b\000\000", "\000b\000b\000b\000\000", 0, 2); n("\000(\000?\000<\000!\000a\000|\000b\000c\000)\000z\000\000", "\000b\000c\000z\000\000"); x2("\000(\000?\000<\000n\000a\000m\000e\0001\000>\000a\000)\000\000", "\000a\000\000", 0, 2); x2("\000(\000?\000<\000n\000a\000m\000e\000_\0002\000>\000a\000b\000)\000\134\000g\000<\000n\000a\000m\000e\000_\0002\000>\000\000", "\000a\000b\000a\000b\000\000", 0, 8); x2("\000(\000?\000<\000n\000a\000m\000e\000_\0003\000>\000.\000z\000v\000.\000)\000\134\000k\000<\000n\000a\000m\000e\000_\0003\000>\000\000", "\000a\000z\000v\000b\000a\000z\000v\000b\000\000", 0, 16); x2("\000(\000?\000<\000=\000\134\000g\000<\000a\000b\000>\000)\000|\000-\000\134\000z\000E\000N\000D\000 \000(\000?\000<\000a\000b\000>\000X\000y\000Z\000)\000\000", "\000X\000y\000Z\000\000", 6, 6); x2("\000(\000?\000<\000n\000>\000|\000a\000\134\000g\000<\000n\000>\000)\000+\000\000", "\000\000", 0, 0); x2("\000(\000?\000<\000n\000>\000|\000\134\000(\000\134\000g\000<\000n\000>\000\134\000)\000)\000+\000$\000\000", "\000(\000)\000(\000(\000)\000)\000\000", 0, 12); x3("\000\134\000g\000<\000n\000>\000(\000?\000<\000n\000>\000.\000)\000{\0000\000}\000\000", "\000X\000\000", 0, 2, 1); x2("\000\134\000g\000<\000n\000>\000(\000a\000b\000c\000|\000d\000f\000(\000?\000<\000n\000>\000.\000Y\000Z\000)\000{\0002\000,\0008\000}\000)\000{\0000\000}\000\000", "\000X\000Y\000Z\000\000", 0, 6); x2("\000\134\000A\000(\000?\000<\000n\000>\000(\000a\000\134\000g\000<\000n\000>\000)\000|\000)\000\134\000z\000\000", "\000a\000a\000a\000a\000\000", 0, 8); x2("\000(\000?\000<\000n\000>\000|\000\134\000g\000<\000m\000>\000\134\000g\000<\000n\000>\000)\000\134\000z\000|\000\134\000z\000E\000N\000D\000 \000(\000?\000<\000m\000>\000a\000|\000(\000b\000)\000\134\000g\000<\000m\000>\000)\000\000", "\000b\000b\000b\000b\000a\000b\000b\000a\000\000", 0, 16); x2("\000(\000?\000<\000n\000a\000m\000e\0001\0002\0004\0000\000>\000\134\000w\000+\000\134\000s\000x\000)\000a\000+\000\134\000k\000<\000n\000a\000m\000e\0001\0002\0004\0000\000>\000\000", "\000 \000 \000f\000g\000 \000x\000a\000a\000a\000a\000a\000a\000a\000a\000f\000g\000 \000x\000\000", 4, 36); x3("\000(\000z\000)\000(\000)\000(\000)\000(\000?\000<\000_\0009\000>\000a\000)\000\134\000g\000<\000_\0009\000>\000\000", "\000z\000a\000a\000\000", 4, 6, 1); x2("\000(\000.\000)\000(\000(\000(\000?\000<\000_\000>\000a\000)\000)\000)\000\134\000k\000<\000_\000>\000\000", "\000z\000a\000a\000\000", 0, 6); x2("\000(\000(\000?\000<\000n\000a\000m\000e\0001\000>\000\134\000d\000)\000|\000(\000?\000<\000n\000a\000m\000e\0002\000>\000\134\000w\000)\000)\000(\000\134\000k\000<\000n\000a\000m\000e\0001\000>\000|\000\134\000k\000<\000n\000a\000m\000e\0002\000>\000)\000\000", "\000f\000f\000\000", 0, 4); x2("\000(\000?\000:\000(\000?\000<\000x\000>\000)\000|\000(\000?\000<\000x\000>\000e\000f\000g\000)\000)\000\134\000k\000<\000x\000>\000\000", "\000\000", 0, 0); x2("\000(\000?\000:\000(\000?\000<\000x\000>\000a\000b\000c\000)\000|\000(\000?\000<\000x\000>\000e\000f\000g\000)\000)\000\134\000k\000<\000x\000>\000\000", "\000a\000b\000c\000e\000f\000g\000e\000f\000g\000\000", 6, 18); n("\000(\000?\000:\000(\000?\000<\000x\000>\000a\000b\000c\000)\000|\000(\000?\000<\000x\000>\000e\000f\000g\000)\000)\000\134\000k\000<\000x\000>\000\000", "\000a\000b\000c\000e\000f\000g\000\000"); x2("\000(\000?\000:\000(\000?\000<\000n\0001\000>\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000)\000\134\000k\000<\000n\0001\000>\000$\000\000", "\000a\000-\000p\000y\000u\000m\000p\000y\000u\000m\000\000", 4, 20); x3("\000(\000?\000:\000(\000?\000<\000n\0001\000>\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000|\000(\000?\000<\000n\0001\000>\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000.\000)\000)\000\134\000k\000<\000n\0001\000>\000$\000\000", "\000x\000x\000x\000x\000a\000b\000c\000d\000e\000f\000g\000h\000i\000j\000k\000l\000m\000n\000a\000b\000c\000d\000e\000f\000g\000h\000i\000j\000k\000l\000m\000n\000\000", 8, 36, 14); x3("\000(\000?\000<\000n\000a\000m\000e\0001\000>\000)\000(\000?\000<\000n\000a\000m\000e\0002\000>\000)\000(\000?\000<\000n\000a\000m\000e\0003\000>\000)\000(\000?\000<\000n\000a\000m\000e\0004\000>\000)\000(\000?\000<\000n\000a\000m\000e\0005\000>\000)\000(\000?\000<\000n\000a\000m\000e\0006\000>\000)\000(\000?\000<\000n\000a\000m\000e\0007\000>\000)\000(\000?\000<\000n\000a\000m\000e\0008\000>\000)\000(\000?\000<\000n\000a\000m\000e\0009\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0000\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0001\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0002\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0003\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0004\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0005\000>\000)\000(\000?\000<\000n\000a\000m\000e\0001\0006\000>\000a\000a\000a\000)\000(\000?\000<\000n\000a\000m\000e\0001\0007\000>\000)\000$\000\000", "\000a\000a\000a\000\000", 0, 6, 16); x2("\000(\000?\000<\000f\000o\000o\000>\000a\000|\000\134\000(\000\134\000g\000<\000f\000o\000o\000>\000\134\000)\000)\000\000", "\000a\000\000", 0, 2); x2("\000(\000?\000<\000f\000o\000o\000>\000a\000|\000\134\000(\000\134\000g\000<\000f\000o\000o\000>\000\134\000)\000)\000\000", "\000(\000(\000(\000(\000(\000(\000a\000)\000)\000)\000)\000)\000)\000\000", 0, 26); x3("\000(\000?\000<\000f\000o\000o\000>\000a\000|\000\134\000(\000\134\000g\000<\000f\000o\000o\000>\000\134\000)\000)\000\000", "\000(\000(\000(\000(\000(\000(\000(\000(\000a\000)\000)\000)\000)\000)\000)\000)\000)\000\000", 0, 34, 1); x2("\000\134\000g\000<\000b\000a\000r\000>\000|\000\134\000z\000E\000N\000D\000(\000?\000<\000b\000a\000r\000>\000.\000*\000a\000b\000c\000$\000)\000\000", "\000a\000b\000c\000x\000x\000x\000a\000b\000c\000\000", 0, 18); x2("\000\134\000g\000<\0001\000>\000|\000\134\000z\000E\000N\000D\000(\000.\000a\000.\000)\000\000", "\000b\000a\000c\000\000", 0, 6); x3("\000\134\000g\000<\000_\000A\000>\000\134\000g\000<\000_\000A\000>\000|\000\134\000z\000E\000N\000D\000(\000.\000a\000.\000)\000(\000?\000<\000_\000A\000>\000.\000b\000.\000)\000\000", "\000x\000b\000x\000y\000b\000y\000\000", 6, 12, 1); x2("\000\134\000A\000(\000?\000:\000\134\000g\000<\000p\000o\000n\000>\000|\000\134\000g\000<\000p\000a\000n\000>\000|\000\134\000z\000E\000N\000D\000 \000 \000(\000?\000<\000p\000a\000n\000>\000a\000|\000c\000\134\000g\000<\000p\000o\000n\000>\000c\000)\000(\000?\000<\000p\000o\000n\000>\000b\000|\000d\000\134\000g\000<\000p\000a\000n\000>\000d\000)\000)\000$\000\000", "\000c\000d\000c\000b\000c\000d\000c\000\000", 0, 14); x2("\000\134\000A\000(\000?\000<\000n\000>\000|\000a\000\134\000g\000<\000m\000>\000)\000\134\000z\000|\000\134\000z\000E\000N\000D\000 \000(\000?\000<\000m\000>\000\134\000g\000<\000n\000>\000)\000\000", "\000a\000a\000a\000a\000\000", 0, 8); x2("\000(\000?\000<\000n\000>\000(\000a\000|\000b\000\134\000g\000<\000n\000>\000c\000)\000{\0003\000,\0005\000}\000)\000\000", "\000b\000a\000a\000a\000a\000c\000a\000\000", 2, 10); x2("\000(\000?\000<\000n\000>\000(\000a\000|\000b\000\134\000g\000<\000n\000>\000c\000)\000{\0003\000,\0005\000}\000)\000\000", "\000b\000a\000a\000a\000a\000c\000a\000a\000a\000a\000a\000\000", 0, 20); x2("\000(\000?\000<\000p\000a\000r\000e\000>\000\134\000(\000(\000[\000^\000\134\000(\000\134\000)\000]\000+\000+\000|\000\134\000g\000<\000p\000a\000r\000e\000>\000)\000*\000+\000\134\000)\000)\000\000", "\000(\000(\000a\000)\000)\000\000", 0, 10); x2("\000(\000)\000*\000\134\0001\000\000", "\000\000", 0, 0); x2("\000(\000?\000:\000(\000)\000|\000(\000)\000)\000*\000\134\0001\000\134\0002\000\000", "\000\000", 0, 0); x3("\000(\000?\000:\000\134\0001\000a\000|\000(\000)\000)\000*\000\000", "\000a\000\000", 0, 0, 1); x2("\000x\000(\000(\000.\000)\000*\000)\000*\000x\000\000", "\0000\000x\0001\000x\0002\000x\0003\000\000", 2, 12); x2("\000x\000(\000(\000.\000)\000*\000)\000*\000x\000(\000?\000i\000:\000\134\0001\000)\000\134\000Z\000\000", "\0000\000x\0001\000x\0002\000x\0001\000X\0002\000\000", 2, 18); x2("\000(\000?\000:\000(\000)\000|\000(\000)\000|\000(\000)\000|\000(\000)\000|\000(\000)\000|\000(\000)\000)\000*\000\134\0002\000\134\0005\000\000", "\000\000", 0, 0); x2("\000(\000?\000:\000(\000)\000|\000(\000)\000|\000(\000)\000|\000(\000x\000)\000|\000(\000)\000|\000(\000)\000)\000*\000\134\0002\000b\000\134\0005\000\000", "\000b\000\000", 0, 2); x2("\217\372\000\000", "\217\372\000\000", 0, 2); x2("\000\000", "0B\000\000", 0, 0); x2("0B\000\000", "0B\000\000", 0, 2); n("0D\000\000", "0B\000\000"); x2("0F0F\000\000", "0F0F\000\000", 0, 4); x2("0B0D0F\000\000", "0B0D0F\000\000", 0, 6); x2("0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S\000\000", "0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S0S\000\000", 0, 70); x2("0B\000\000", "0D0B\000\000", 2, 4); x2("0D0F\000\000", "0B0D0F\000\000", 2, 6); x2("e\207\000\000", "e\207\000\000", 0, 2); x2("\000.\000\000", "0B\000\000", 0, 2); x2("\000.\000.\000\000", "0K0M\000\000", 0, 4); x2("\000(\000?\000u\000)\000\134\000w\000\000", "0J\000\000", 0, 2); n("\000(\000?\000u\000)\000\134\000W\000\000", "0B\000\000"); x2("\000(\000?\000u\000)\000[\000\134\000W\000]\000\000", "0F\000$\000\000", 2, 4); x2("\000\134\000S\000\000", "0]\000\000", 0, 2); x2("\000\134\000S\000\000", "o\042\000\000", 0, 2); x2("\000\134\000b\000\000", "l\027\000 \000\000", 0, 0); x2("\000\134\000b\000\000", "\000 0{\000\000", 2, 2); x2("\000\134\000B\000\000", "0[0]\000 \000\000", 2, 2); x2("\000\134\000B\000\000", "0F\000 \000\000", 4, 4); x2("\000\134\000B\000\000", "\000 0D\000\000", 0, 0); x2("\000[0_0a\000]\000\000", "0a\000\000", 0, 2); n("\000[0j0k\000]\000\000", "0l\000\000"); x2("\000[0F\000-0J\000]\000\000", "0H\000\000", 0, 2); n("\000[\000^0Q\000]\000\000", "0Q\000\000"); x2("\000(\000?\000u\000)\000[\000\134\000w\000]\000\000", "0m\000\000", 0, 2); n("\000[\000\134\000d\000]\000\000", "0u\000\000"); x2("\000[\000\134\000D\000]\000\000", "0o\000\000", 0, 2); n("\000[\000\134\000s\000]\000\000", "0O\000\000"); x2("\000[\000\134\000S\000]\000\000", "0x\000\000", 0, 2); x2("\000(\000?\000u\000)\000[\000\134\000w\000\134\000d\000]\000\000", "0\210\000\000", 0, 2); x2("\000(\000?\000u\000)\000[\000\134\000w\000\134\000d\000]\000\000", "\000 \000 \000 0\210\000\000", 6, 8); n("\000(\000?\000u\000)\000\134\000w\233<\216\312\000\000", "\000 \233<\216\312\000\000"); x2("\000(\000?\000u\000)\233<\000\134\000W\216\312\000\000", "\233<\000 \216\312\000\000", 0, 6); x2("0B\000.0D\000.0F\000\000", "0B0B0D0D0F\000\000", 0, 10); x2("\000(\000?\000u\000)\000.\000\134\000w0F\000\134\000W\000.\000.0^\000\000", "0H0F0F\000 0F0^0^\000\000", 0, 14); x2("\000(\000?\000u\000)\000\134\000s\000\134\000w0S0S0S\000\000", "\000 0S0S0S0S\000\000", 0, 10); x2("0B0B\000.0Q\000\000", "0B0B0Q0Q\000\000", 0, 8); n("\000.0D\000\000", "0D0H\000\000"); x2("\000.0J\000\000", "0J0J\000\000", 0, 4); x2("\000^0B\000\000", "0B\000\000", 0, 2); x2("\000^0\200\000$\000\000", "0\200\000\000", 0, 2); x2("\000(\000?\000u\000)\000^\000\134\000w\000$\000\000", "0k\000\000", 0, 2); x2("\000(\000?\000u\000)\000^\000\134\000w0K0M0O0Q0S\000$\000\000", "\000z0K0M0O0Q0S\000\000", 0, 12); x2("\000(\000?\000u\000)\000^\000\134\000w\000.\000.\000.0F0H0J\000$\000\000", "\000z0B0D0F0F0H0J\000\000", 0, 14); x2("\000(\000?\000u\000)\000\134\000w\000\134\000w\000\134\000s\000\134\000W0J0J0J\000\134\000d\000\000", "\000a0J\000 \000 0J0J0J\0004\000\000", 0, 16); x2("\000\134\000A0_0a0d\000\000", "0_0a0d\000\000", 0, 6); x2("0\2000\2010\202\000\134\000Z\000\000", "0\2000\2010\202\000\000", 0, 6); x2("0K0M0O\000\134\000z\000\000", "0K0M0O\000\000", 0, 6); x2("0K0M0O\000\134\000Z\000\000", "0K0M0O\000\012\000\000", 0, 6); x2("\000\134\000G0}0t\000\000", "0}0t\000\000", 0, 4); n("\000\134\000G0H\000\000", "0F0H0J\000\000"); n("0h0f\000\134\000G\000\000", "0h0f\000\000"); n("0~0\177\000\134\000A\000\000", "0~0\177\000\000"); n("0~\000\134\000A0\177\000\000", "0~0\177\000\000"); x2("\000(\000?\000=0[\000)0[\000\000", "0[\000\000", 0, 2); n("\000(\000?\000=0F\000)\000.\000\000", "0D\000\000"); x2("\000(\000?\000!0F\000)0K\000\000", "0K\000\000", 0, 2); n("\000(\000?\000!0h\000)0B\000\000", "0h\000\000"); x2("\000(\000?\000i\000:0B\000)\000\000", "0B\000\000", 0, 2); x2("\000(\000?\000i\000:0v0y\000)\000\000", "0v0y\000\000", 0, 4); n("\000(\000?\000i\000:0D\000)\000\000", "0F\000\000"); x2("\000(\000?\000m\000:0\210\000.\000)\000\000", "0\210\000\012\000\000", 0, 4); x2("\000(\000?\000m\000:\000.0\201\000)\000\000", "0~\000\0120\201\000\000", 2, 6); x2("0B\000?\000\000", "\000\000", 0, 0); x2("Y\011\000?\000\000", "S\026\000\000", 0, 0); x2("Y\011\000?\000\000", "Y\011\000\000", 0, 2); x2("\221\317\000*\000\000", "\000\000", 0, 0); x2("\221\317\000*\000\000", "\221\317\000\000", 0, 2); x2("[P\000*\000\000", "[P[P[P\000\000", 0, 6); x2("\231\254\000*\000\000", "\236\177\231\254\231\254\231\254\231\254\000\000", 0, 0); n("\134q\000+\000\000", "\000\000"); x2("l\263\000+\000\000", "l\263\000\000", 0, 2); x2("fB\000+\000\000", "fBfBfBfB\000\000", 0, 8); x2("0H\000+\000\000", "0H0H0F0F0F\000\000", 0, 4); x2("0F\000+\000\000", "0J0F0F0F0F\000\000", 2, 10); x2("\000.\000?\000\000", "0_\000\000", 0, 2); x2("\000.\000*\000\000", "0q0t0w0z\000\000", 0, 8); x2("\000.\000+\000\000", "0\215\000\000", 0, 2); x2("\000.\000+\000\000", "0D0F0H0K\000\012\000\000", 0, 8); x2("0B\000|0D\000\000", "0B\000\000", 0, 2); x2("0B\000|0D\000\000", "0D\000\000", 0, 2); x2("0B0D\000|0D0F\000\000", "0B0D\000\000", 0, 4); x2("0B0D\000|0D0F\000\000", "0D0F\000\000", 0, 4); x2("0\222\000(\000?\000:0K0M\000|0M0O\000)\000\000", "0\2220K0M\000\000", 0, 6); x2("0\222\000(\000?\000:0K0M\000|0M0O\000)0Q\000\000", "0\2220M0O0Q\000\000", 0, 8); x2("0B0D\000|\000(\000?\000:0B0F\000|0B0\222\000)\000\000", "0B0\222\000\000", 0, 4); x2("0B\000|0D\000|0F\000\000", "0H0F\000\000", 2, 4); x2("0B\000|0D\000|0F0H\000|0J0K0M\000|0O\000|0Q0S0U\000|0W0Y0[\000|0]\000|0_0a\000|0d0f0h0j0k\000|0l0m\000\000", "0W0Y0[\000\000", 0, 6); n("0B\000|0D\000|0F0H\000|0J0K0M\000|0O\000|0Q0S0U\000|0W0Y0[\000|0]\000|0_0a\000|0d0f0h0j0k\000|0l0m\000\000", "0Y0[\000\000"); x2("0B\000|\000^0\217\000\000", "0v0B\000\000", 2, 4); x2("0B\000|\000^0\222\000\000", "0\2220B\000\000", 0, 2); x2("\233<\000|\000\134\000G\216\312\000\000", "0Q\216\312\233<\000\000", 4, 6); x2("\233<\000|\000\134\000G\216\312\000\000", "\216\312\233<\000\000", 0, 2); x2("\233<\000|\000\134\000A\216\312\000\000", "\000b\216\312\233<\000\000", 4, 6); x2("\233<\000|\000\134\000A\216\312\000\000", "\216\312\000\000", 0, 2); x2("\233<\000|\216\312\000\134\000Z\000\000", "\216\312\233<\000\000", 2, 4); x2("\233<\000|\216\312\000\134\000Z\000\000", "\216\312\000\000", 0, 2); x2("\233<\000|\216\312\000\134\000Z\000\000", "\216\312\000\012\000\000", 0, 2); x2("\233<\000|\216\312\000\134\000z\000\000", "\216\312\233<\000\000", 2, 4); x2("\233<\000|\216\312\000\134\000z\000\000", "\216\312\000\000", 0, 2); x2("\000(\000?\000u\000)\000\134\000w\000|\000\134\000s\000\000", "0J\000\000", 0, 2); x2("\000(\000?\000u\000)\000\134\000w\000|\000%\000\000", "\000%0J\000\000", 0, 2); x2("\000(\000?\000u\000)\000\134\000w\000|\000[\000&\000$\000]\000\000", "0F\000&\000\000", 0, 2); x2("\000[0D\000-0Q\000]\000\000", "0F\000\000", 0, 2); x2("\000[0D\000-0Q\000]\000|\000[\000^0K\000-0S\000]\000\000", "0B\000\000", 0, 2); x2("\000[0D\000-0Q\000]\000|\000[\000^0K\000-0S\000]\000\000", "0K\000\000", 0, 2); x2("\000[\000^0B\000]\000\000", "\000\012\000\000", 0, 2); x2("\000(\000?\000:0B\000|\000[0F\000-0M\000]\000)\000|0D0\222\000\000", "0F0\222\000\000", 0, 2); x2("\000(\000?\000:0B\000|\000[0F\000-0M\000]\000)\000|0D0\222\000\000", "0D0\222\000\000", 0, 4); x2("0B0D0F\000|\000(\000?\000=0Q0Q\000)\000.\000.0{\000\000", "0Q0Q0{\000\000", 0, 6); x2("0B0D0F\000|\000(\000?\000!0Q0Q\000)\000.\000.0{\000\000", "0B0D0{\000\000", 0, 6); x2("\000(\000?\000=0\2220B\000)\000.\000.0B\000|\000(\000?\000=0\2220\222\000)\000.\000.0B\000\000", "0\2220\2220B\000\000", 0, 6); x2("\000(\000?\000<\000=0B\000|0D0F\000)0D\000\000", "0D0F0D\000\000", 4, 6); n("\000(\000?\000>0B\000|0B0D0H\000)0F\000\000", "0B0D0H0F\000\000"); x2("\000(\000?\000>0B0D0H\000|0B\000)0F\000\000", "0B0D0H0F\000\000", 0, 8); x2("0B\000?\000|0D\000\000", "0B\000\000", 0, 2); x2("0B\000?\000|0D\000\000", "0D\000\000", 0, 0); x2("0B\000?\000|0D\000\000", "\000\000", 0, 0); x2("0B\000*\000|0D\000\000", "0B0B\000\000", 0, 4); x2("0B\000*\000|0D\000*\000\000", "0D0B\000\000", 0, 0); x2("0B\000*\000|0D\000*\000\000", "0B0D\000\000", 0, 2); x2("\000[\000a0B\000]\000*\000|0D\000*\000\000", "\000a0B0D0D0D\000\000", 0, 4); x2("0B\000+\000|0D\000*\000\000", "\000\000", 0, 0); x2("0B\000+\000|0D\000*\000\000", "0D0D0D\000\000", 0, 6); x2("0B\000+\000|0D\000*\000\000", "0B0D0D0D\000\000", 0, 2); x2("0B\000+\000|0D\000*\000\000", "\000a0B0D0D0D\000\000", 0, 0); n("0B\000+\000|0D\000+\000\000", "\000\000"); x2("\000(0B\000|0D\000)\000?\000\000", "0D\000\000", 0, 2); x2("\000(0B\000|0D\000)\000*\000\000", "0D0B\000\000", 0, 4); x2("\000(0B\000|0D\000)\000+\000\000", "0D0B0D\000\000", 0, 6); x2("\000(0B0D\000|0F0B\000)\000+\000\000", "0F0B0B0D0F0H\000\000", 0, 8); x2("\000(0B0D\000|0F0H\000)\000+\000\000", "0F0B0B0D0F0H\000\000", 4, 12); x2("\000(0B0D\000|0F0B\000)\000+\000\000", "0B0B0D0F0B\000\000", 2, 10); x2("\000(0B0D\000|0F0B\000)\000+\000\000", "0B0D0\2220F0B\000\000", 0, 4); x2("\000(0B0D\000|0F0B\000)\000+\000\000", "\000$\000$\000z\000z\000z\000z0B0D0\2220F0B\000\000", 12, 16); x2("\000(0B\000|0D0B0D\000)\000+\000\000", "0B0D0B0D0B\000\000", 0, 10); x2("\000(0B\000|0D0B0D\000)\000+\000\000", "0D0B\000\000", 2, 4); x2("\000(0B\000|0D0B0D\000)\000+\000\000", "0D0B0B0B0D0B\000\000", 2, 8); x2("\000(\000?\000:0B\000|0D\000)\000(\000?\000:0B\000|0D\000)\000\000", "0B0D\000\000", 0, 4); x2("\000(\000?\000:0B\000*\000|0D\000*\000)\000(\000?\000:0B\000*\000|0D\000*\000)\000\000", "0B0B0B0D0D0D\000\000", 0, 6); x2("\000(\000?\000:0B\000*\000|0D\000*\000)\000(\000?\000:0B\000+\000|0D\000+\000)\000\000", "0B0B0B0D0D0D\000\000", 0, 12); x2("\000(\000?\000:0B\000+\000|0D\000+\000)\000{\0002\000}\000\000", "0B0B0B0D0D0D\000\000", 0, 12); x2("\000(\000?\000:0B\000+\000|0D\000+\000)\000{\0001\000,\0002\000}\000\000", "0B0B0B0D0D0D\000\000", 0, 12); x2("\000(\000?\000:0B\000+\000|\000\134\000A0D\000*\000)0F0F\000\000", "0F0F\000\000", 0, 4); n("\000(\000?\000:0B\000+\000|\000\134\000A0D\000*\000)0F0F\000\000", "0B0D0F0F\000\000"); x2("\000(\000?\000:\000^0B\000+\000|0D\000+\000)\000*0F\000\000", "0B0B0D0D0D0B0D0F\000\000", 12, 16); x2("\000(\000?\000:\000^0B\000+\000|0D\000+\000)\000*0F\000\000", "0B0B0D0D0D0D0F\000\000", 0, 14); x2("0F\000{\0000\000,\000}\000\000", "0F0F0F0F\000\000", 0, 8); x2("0B\000|\000(\000?\000i\000)\000c\000\000", "\000C\000\000", 0, 2); x2("\000(\000?\000i\000)\000c\000|0B\000\000", "\000C\000\000", 0, 2); x2("\000(\000?\000i\000:0B\000)\000|\000a\000\000", "\000a\000\000", 0, 2); n("\000(\000?\000i\000:0B\000)\000|\000a\000\000", "\000A\000\000"); x2("\000[0B0D0F\000]\000?\000\000", "0B0D0F\000\000", 0, 2); x2("\000[0B0D0F\000]\000*\000\000", "0B0D0F\000\000", 0, 6); x2("\000[\000^0B0D0F\000]\000*\000\000", "0B0D0F\000\000", 0, 0); n("\000[\000^0B0D0F\000]\000+\000\000", "0B0D0F\000\000"); x2("0B\000?\000?\000\000", "0B0B0B\000\000", 0, 0); x2("0D0B\000?\000?0D\000\000", "0D0B0D\000\000", 0, 6); x2("0B\000*\000?\000\000", "0B0B0B\000\000", 0, 0); x2("0D0B\000*\000?\000\000", "0D0B0B\000\000", 0, 2); x2("0D0B\000*\000?0D\000\000", "0D0B0B0D\000\000", 0, 8); x2("0B\000+\000?\000\000", "0B0B0B\000\000", 0, 2); x2("0D0B\000+\000?\000\000", "0D0B0B\000\000", 0, 4); x2("0D0B\000+\000?0D\000\000", "0D0B0B0D\000\000", 0, 8); x2("\000(\000?\000:Y)\000?\000)\000?\000?\000\000", "Y)\000\000", 0, 0); x2("\000(\000?\000:Y)\000?\000?\000)\000?\000\000", "Y)\000\000", 0, 0); x2("\000(\000?\000:Y\042\000?\000)\000+\000?\000\000", "Y\042Y\042Y\042\000\000", 0, 2); x2("\000(\000?\000:\230\250\000+\000)\000?\000?\000\000", "\230\250\230\250\230\250\000\000", 0, 0); x2("\000(\000?\000:\226\352\000+\000)\000?\000?\227\034\000\000", "\226\352\226\352\226\352\227\034\000\000", 0, 8); x2("\000(\000?\000:0B0D\000)\000?\000{\0002\000}\000\000", "\000\000", 0, 0); x2("\000(\000?\000:\233<\216\312\000)\000?\000{\0002\000}\000\000", "\233<\216\312\233<\216\312\233<\000\000", 0, 8); x2("\000(\000?\000:\233<\216\312\000)\000*\000{\0000\000}\000\000", "\233<\216\312\233<\216\312\233<\000\000", 0, 0); x2("\000(\000?\000:\233<\216\312\000)\000{\0003\000,\000}\000\000", "\233<\216\312\233<\216\312\233<\216\312\233<\216\312\000\000", 0, 16); n("\000(\000?\000:\233<\216\312\000)\000{\0003\000,\000}\000\000", "\233<\216\312\233<\216\312\000\000"); x2("\000(\000?\000:\233<\216\312\000)\000{\0002\000,\0004\000}\000\000", "\233<\216\312\233<\216\312\233<\216\312\000\000", 0, 12); x2("\000(\000?\000:\233<\216\312\000)\000{\0002\000,\0004\000}\000\000", "\233<\216\312\233<\216\312\233<\216\312\233<\216\312\233<\216\312\000\000", 0, 16); x2("\000(\000?\000:\233<\216\312\000)\000{\0002\000,\0004\000}\000?\000\000", "\233<\216\312\233<\216\312\233<\216\312\233<\216\312\233<\216\312\000\000", 0, 8); x2("\000(\000?\000:\233<\216\312\000)\000{\000,\000}\000\000", "\233<\216\312\000{\000,\000}\000\000", 0, 10); x2("\000(\000?\000:0K0M0O\000)\000+\000?\000{\0002\000}\000\000", "0K0M0O0K0M0O0K0M0O\000\000", 0, 12); x3("\000(pk\000)\000\000", "pk\000\000", 0, 2, 1); x3("\000(pkl4\000)\000\000", "pkl4\000\000", 0, 4, 1); x2("\000(\000(fB\225\223\000)\000)\000\000", "fB\225\223\000\000", 0, 4); x3("\000(\000(\230\250l4\000)\000)\000\000", "\230\250l4\000\000", 0, 4, 1); x3("\000(\000(f(e\345\000)\000)\000\000", "f(e\345\000\000", 0, 4, 2); x3("\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\000(\221\317[P\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000)\000\000", "\221\317[P\000\000", 0, 4, 20); x3("\000(0B0D\000)\000(0F0H\000)\000\000", "0B0D0F0H\000\000", 0, 4, 1); x3("\000(0B0D\000)\000(0F0H\000)\000\000", "0B0D0F0H\000\000", 4, 8, 2); x3("\000(\000)\000(0B\000)0D0F\000(0H0J0K\000)0M0O0Q0S\000\000", "0B0D0F0H0J0K0M0O0Q0S\000\000", 6, 12, 3); x3("\000(\000(\000)\000(0B\000)0D0F\000(0H0J0K\000)0M0O0Q0S\000)\000\000", "0B0D0F0H0J0K0M0O0Q0S\000\000", 6, 12, 4); x3("\000.\000*\000(0\3250\251\000)0\3630\3730\336\000(0\363\000(\000)0\2670\3450\277\000)0\2440\363\000\000", "0\3250\2510\3630\3730\3360\3630\2670\3450\2770\2440\363\000\000", 10, 18, 2); x2("\000(\000^0B\000)\000\000", "0B\000\000", 0, 2); x3("\000(0B\000)\000|\000(0B\000)\000\000", "0D0B\000\000", 2, 4, 1); x3("\000(\000^0B\000)\000|\000(0B\000)\000\000", "0D0B\000\000", 2, 4, 2); x3("\000(0B\000?\000)\000\000", "0B0B0B\000\000", 0, 2, 1); x3("\000(0~\000*\000)\000\000", "0~0~0~\000\000", 0, 6, 1); x3("\000(0h\000*\000)\000\000", "\000\000", 0, 0, 1); x3("\000(0\213\000+\000)\000\000", "0\2130\2130\2130\2130\2130\2130\213\000\000", 0, 14, 1); x3("\000(0u\000+\000|0x\000*\000)\000\000", "0u0u0u0x0x\000\000", 0, 6, 1); x3("\000(0B\000+\000|0D\000?\000)\000\000", "0D0D0D0B0B\000\000", 0, 2, 1); x3("\000(0B0D0F\000)\000?\000\000", "0B0D0F\000\000", 0, 6, 1); x3("\000(0B0D0F\000)\000*\000\000", "0B0D0F\000\000", 0, 6, 1); x3("\000(0B0D0F\000)\000+\000\000", "0B0D0F\000\000", 0, 6, 1); x3("\000(0U0W0Y\000|0B0D0F\000)\000+\000\000", "0B0D0F\000\000", 0, 6, 1); x3("\000(\000[0j0k0l\000]\000[0K0M0O\000]\000|0K0M0O\000)\000+\000\000", "0K0M0O\000\000", 0, 6, 1); x3("\000(\000(\000?\000i\000:0B0D0F\000)\000)\000\000", "0B0D0F\000\000", 0, 6, 1); x3("\000(\000(\000?\000m\000:0B\000.0F\000)\000)\000\000", "0B\000\0120F\000\000", 0, 6, 1); x3("\000(\000(\000?\000=0B0\223\000)0B\000)\000\000", "0B0\2230D\000\000", 0, 2, 1); x3("0B0D0F\000|\000(\000.0B0D0H\000)\000\000", "0\2230B0D0H\000\000", 0, 8, 1); x3("0B\000*\000(\000.\000)\000\000", "0B0B0B0B0\223\000\000", 8, 10, 1); x3("0B\000*\000?\000(\000.\000)\000\000", "0B0B0B0B0\223\000\000", 0, 2, 1); x3("0B\000*\000?\000(0\223\000)\000\000", "0B0B0B0B0\223\000\000", 8, 10, 1); x3("\000[0D0F0H\000]0B\000*\000(\000.\000)\000\000", "0H0B0B0B0B0\223\000\000", 10, 12, 1); x3("\000(\000\134\000A0D0D\000)0F0F\000\000", "0D0D0F0F\000\000", 0, 4, 1); n("\000(\000\134\000A0D0D\000)0F0F\000\000", "0\2230D0D0F0F\000\000"); x3("\000(\000^0D0D\000)0F0F\000\000", "0D0D0F0F\000\000", 0, 4, 1); n("\000(\000^0D0D\000)0F0F\000\000", "0\2230D0D0F0F\000\000"); x3("0\2150\215\000(0\2130\213\000$\000)\000\000", "0\2150\2150\2130\213\000\000", 4, 8, 1); n("0\2150\215\000(0\2130\213\000$\000)\000\000", "0\2150\2150\2130\2130\213\000\000"); x2("\000(q!\000)\000\134\0001\000\000", "q!q!\000\000", 0, 4); n("\000(q!\000)\000\134\0001\000\000", "q!kf\000\000"); x2("\000(zz\000?\000)\000\134\0001\000\000", "zzzz\000\000", 0, 4); x2("\000(zz\000?\000?\000)\000\134\0001\000\000", "zzzz\000\000", 0, 0); x2("\000(zz\000*\000)\000\134\0001\000\000", "zzzzzzzzzz\000\000", 0, 8); x3("\000(zz\000*\000)\000\134\0001\000\000", "zzzzzzzzzz\000\000", 0, 4, 1); x2("0B\000(0D\000*\000)\000\134\0001\000\000", "0B0D0D0D0D\000\000", 0, 10); x2("0B\000(0D\000*\000)\000\134\0001\000\000", "0B0D\000\000", 0, 2); x2("\000(0B\000*\000)\000(0D\000*\000)\000\134\0001\000\134\0002\000\000", "0B0B0B0D0D0B0B0B0D0D\000\000", 0, 20); x2("\000(0B\000*\000)\000(0D\000*\000)\000\134\0002\000\000", "0B0B0B0D0D0D0D\000\000", 0, 14); x3("\000(0B\000*\000)\000(0D\000*\000)\000\134\0002\000\000", "0B0B0B0D0D0D0D\000\000", 6, 10, 2); x2("\000(\000(\000(\000(\000(\000(\000(0}\000*\000)0z\000)\000)\000)\000)\000)\000)0t\000\134\0007\000\000", "0}0}0}0z0t0}0}0}\000\000", 0, 16); x3("\000(\000(\000(\000(\000(\000(\000(0}\000*\000)0z\000)\000)\000)\000)\000)\000)0t\000\134\0007\000\000", "0}0}0}0z0t0}0}0}\000\000", 0, 6, 7); x2("\000(0o\000)\000(0r\000)\000(0u\000)\000\134\0002\000\134\0001\000\134\0003\000\000", "0o0r0u0r0o0u\000\000", 0, 12); x2("\000(\000[0M\000-0Q\000]\000)\000\134\0001\000\000", "0O0O\000\000", 0, 4); x2("\000(\000?\000u\000)\000(\000\134\000w\000\134\000d\000\134\000s\000)\000\134\0001\000\000", "0B\0005\000 0B\0005\000 \000\000", 0, 12); n("\000(\000?\000u\000)\000(\000\134\000w\000\134\000d\000\134\000s\000)\000\134\0001\000\000", "0B\0005\000 0B\0005\000\000"); x2("\000(\212\260\377\037\000|\000[0B\000-0F\000]\000{\0003\000}\000)\000\134\0001\000\000", "\212\260\377\037\212\260\377\037\000\000", 0, 8); x2("\000.\000.\000.\000(\212\260\377\037\000|\000[0B\000-0F\000]\000{\0003\000}\000)\000\134\0001\000\000", "0B\000a0B\212\260\377\037\212\260\377\037\000\000", 0, 14); x2("\000(\212\260\377\037\000|\000[0B\000-0F\000]\000{\0003\000}\000)\000\134\0001\000\000", "0F0D0F0F0D0F\000\000", 0, 12); x2("\000(\000^0S\000)\000\134\0001\000\000", "0S0S\000\000", 0, 4); n("\000(\000^0\200\000)\000\134\0001\000\000", "0\2010\2000\200\000\000"); n("\000(0B\000$\000)\000\134\0001\000\000", "0B0B\000\000"); n("\000(0B0D\000\134\000Z\000)\000\134\0001\000\000", "0B0D\000\000"); x2("\000(0B\000*\000\134\000Z\000)\000\134\0001\000\000", "0B\000\000", 2, 2); x2("\000.\000(0B\000*\000\134\000Z\000)\000\134\0001\000\000", "0D0B\000\000", 2, 4); x3("\000(\000.\000(0\2040D0\206\000)\000\134\0002\000)\000\000", "\000z0\2040D0\2060\2040D0\206\000\000", 0, 14, 1); x3("\000(\000.\000(\000.\000.\000\134\000d\000.\000)\000\134\0002\000)\000\000", "0B\0001\0002\0003\0004\0001\0002\0003\0004\000\000", 0, 18, 1); x2("\000(\000(\000?\000i\000:0B\000v0Z\000)\000)\000\134\0001\000\000", "0B\000v0Z0B\000v0Z\000\000", 0, 12); x2("\000(\000?\000Y\011\000|\000\134\000(\000\134\000g\000\000\134\000)\000)\000\000", "\000(\000(\000(\000(\000(\000(Y\011\000)\000)\000)\000)\000)\000)\000\000", 0, 26); x2("\000\134\000A\000(\000?\000:\000\134\000g\000<\226?\000_\0001\000>\000|\000\134\000g\000\000|\000\134\000z}BN\206\000 \000 \000(\000?\000<\226?\000_\0001\000>\211\263\000|\201\352\000\134\000g\000\201\352\000)\000(\000?\000W(\000|\203\351\205\251\000\134\000g\000<\226?\000_\0001\000>\203\351\205\251\000)\000)\000$\000\000", "\203\351\205\251\201\352\203\351\205\251\201\352W(\201\352\203\351\205\251\201\352\203\351\205\251\000\000", 0, 26); x2("\000[\000[0r0u\000]\000]\000\000", "0u\000\000", 0, 2); x2("\000[\000[0D0J0F\000]0K\000]\000\000", "0K\000\000", 0, 2); n("\000[\000[\000^0B\000]\000]\000\000", "0B\000\000"); n("\000[\000^\000[0B\000]\000]\000\000", "0B\000\000"); x2("\000[\000^\000[\000^0B\000]\000]\000\000", "0B\000\000", 0, 2); x2("\000[\000[0K0M0O\000]\000&\000&0M0O\000]\000\000", "0O\000\000", 0, 2); n("\000[\000[0K0M0O\000]\000&\000&0M0O\000]\000\000", "0K\000\000"); n("\000[\000[0K0M0O\000]\000&\000&0M0O\000]\000\000", "0Q\000\000"); x2("\000[0B\000-0\223\000&\000&0D\000-0\222\000&\000&0F\000-0\221\000]\000\000", "0\221\000\000", 0, 2); n("\000[\000^0B\000-0\223\000&\000&0D\000-0\222\000&\000&0F\000-0\221\000]\000\000", "0\221\000\000"); x2("\000[\000[\000^0B\000&\000&0B\000]\000&\000&0B\000-0\223\000]\000\000", "0D\000\000", 0, 2); n("\000[\000[\000^0B\000&\000&0B\000]\000&\000&0B\000-0\223\000]\000\000", "0B\000\000"); x2("\000[\000[\000^0B\000-0\223\000&\000&0D0F0H0J\000]\000&\000&\000[\000^0F\000-0K\000]\000]\000\000", "0M\000\000", 0, 2); n("\000[\000[\000^0B\000-0\223\000&\000&0D0F0H0J\000]\000&\000&\000[\000^0F\000-0K\000]\000]\000\000", "0D\000\000"); x2("\000[\000^\000[\000^0B0D0F\000]\000&\000&\000[\000^0F0H0J\000]\000]\000\000", "0F\000\000", 0, 2); x2("\000[\000^\000[\000^0B0D0F\000]\000&\000&\000[\000^0F0H0J\000]\000]\000\000", "0H\000\000", 0, 2); n("\000[\000^\000[\000^0B0D0F\000]\000&\000&\000[\000^0F0H0J\000]\000]\000\000", "0K\000\000"); x2("\000[0B\000-\000&\000&\000-0B\000]\000\000", "\000-\000\000", 0, 2); x2("\000[\000^\000[\000^\000a\000-\000z0B0D0F\000]\000&\000&\000[\000^\000b\000c\000d\000e\000f\000g0F0H0J\000]\000q\000-\000w\000]\000\000", "0H\000\000", 0, 2); x2("\000[\000^\000[\000^\000a\000-\000z0B0D0F\000]\000&\000&\000[\000^\000b\000c\000d\000e\000f\000g0F0H0J\000]\000g\000-\000w\000]\000\000", "\000f\000\000", 0, 2); x2("\000[\000^\000[\000^\000a\000-\000z0B0D0F\000]\000&\000&\000[\000^\000b\000c\000d\000e\000f\000g0F0H0J\000]\000g\000-\000w\000]\000\000", "\000g\000\000", 0, 2); n("\000[\000^\000[\000^\000a\000-\000z0B0D0F\000]\000&\000&\000[\000^\000b\000c\000d\000e\000f\000g0F0H0J\000]\000g\000-\000w\000]\000\000", "\0002\000\000"); x2("\000a\000<\000b\000>0\3200\3740\2700\3470\3630n0\3000\2460\3630\3550\3740\311\000<\000\134\000/\000b\000>\000\000", "\000a\000<\000b\000>0\3200\3740\2700\3470\3630n0\3000\2460\3630\3550\3740\311\000<\000/\000b\000>\000\000", 0, 40); x2("\000.\000<\000b\000>0\3200\3740\2700\3470\3630n0\3000\2460\3630\3550\3740\311\000<\000\134\000/\000b\000>\000\000", "\000a\000<\000b\000>0\3200\3740\2700\3470\3630n0\3000\2460\3630\3550\3740\311\000<\000/\000b\000>\000\000", 0, 40); fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d (by Onigmo %s)\n", nsucc, nfail, nerror, onig_version()); #ifndef POSIX_TEST onig_region_free(region, 1); onig_end(); #endif return ((nfail == 0 && nerror == 0) ? 0 : -1); } ================================================ FILE: src/Onigmo/tool/.gitignore ================================================ # ignore UCD files Blocks.txt CaseFolding.txt DerivedAge.txt DerivedCoreProperties.txt PropList.txt PropertyAliases.txt PropertyValueAliases.txt Scripts.txt UnicodeData.txt # ignore generated files casefold.h name2ctype.h name2ctype.kwd ================================================ FILE: src/Onigmo/tool/CaseFolding.py ================================================ #!/usr/bin/env python # -*- coding: utf-8 -*- # Usage: # $ wget http://www.unicode.org/Public/UNIDATA/CaseFolding.txt # $ python CaseFolding.py CaseFolding.txt > ../enc/unicode/casefold.h from __future__ import print_function import sys import re def print_case_folding_data(filename): pattern = re.compile("([0-9A-F]{4,6}); ([CFT]); " + "([0-9A-F]{4,6})(?: ([0-9A-F]{4,6}))?(?: ([0-9A-F]{4,6}))?;") fold = {} unfold = [{}, {}, {}] turkic = [] with open(filename, 'r') as f: for line in f: res = pattern.match(line) if not res: continue ch_from = int(res.group(1), 16) ch_to = [] if res.group(2) == 'T': # Turkic case folding turkic.append(ch_from) continue # store folding data for i in range(3, 6): if res.group(i): ch_to.append(int(res.group(i), 16)) fold[ch_from] = ch_to # store unfolding data key = tuple(ch_to) i = len(key) - 1 unfold[i].setdefault(key, []).append(ch_from) # move locale dependent data to (un)fold_locale fold_locale = {} unfold_locale = [{}, {}] for ch_from in turkic: key = tuple(fold[ch_from]) i = len(key) - 1 unfold_locale[i][key] = unfold[i][key] del unfold[i][key] fold_locale[ch_from] = fold[ch_from] del fold[ch_from] # print the header print("/* DO NOT EDIT THIS FILE. */") print("/* Generated by tool/CaseFolding.py */\n") # print folding data # CaseFold print("static const CaseFold_11_Type CaseFold[] = {") for k, v in sorted(fold.items()): sv = ", ".join("0x%04x" % i for i in v) print(" { 0x%04x, {%d, {%s}}}," % (k, len(v), sv)) print("};\n") # CaseFold_Locale print("static const CaseFold_11_Type CaseFold_Locale[] = {") for k, v in sorted(fold_locale.items()): sv = ", ".join("0x%04x" % i for i in v) print(" { 0x%04x, {%d, {%s}}}," % (k, len(v), sv)) print("};\n") # print unfolding data # CaseUnfold_11 print("static const CaseUnfold_11_Type CaseUnfold_11[] = {") for k, v in sorted(unfold[0].items()): sv = ", ".join("0x%04x" % i for i in v) print(" { 0x%04x, {%d, {%s }}}," % (k[0], len(v), sv)) print("};\n") # CaseUnfold_11_Locale print("static const CaseUnfold_11_Type CaseUnfold_11_Locale[] = {") for k, v in sorted(unfold_locale[0].items()): sv = ", ".join("0x%04x" % i for i in v) print(" { 0x%04x, {%d, {%s }}}," % (k[0], len(v), sv)) print("};\n") # CaseUnfold_12 print("static const CaseUnfold_12_Type CaseUnfold_12[] = {") for k, v in sorted(unfold[1].items()): sk = ", ".join("0x%04x" % i for i in k) sv = ", ".join("0x%04x" % i for i in v) print(" { {%s}, {%d, {%s }}}," % (sk, len(v), sv)) print("};\n") # CaseUnfold_12_Locale print("static const CaseUnfold_12_Type CaseUnfold_12_Locale[] = {") for k, v in sorted(unfold_locale[1].items()): sk = ", ".join("0x%04x" % i for i in k) sv = ", ".join("0x%04x" % i for i in v) print(" { {%s}, {%d, {%s }}}," % (sk, len(v), sv)) print("};\n") # CaseUnfold_13 print("static const CaseUnfold_13_Type CaseUnfold_13[] = {") for k, v in sorted(unfold[2].items()): sk = ", ".join("0x%04x" % i for i in k) sv = ", ".join("0x%04x" % i for i in v) print(" { {%s}, {%d, {%s }}}," % (sk, len(v), sv)) print("};\n") # table sizes fold_table_size = len(fold) + len(fold_locale) print("#define FOLD_TABLE_SIZE\t\t%d" % int(fold_table_size * 1.2)) unfold1_table_size = len(unfold[0]) + len(unfold_locale[0]) print("#define UNFOLD1_TABLE_SIZE\t%d" % int(unfold1_table_size * 1.2)) unfold2_table_size = len(unfold[1]) + len(unfold_locale[1]) print("#define UNFOLD2_TABLE_SIZE\t%d" % int(unfold2_table_size * 1.5)) unfold3_table_size = len(unfold[2]) print("#define UNFOLD3_TABLE_SIZE\t%d" % int(unfold3_table_size * 1.7)) def main(): filename = 'CaseFolding.txt' if len(sys.argv) > 1: filename = sys.argv[1] print_case_folding_data(filename) if __name__ == '__main__': main() ================================================ FILE: src/Onigmo/tool/convert-name2ctype.sh ================================================ #!/bin/sh # Convert name2ctype.kwd to name2ctype.h using GNU gperf. # # Usage: # convert-name2ctype.sh name2ctype.kwd > name2ctype.h NAME2CTYPE_OPTIONS='-7 -c -j1 -i1 -t -C -P -T -H uniname2ctype_hash -Q uniname2ctype_pool -N uniname2ctype_p' # undef USE_UNICODE_PROPERTIES sed '/^#ifdef USE_UNICODE_PROPERTIES/,/^#endif/d' $1 | gperf ${NAME2CTYPE_OPTIONS} > name2ctype-1.h # define USE_UNICODE_PROPERTIES sed '/^\(#ifdef USE_UNICODE_PROPERTIES\|#endif\)/d' $1 | gperf ${NAME2CTYPE_OPTIONS} > name2ctype-2.h # merge them diff -DUSE_UNICODE_PROPERTIES name2ctype-1.h name2ctype-2.h rm name2ctype-1.h name2ctype-2.h ================================================ FILE: src/Onigmo/tool/enc-unicode.rb ================================================ #!/usr/bin/env ruby # Creates the data structures needed by Onigurma to map Unicode codepoints to # property names and POSIX character classes # # To use this, get UnicodeData.txt, Scripts.txt, PropList.txt, # PropertyAliases.txt, PropertyValueAliases.txt, DerivedCoreProperties.txt, # DerivedAge.txt and Blocks.txt from unicode.org. # (http://unicode.org/Public/UNIDATA/) And run following command. # ruby1.9 tool/enc-unicode.rb data_dir > enc/unicode/name2ctype.kwd # You can get source file for gperf. After this, simply make ruby. unless ARGV.size == 1 $stderr.puts "Usage: #{$0} data_directory" exit(1) end POSIX_NAMES = %w[NEWLINE Alpha Blank Cntrl Digit Graph Lower Print Punct Space Upper XDigit Word Alnum ASCII] def pair_codepoints(codepoints) # We have a sorted Array of codepoints that we wish to partition into # ranges such that the start- and endpoints form an inclusive set of # codepoints with property _property_. Note: It is intended that some ranges # will begin with the value with which they end, e.g. 0x0020 -> 0x0020 codepoints.sort! last_cp = codepoints.first pairs = [[last_cp, nil]] codepoints[1..-1].each do |codepoint| next if last_cp == codepoint # If the current codepoint does not follow directly on from the last # codepoint, the last codepoint represents the end of the current range, # and the current codepoint represents the start of the next range. if last_cp.next != codepoint pairs[-1][-1] = last_cp pairs << [codepoint, nil] end last_cp = codepoint end # The final pair has as its endpoint the last codepoint for this property pairs[-1][-1] = codepoints.last pairs end def parse_unicode_data(file) last_cp = 0 data = {'Any' => (0x0000..0x10ffff).to_a, 'Assigned' => [], 'ASCII' => (0..0x007F).to_a, 'NEWLINE' => [0x0a], 'Cn' => []} beg_cp = nil IO.foreach(file) do |line| fields = line.split(';') cp = fields[0].to_i(16) case fields[1] when /\A<(.*),\s*First>\z/ beg_cp = cp next when /\A<(.*),\s*Last>\z/ cps = (beg_cp..cp).to_a else beg_cp = cp cps = [cp] end # The Cn category represents unassigned characters. These are not listed in # UnicodeData.txt so we must derive them by looking for 'holes' in the range # of listed codepoints. We increment the last codepoint seen and compare it # with the current codepoint. If the current codepoint is less than # last_cp.next we have found a hole, so we add the missing codepoint to the # Cn category. data['Cn'].concat((last_cp.next...beg_cp).to_a) # Assigned - Defined in unicode.c; interpreted as every character in the # Unicode range minus the unassigned characters data['Assigned'].concat(cps) # The third field denotes the 'General' category, e.g. Lu (data[fields[2]] ||= []).concat(cps) # The 'Major' category is the first letter of the 'General' category, e.g. # 'Lu' -> 'L' (data[fields[2][0,1]] ||= []).concat(cps) last_cp = cp end # The last Cn codepoint should be 0x10ffff. If it's not, append the missing # codepoints to Cn and C cn_remainder = (last_cp.next..0x10ffff).to_a data['Cn'] += cn_remainder data['C'] += data['Cn'] # Special case for LC (Cased_Letter). LC = Ll + Lt + Lu data['LC'] = data['Ll'] + data['Lt'] + data['Lu'] # Define General Category properties gcps = data.keys.sort - POSIX_NAMES # Returns General Category Property names and the data [gcps, data] end def define_posix_props(data) # We now derive the character classes (POSIX brackets), e.g. [[:alpha:]] # data['Alpha'] = data['Alphabetic'] data['Upper'] = data['Uppercase'] data['Lower'] = data['Lowercase'] data['Punct'] = data['Punctuation'] data['Digit'] = data['Decimal_Number'] data['XDigit'] = (0x0030..0x0039).to_a + (0x0041..0x0046).to_a + (0x0061..0x0066).to_a data['Alnum'] = data['Alpha'] + data['Digit'] data['Space'] = data['White_Space'] data['Blank'] = data['Space_Separator'] + [0x0009] data['Cntrl'] = data['Cc'] data['Word'] = data['Alpha'] + data['Mark'] + data['Digit'] + data['Connector_Punctuation'] data['Graph'] = data['Any'] - data['Space'] - data['Cntrl'] - data['Surrogate'] - data['Unassigned'] data['Print'] = data['Graph'] + data['Space_Separator'] end def parse_scripts(data, categories) files = [ {:fn => 'DerivedCoreProperties.txt', :title => 'Derived Property'}, {:fn => 'Scripts.txt', :title => 'Script'}, {:fn => 'PropList.txt', :title => 'Binary Property'} ] current = nil cps = [] names = {} files.each do |file| IO.foreach(get_file(file[:fn])) do |line| if /^# Total code points: / =~ line data[current] = cps categories[current] = file[:title] (names[file[:title]] ||= []) << current cps = [] elsif /^([0-9a-fA-F]+)(?:..([0-9a-fA-F]+))?\s*;\s*(\w+)/ =~ line current = $3 $2 ? cps.concat(($1.to_i(16)..$2.to_i(16)).to_a) : cps.push($1.to_i(16)) end end end # All code points not explicitly listed for Script # have the value Unknown (Zzzz). data['Unknown'] = (0..0x10ffff).to_a - data.values_at(*names['Script']).flatten categories['Unknown'] = 'Script' names.values.flatten << 'Unknown' end def parse_aliases(data) kv = {} IO.foreach(get_file('PropertyAliases.txt')) do |line| next unless /^(\w+)\s*; (\w+)/ =~ line data[$1] = data[$2] kv[normalize_propname($1)] = normalize_propname($2) end IO.foreach(get_file('PropertyValueAliases.txt')) do |line| next unless /^(sc|gc)\s*; (\w+)\s*; (\w+)(?:\s*; (\w+))?/ =~ line if $1 == 'gc' data[$3] = data[$2] data[$4] = data[$2] kv[normalize_propname($3)] = normalize_propname($2) kv[normalize_propname($4)] = normalize_propname($2) if $4 else data[$2] = data[$3] data[$4] = data[$3] kv[normalize_propname($2)] = normalize_propname($3) kv[normalize_propname($4)] = normalize_propname($3) if $4 end end kv end # According to Unicode6.0.0/ch03.pdf, Section 3.1, "An update version # never involves any additions to the character repertoire." Versions # in DerivedAge.txt should always be /\d+\.\d+/ def parse_age(data) current = nil last_constname = nil cps = [] ages = [] IO.foreach(get_file('DerivedAge.txt')) do |line| if /^# Total code points: / =~ line constname = constantize_agename(current) # each version matches all previous versions cps.concat(data[last_constname]) if last_constname data[constname] = cps make_const(constname, cps, "Derived Age #{current}") ages << current last_constname = constname cps = [] elsif /^([0-9a-fA-F]+)(?:..([0-9a-fA-F]+))?\s*;\s*(\d+\.\d+)/ =~ line current = $3 $2 ? cps.concat(($1.to_i(16)..$2.to_i(16)).to_a) : cps.push($1.to_i(16)) end end ages end def parse_block(data) current = nil last_constname = nil cps = [] blocks = [] IO.foreach(get_file('Blocks.txt')) do |line| if /^([0-9a-fA-F]+)\.\.([0-9a-fA-F]+);\s*(.*)/ =~ line cps = ($1.to_i(16)..$2.to_i(16)).to_a constname = constantize_blockname($3) data[constname] = cps make_const(constname, cps, "Block") blocks << constname end end # All code points not belonging to any of the named blocks # have the value No_Block. no_block = (0..0x10ffff).to_a - data.values_at(*blocks).flatten constname = constantize_blockname("No_Block") make_const(constname, no_block, "Block") blocks << constname end # shim for Ruby 1.8 unless {}.respond_to?(:key) class Hash alias key index end end $const_cache = {} # make_const(property, pairs, name): Prints a 'static const' structure for a # given property, group of paired codepoints, and a human-friendly name for # the group def make_const(prop, data, name) puts "\n/* '#{prop}': #{name} */" if origprop = $const_cache.key(data) puts "#define CR_#{prop} CR_#{origprop}" else $const_cache[prop] = data pairs = pair_codepoints(data) puts "static const OnigCodePoint CR_#{prop}[] = {" # The first element of the constant is the number of pairs of codepoints puts "\t#{pairs.size}," pairs.each do |pair| pair.map! { |c| c == 0 ? '0x0000' : sprintf("%0#6x", c) } puts "\t#{pair.first}, #{pair.last}," end puts "}; /* CR_#{prop} */" end end def normalize_propname(name) name = name.downcase name.delete!('- _') name end def constantize_agename(name) "Age_#{name.sub(/\./, '_')}" end def constantize_blockname(name) "In_#{name.gsub(/\W/, '_')}" end def get_file(name) File.join(ARGV[0], name) end # Write Data puts '%{' puts '#define long size_t' props, data = parse_unicode_data(get_file('UnicodeData.txt')) categories = {} props.concat parse_scripts(data, categories) aliases = parse_aliases(data) define_posix_props(data) POSIX_NAMES.each do |name| make_const(name, data[name], "[[:#{name}:]]") end print "\n#ifdef USE_UNICODE_PROPERTIES" props.each do |name| category = categories[name] || case name.size when 1 then 'Major Category' when 2 then 'General Category' else '-' end make_const(name, data[name], category) end ages = parse_age(data) blocks = parse_block(data) puts '#endif /* USE_UNICODE_PROPERTIES */' puts(<<'__HEREDOC') static const OnigCodePoint* const CodeRanges[] = { __HEREDOC POSIX_NAMES.each{|name|puts" CR_#{name},"} puts "#ifdef USE_UNICODE_PROPERTIES" props.each{|name| puts" CR_#{name},"} ages.each{|name| puts" CR_#{constantize_agename(name)},"} blocks.each{|name|puts" CR_#{name},"} puts(<<'__HEREDOC') #endif /* USE_UNICODE_PROPERTIES */ }; struct uniname2ctype_struct { int name, ctype; }; static const struct uniname2ctype_struct *uniname2ctype_p(const char *, unsigned int); %} struct uniname2ctype_struct; %% __HEREDOC i = -1 name_to_index = {} POSIX_NAMES.each do |name| i += 1 next if name == 'NEWLINE' name = normalize_propname(name) name_to_index[name] = i puts"%-40s %3d" % [name + ',', i] end puts "#ifdef USE_UNICODE_PROPERTIES" props.each do |name| i += 1 name = normalize_propname(name) name_to_index[name] = i puts "%-40s %3d" % [name + ',', i] end aliases.each_pair do |k, v| next if name_to_index[k] next unless v = name_to_index[v] puts "%-40s %3d" % [k + ',', v] end ages.each do |name| i += 1 name = "age=#{name}" name_to_index[name] = i puts "%-40s %3d" % [name + ',', i] end blocks.each do |name| i += 1 name = normalize_propname(name) name_to_index[name] = i puts "%-40s %3d" % [name + ',', i] end puts(<<'__HEREDOC') #endif /* USE_UNICODE_PROPERTIES */ %% static int uniname2ctype(const UChar *name, unsigned int len) { const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len); if (p) return p->ctype; return -1; } __HEREDOC ================================================ FILE: src/Onigmo/win32/Makefile ================================================ # Oniguruma Makefile for Win32 product_name = oniguruma # Comment out the next line, if you don't want to use LTCG. USE_LTCG = 1 # Enable the next line, if you want to use a .def file. #DEFFILE = onig.def CPPFLAGS = CFLAGS = -O2 -nologo /W3 LDFLAGS = LOADLIBES = ARLIB = lib ARLIB_FLAGS = -nologo ARDLL = cl ARDLL_FLAGS = -nologo -LD $(LINKFLAGS) -dll LINKFLAGS = -link -incremental:no -pdb:none INSTALL = install -c CP = copy CC = cl RC = rc DEFS = -DHAVE_CONFIG_H -DNOT_RUBY -DEXPORT RUBYDIR = .. PYTHON = python # Command string to get the version of cl.exe _MSC_VER = [for /f %i in ('cmd /c "(echo _MSC_VER>mscver.c) && ($(CC) /EP mscver.c 2>nul) && del mscver.c"') do @exit %i] !if DEFINED(USE_LTCG) && $(USE_LTCG) # Use LTCG (Link Time Code Generation). # Check if cl.exe is newer than VC++ 7.0 (_MSC_VER >= 1300). !if $(_MSC_VER) >= 1300 CFLAGS = $(CFLAGS) -GL ARLIB_FLAGS = $(ARLIB_FLAGS) -LTCG ARDLL_FLAGS = $(ARDLL_FLAGS) -LTCG !endif !endif !ifdef DEFFILE # Use a .def file to export APIs. CFLAGS = $(CFLAGS) /DONIG_EXTERN=extern ARDLL_FLAGS = $(ARDLL_FLAGS) -def:$(DEFFILE) !endif subdirs = libbase = onig libname = $(libbase)_s.lib dllname = $(libbase).dll dlllib = $(libbase).lib onigheaders = oniguruma.h regint.h regparse.h regenc.h st.h posixheaders = onigposix.h headers = $(posixheaders) $(onigheaders) onigobjs = reggnu.obj regerror.obj regparse.obj regext.obj regcomp.obj \ regexec.obj regenc.obj regsyntax.obj regtrav.obj \ regversion.obj st.obj posixobjs = regposix.obj regposerr.obj libobjs = $(onigobjs) $(posixobjs) jp_objs = $(encdir)\euc_jp.obj $(encdir)\sjis.obj $(encdir)\cp932.obj iso8859_objs = $(encdir)\iso8859_1.obj $(encdir)\iso8859_2.obj \ $(encdir)\iso8859_3.obj $(encdir)\iso8859_4.obj \ $(encdir)\iso8859_5.obj $(encdir)\iso8859_6.obj \ $(encdir)\iso8859_7.obj $(encdir)\iso8859_8.obj \ $(encdir)\iso8859_9.obj $(encdir)\iso8859_10.obj \ $(encdir)\iso8859_11.obj $(encdir)\iso8859_13.obj \ $(encdir)\iso8859_14.obj $(encdir)\iso8859_15.obj \ $(encdir)\iso8859_16.obj encobjs = $(encdir)\ascii.obj $(encdir)\utf8.obj \ $(encdir)\unicode.obj \ $(encdir)\utf16_be.obj $(encdir)\utf16_le.obj \ $(encdir)\utf32_be.obj $(encdir)\utf32_le.obj \ $(jp_objs) $(iso8859_objs) \ $(encdir)\euc_tw.obj $(encdir)\euc_kr.obj $(encdir)\big5.obj \ $(encdir)\gb18030.obj \ $(encdir)\koi8_r.obj \ $(encdir)\cp1251.obj # $(encdir)\koi8.obj resobj = win32\onig.res onigsources = regerror.c regparse.c regext.c regcomp.c regexec.c regenc.c \ regsyntax.c regtrav.c regversion.c reggnu.c st.c posixsources = regposix.c regposerr.c libsources = $(posixsources) $(onigsources) rubysources = $(onigsources) encdir = enc patchfiles = re.c.168.patch re.c.181.patch distfiles = README COPYING HISTORY \ Makefile.in configure.in config.h.in configure \ $(headers) $(libsources) $(patchfiles) \ test.rb testconv.rb testc = testc testcu = testu testp = testp makeargs = $(MFLAGS) CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' CC='$(CC)' .SUFFIXES: .SUFFIXES: .obj .c .h .ps .dvi .info .texinfo .res .rc !ifdef NOBatch .c.obj: $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) /I. /I.. /Fo$@ /c $< !else # batch-mode inference rules .c.obj:: $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) /I. /I.. /Fo.\ /c $< {$(encdir)\}.c{$(encdir)\}.obj:: $(CC) $(CFLAGS) $(CPPFLAGS) $(DEFS) /I. /I.. /Fo$(encdir)\ /c $< !endif .rc.res: $(RC) /Fo$@ $< # targets default: all setup: $(CP) win32\config.h config.h $(CP) win32\testc.c testc.c all: $(libname) $(dllname) $(libname): $(libobjs) $(encobjs) $(ARLIB) $(ARLIB_FLAGS) -out:$@ $(libobjs) $(encobjs) $(dllname): $(libobjs) $(encobjs) $(resobj) $(DEFFILE) $(ARDLL) $(libobjs) $(encobjs) $(resobj) -Fe$@ $(ARDLL_FLAGS) regparse.obj: regparse.c $(onigheaders) config.h st.h regext.obj: regext.c $(onigheaders) config.h regtrav.obj: regtrav.c $(onigheaders) config.h regcomp.obj: regcomp.c $(onigheaders) config.h regexec.obj: regexec.c regint.h regenc.h oniguruma.h config.h reggnu.obj: reggnu.c regint.h regenc.h oniguruma.h config.h oniggnu.h regerror.obj: regerror.c regint.h regenc.h oniguruma.h config.h regenc.obj: regenc.c regint.h regenc.h oniguruma.h config.h regsyntax.obj: regsyntax.c regint.h regenc.h oniguruma.h config.h regversion.obj: regversion.c oniguruma.h config.h regposix.obj: regposix.c $(posixheaders) oniguruma.h config.h regposerr.obj: regposerr.c $(posixheaders) config.h st.obj: st.c regint.h oniguruma.h config.h st.h $(encdir)\ascii.obj: $(encdir)\ascii.c regenc.h config.h $(encdir)\unicode.obj: $(encdir)\unicode.c regint.h regenc.h config.h $(encdir)\unicode\casefold.h $(encdir)\unicode\name2ctype.h $(encdir)\utf8.obj: $(encdir)\utf8.c regenc.h config.h $(encdir)\utf16_be.obj: $(encdir)\utf16_be.c regenc.h config.h $(encdir)\utf16_le.obj: $(encdir)\utf16_le.c regenc.h config.h $(encdir)\utf32_be.obj: $(encdir)\utf32_be.c regenc.h config.h $(encdir)\utf32_le.obj: $(encdir)\utf32_le.c regenc.h config.h $(encdir)\euc_jp.obj: $(encdir)\euc_jp.c regenc.h config.h $(encdir)\euc_tw.obj: $(encdir)\euc_tw.c regenc.h config.h $(encdir)\euc_kr.obj: $(encdir)\euc_kr.c regenc.h config.h $(encdir)\sjis.obj: $(encdir)\sjis.c regenc.h config.h $(encdir)\cp932.obj: $(encdir)\cp932.c $(encdir)\sjis.c regenc.h config.h $(encdir)\iso8859_1.obj: $(encdir)\iso8859_1.c regenc.h config.h $(encdir)\iso8859_2.obj: $(encdir)\iso8859_2.c regenc.h config.h $(encdir)\iso8859_3.obj: $(encdir)\iso8859_3.c regenc.h config.h $(encdir)\iso8859_4.obj: $(encdir)\iso8859_4.c regenc.h config.h $(encdir)\iso8859_5.obj: $(encdir)\iso8859_5.c regenc.h config.h $(encdir)\iso8859_6.obj: $(encdir)\iso8859_6.c regenc.h config.h $(encdir)\iso8859_7.obj: $(encdir)\iso8859_7.c regenc.h config.h $(encdir)\iso8859_8.obj: $(encdir)\iso8859_8.c regenc.h config.h $(encdir)\iso8859_9.obj: $(encdir)\iso8859_9.c regenc.h config.h $(encdir)\iso8859_10.obj: $(encdir)\iso8859_10.c regenc.h config.h $(encdir)\iso8859_11.obj: $(encdir)\iso8859_11.c regenc.h config.h $(encdir)\iso8859_13.obj: $(encdir)\iso8859_13.c regenc.h config.h $(encdir)\iso8859_14.obj: $(encdir)\iso8859_14.c regenc.h config.h $(encdir)\iso8859_15.obj: $(encdir)\iso8859_15.c regenc.h config.h $(encdir)\iso8859_16.obj: $(encdir)\iso8859_16.c regenc.h config.h $(encdir)\koi8.obj: $(encdir)\koi8.c regenc.h config.h $(encdir)\koi8_r.obj: $(encdir)\koi8_r.c regenc.h config.h $(encdir)\cp1251.obj: $(encdir)\cp1251.c regenc.h config.h $(encdir)\big5.obj: $(encdir)\big5.c regenc.h config.h $(encdir)\gb18030.obj: $(encdir)\gb18030.c regenc.h config.h win32\onig.res: win32\onig.rc # Ruby test rtest: $(RUBYDIR)\win32\ruby -w -Ke test.rb # C library test ctest: $(testc) .\$(testc) # POSIX C library test ptest: $(testp) .\$(testp) $(testc): $(testc).c $(libname) $(CC) -nologo -o $(testc) -DONIG_EXTERN=extern $(testc).c $(libname) $(testp): $(testc).c $(dlllib) $(CC) -nologo -DPOSIX_TEST -o $(testp) $(testc).c $(dlllib) #$(testc)u.c: test.rb testconvu.rb # ruby -Ke testconvu.rb test.rb > $@ $(testcu): $(testcu).c $(libname) $(CC) -nologo -o $(testcu) -DONIG_EXTERN=extern $(testcu).c $(libname) $(libbase).def: win32\makedef.py oniguruma.h regenc.h oniggnu.h onigposix.h $(PYTHON) win32\makedef.py > $@ clean: del *.obj $(encdir)\*.obj *.lib *.exp *.dll $(testp).exe $(testc).exe $(testc).obj $(testcu).exe $(testcu).obj win32\*.res # backup file suffix SORIG = ruby_orig # ruby 1.9 source update 19: $(CP) regerror.c $(RUBYDIR) $(CP) regparse.c $(RUBYDIR) $(CP) regcomp.c $(RUBYDIR) $(CP) regexec.c $(RUBYDIR) $(CP) regenc.c $(RUBYDIR) $(CP) regint.h $(RUBYDIR) $(CP) regparse.h $(RUBYDIR) $(CP) regenc.h $(RUBYDIR) $(CP) oniguruma.h $(RUBYDIR) $(CP) enc\ascii.c $(RUBYDIR) $(CP) enc\utf8.c $(RUBYDIR) $(CP) enc\euc_jp.c $(RUBYDIR) $(CP) enc\sjis.c $(RUBYDIR) $(CP) enc\unicode.c $(RUBYDIR) samples: all $(CC) $(CFLAGS) -I. -o simple sample\simple.c $(dlllib) $(CC) $(CFLAGS) -I. -o posix sample\posix.c $(dlllib) $(CC) $(CFLAGS) -I. -o names sample\names.c $(dlllib) $(CC) $(CFLAGS) -I. -o listcap sample\listcap.c $(dlllib) $(CC) $(CFLAGS) -I. -o sql sample\sql.c $(dlllib) $(CC) $(CFLAGS) -I. -o encode sample\encode.c $(dlllib) $(CC) $(CFLAGS) -I. -o syntax sample\syntax.c $(dlllib) $(CC) $(CFLAGS) -I. -o crnl sample\crnl.c $(dlllib) ================================================ FILE: src/Onigmo/win32/config.h ================================================ #define STDC_HEADERS 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRING_H 1 #define HAVE_MEMORY_H 1 #define HAVE_FLOAT_H 1 #define HAVE_OFF_T 1 #define SIZEOF_INT 4 #define SIZEOF_SHORT 2 #define SIZEOF_LONG 4 #define SIZEOF_LONG_LONG 0 #define SIZEOF___INT64 8 #define SIZEOF_OFF_T 4 #define SIZEOF_VOIDP 4 #define SIZEOF_FLOAT 4 #define SIZEOF_DOUBLE 8 #define HAVE_PROTOTYPES 1 #define TOKEN_PASTE(x,y) x##y #define HAVE_STDARG_PROTOTYPES 1 #ifndef NORETURN #if _MSC_VER > 1100 #define NORETURN(x) __declspec(noreturn) x #else #define NORETURN(x) x #endif #endif #define HAVE_DECL_SYS_NERR 1 #define HAVE_LIMITS_H 1 #define HAVE_FCNTL_H 1 #define HAVE_SYS_UTIME_H 1 #if _MSC_VER >= 1600 #define HAVE_STDINT_H 1 #endif #define uid_t int #define gid_t int #define HAVE_STRUCT_STAT_ST_RDEV 1 #define HAVE_ST_RDEV 1 #define GETGROUPS_T int #define RETSIGTYPE void #define HAVE_ALLOCA 1 #define HAVE_DUP2 1 #define HAVE_MEMCMP 1 #define HAVE_MEMMOVE 1 #define HAVE_MKDIR 1 #define HAVE_STRCASECMP 1 #define HAVE_STRNCASECMP 1 #define HAVE_STRERROR 1 #define HAVE_STRFTIME 1 #define HAVE_STRCHR 1 #define HAVE_STRSTR 1 #define HAVE_STRTOD 1 #define HAVE_STRTOL 1 #define HAVE_STRTOUL 1 #define HAVE_FLOCK 1 #define HAVE_VSNPRINTF 1 #define HAVE_FINITE 1 #define HAVE_FMOD 1 #define HAVE_FREXP 1 #define HAVE_HYPOT 1 #define HAVE_MODF 1 #define HAVE_WAITPID 1 #define HAVE_CHSIZE 1 #define HAVE_TIMES 1 #define HAVE__SETJMP 1 #define HAVE_TELLDIR 1 #define HAVE_SEEKDIR 1 #define HAVE_MKTIME 1 #define HAVE_COSH 1 #define HAVE_SINH 1 #define HAVE_TANH 1 #define HAVE_EXECVE 1 #define HAVE_TZNAME 1 #define HAVE_DAYLIGHT 1 #define SETPGRP_VOID 1 #define inline __inline #define NEED_IO_SEEK_BETWEEN_RW 1 #define RSHIFT(x,y) ((x)>>(int)y) #define FILE_COUNT _cnt #define FILE_READPTR _ptr #define DEFAULT_KCODE KCODE_NONE #define DLEXT ".so" #define DLEXT2 ".dll" ================================================ FILE: src/Onigmo/win32/makedef.py ================================================ #!/usr/bin/env python from __future__ import print_function import re header_files = ( "oniguruma.h", "regenc.h", "oniggnu.h", "onigposix.h" ) exclude_symbols = ( "OnigEncodingKOI8", # USE_UPPER_CASE_TABLE "OnigEncAsciiToUpperCaseTable", "OnigEncISO_8859_1_ToUpperCaseTable", # USE_RECOMPILE_API "onig_recompile", "onig_recompile_deluxe", "re_recompile_pattern", # USE_VARIABLE_META_CHARS #"onig_set_meta_char", # USE_CAPTURE_HISTORY #"onig_get_capture_tree", ) symbols = set() rx1 = re.compile("(ONIG_EXTERN.*)$") rx2 = re.compile(r"(\w+)( +PV?_\(\(.*\)\)|\[.*\])?;\s*(/\*.*\*/)?$") for filename in header_files: with open(filename, "r") as f: while True: line = f.readline() if not line: break m = rx1.match(line) if not m: continue s = m.group(1) if s[-1] != ';': s += ' ' + f.readline() m2 = rx2.search(s) if m2 and (not m2.group(1) in exclude_symbols): symbols.add(m2.group(1)) print('EXPORTS') for s in sorted(symbols): print('\t' + s) ================================================ FILE: src/Onigmo/win32/onig.rc ================================================ /********************************************************************** onig.rc - Onigmo (Oniguruma-mod) (regular expression library) **********************************************************************/ /*- * Copyright (c) 2011-2012 K.Takata * 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. */ #include #include "oniguruma.h" #define TOSTR_(a) #a #define ONIG_VERSION_TOSTR_(a,b,c) \ TOSTR_(a) "." TOSTR_(b) "." TOSTR_(c) #define ONIG_VERSION_STRING \ ONIG_VERSION_TOSTR_(ONIGURUMA_VERSION_MAJOR, ONIGURUMA_VERSION_MINOR, ONIGURUMA_VERSION_TEENY) ///////////////////////////////////////////////////////////////////////////// // English resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION ONIGURUMA_VERSION_MAJOR,ONIGURUMA_VERSION_MINOR,ONIGURUMA_VERSION_TEENY,0 PRODUCTVERSION ONIGURUMA_VERSION_MAJOR,ONIGURUMA_VERSION_MINOR,ONIGURUMA_VERSION_TEENY,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "Comments", "\0" VALUE "CompanyName", " \0" VALUE "FileDescription", "Onigmo (Oniguruma-mod) (regular expression library)\0" VALUE "FileVersion", ONIG_VERSION_STRING "\0" VALUE "InternalName", "onig.dll\0" VALUE "LegalCopyright", "Copyright (C) 2002-2009 K.Kosako, 2011-2012 K.Takata\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "onig.dll\0" VALUE "PrivateBuild", "\0" VALUE "ProductName", "Onigmo (Oniguruma-mod)\0" VALUE "ProductVersion", ONIG_VERSION_STRING "\0" VALUE "SpecialBuild", "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0409, 1200 END END #endif // English resources ///////////////////////////////////////////////////////////////////////////// ================================================ FILE: src/Onigmo/win32/testc.c ================================================ /* * This program was generated by testconv.rb. */ #include "config.h" #ifdef ONIG_ESCAPE_UCHAR_COLLISION #undef ONIG_ESCAPE_UCHAR_COLLISION #endif #include #ifdef POSIX_TEST #include "onigposix.h" #else #include "oniguruma.h" #endif #ifdef HAVE_STRING_H # include #else # include #endif #define SLEN(s) strlen(s) static int nsucc = 0; static int nfail = 0; static int nerror = 0; static FILE* err_file; #ifndef POSIX_TEST static OnigRegion* region; #endif static void xx(char* pattern, char* str, int from, int to, int mem, int not) { OnigPosition r; #ifdef POSIX_TEST regex_t reg; char buf[200]; regmatch_t pmatch[25]; r = regcomp(®, pattern, REG_EXTENDED | REG_NEWLINE); if (r) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } r = regexec(®, str, reg.re_nsub + 1, pmatch, 0); if (r != 0 && r != REG_NOMATCH) { regerror(r, ®, buf, sizeof(buf)); fprintf(err_file, "ERROR: %s\n", buf); nerror++; return ; } if (r == REG_NOMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); nfail++; } else { if (pmatch[mem].rm_so == from && pmatch[mem].rm_eo == to) { fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, from, to, pmatch[mem].rm_so, pmatch[mem].rm_eo); nfail++; } } } regfree(®); #else regex_t* reg; OnigErrorInfo einfo; OnigSyntaxType syn = *ONIG_SYNTAX_DEFAULT; OnigIterator it = {onig_default_charat, str}; /* ONIG_OPTION_OFF(syn.options, ONIG_OPTION_ASCII_RANGE); */ r = onig_new(®, (UChar* )pattern, (UChar* )(pattern + SLEN(pattern)), ONIG_OPTION_DEFAULT, ONIG_ENCODING_SJIS, &syn, &einfo); if (r) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r, &einfo); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } r = onig_search(&it, reg, 0, SLEN(str), 0, SLEN(str), region, ONIG_OPTION_NONE); if (r < ONIG_MISMATCH) { char s[ONIG_MAX_ERROR_MESSAGE_LEN]; onig_error_code_to_str((UChar* )s, r); fprintf(err_file, "ERROR: %s\n", s); nerror++; return ; } if (r == ONIG_MISMATCH) { if (not) { fprintf(stdout, "OK(N): /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s'\n", pattern, str); nfail++; } } else { if (not) { fprintf(stdout, "FAIL(N): /%s/ '%s'\n", pattern, str); nfail++; } else { if (region->beg[mem] == from && region->end[mem] == to) { fprintf(stdout, "OK: /%s/ '%s'\n", pattern, str); nsucc++; } else { fprintf(stdout, "FAIL: /%s/ '%s' %d-%d : %d-%d\n", pattern, str, from, to, region->beg[mem], region->end[mem]); nfail++; } } } onig_free(reg); #endif } static void x2(char* pattern, char* str, int from, int to) { xx(pattern, str, from, to, 0, 0); } static void x3(char* pattern, char* str, int from, int to, int mem) { xx(pattern, str, from, to, mem, 0); } static void n(char* pattern, char* str) { xx(pattern, str, 0, 0, 0, 1); } extern int main(int argc, char* argv[]) { err_file = stdout; #ifdef POSIX_TEST reg_set_encoding(REG_POSIX_ENCODING_SJIS); #else region = onig_region_new(); #endif x2("", "", 0, 0); x2("^", "", 0, 0); x2("$", "", 0, 0); x2("\\G", "", 0, 0); x2("\\A", "", 0, 0); x2("\\Z", "", 0, 0); x2("\\z", "", 0, 0); x2("^$", "", 0, 0); x2("\\ca", "\001", 0, 1); x2("\\C-b", "\002", 0, 1); x2("\\c\\\\", "\034", 0, 1); x2("q[\\c\\\\]", "q\034", 0, 2); x2("", "a", 0, 0); x2("a", "a", 0, 1); x2("\\x61", "a", 0, 1); x2("aa", "aa", 0, 2); x2("aaa", "aaa", 0, 3); x2("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 35); x2("ab", "ab", 0, 2); x2("b", "ab", 1, 2); x2("bc", "abc", 1, 3); x2("(?i:#RET#)", "#INS##RET#", 5, 10); x2("\\17", "\017", 0, 1); x2("\\x1f", "\x1f", 0, 1); x2("a(?#....\\\\JJJJ)b", "ab", 0, 2); x2("(?x) G (o O(?-x)oO) g L", "GoOoOgLe", 0, 7); x2(".", "a", 0, 1); n(".", ""); x2("..", "ab", 0, 2); x2("\\w", "e", 0, 1); n("\\W", "e"); x2("\\s", " ", 0, 1); x2("\\S", "b", 0, 1); x2("\\d", "4", 0, 1); n("\\D", "4"); x2("\\b", "z ", 0, 0); x2("\\b", " z", 1, 1); x2("\\B", "zz ", 1, 1); x2("\\B", "z ", 2, 2); x2("\\B", " z", 0, 0); x2("[ab]", "b", 0, 1); n("[ab]", "c"); x2("[a-z]", "t", 0, 1); n("[^a]", "a"); x2("[^a]", "\n", 0, 1); x2("[]]", "]", 0, 1); n("[^]]", "]"); x2("[\\^]+", "0^^1", 1, 3); x2("[b-]", "b", 0, 1); x2("[b-]", "-", 0, 1); x2("[\\w]", "z", 0, 1); n("[\\w]", " "); x2("[\\W]", "b$", 1, 2); x2("[\\d]", "5", 0, 1); n("[\\d]", "e"); x2("[\\D]", "t", 0, 1); n("[\\D]", "3"); x2("[\\s]", " ", 0, 1); n("[\\s]", "a"); x2("[\\S]", "b", 0, 1); n("[\\S]", " "); x2("[\\w\\d]", "2", 0, 1); n("[\\w\\d]", " "); x2("[[:upper:]]", "B", 0, 1); x2("[*[:xdigit:]+]", "+", 0, 1); x2("[*[:xdigit:]+]", "GHIKK-9+*", 6, 7); x2("[*[:xdigit:]+]", "-@^+", 3, 4); n("[[:upper]]", "A"); x2("[[:upper]]", ":", 0, 1); x2("[\\044-\\047]", "\046", 0, 1); x2("[\\x5a-\\x5c]", "\x5b", 0, 1); x2("[\\x6A-\\x6D]", "\x6c", 0, 1); n("[\\x6A-\\x6D]", "\x6E"); n("^[0-9A-F]+ 0+ UNDEF ", "75F 00000000 SECT14A notype () External | _rb_apply"); x2("[\\[]", "[", 0, 1); x2("[\\]]", "]", 0, 1); x2("[&]", "&", 0, 1); x2("[[ab]]", "b", 0, 1); x2("[[ab]c]", "c", 0, 1); n("[[^a]]", "a"); n("[^[a]]", "a"); x2("[[ab]&&bc]", "b", 0, 1); n("[[ab]&&bc]", "a"); n("[[ab]&&bc]", "c"); x2("[a-z&&b-y&&c-x]", "w", 0, 1); n("[^a-z&&b-y&&c-x]", "w"); x2("[[^a&&a]&&a-z]", "b", 0, 1); n("[[^a&&a]&&a-z]", "a"); x2("[[^a-z&&bcdef]&&[^c-g]]", "h", 0, 1); n("[[^a-z&&bcdef]&&[^c-g]]", "c"); x2("[^[^abc]&&[^cde]]", "c", 0, 1); x2("[^[^abc]&&[^cde]]", "e", 0, 1); n("[^[^abc]&&[^cde]]", "f"); x2("[a-&&-a]", "-", 0, 1); n("[a\\-&&\\-a]", "&"); n("\\wabc", " abc"); x2("a\\Wbc", "a bc", 0, 4); x2("a.b.c", "aabbc", 0, 5); x2(".\\wb\\W..c", "abb bcc", 0, 7); x2("\\s\\wzzz", " zzzz", 0, 5); x2("aa.b", "aabb", 0, 4); n(".a", "ab"); x2(".a", "aa", 0, 2); x2("^a", "a", 0, 1); x2("^a$", "a", 0, 1); x2("^\\w$", "a", 0, 1); n("^\\w$", " "); x2("^\\wab$", "zab", 0, 3); x2("^\\wabcdef$", "zabcdef", 0, 7); x2("^\\w...def$", "zabcdef", 0, 7); x2("\\w\\w\\s\\Waaa\\d", "aa aaa4", 0, 8); x2("\\A\\Z", "", 0, 0); x2("\\Axyz", "xyz", 0, 3); x2("xyz\\Z", "xyz", 0, 3); x2("xyz\\z", "xyz", 0, 3); x2("a\\Z", "a", 0, 1); x2("\\Gaz", "az", 0, 2); n("\\Gz", "bza"); n("az\\G", "az"); n("az\\A", "az"); n("a\\Az", "az"); x2("\\^\\$", "^$", 0, 2); x2("^x?y", "xy", 0, 2); x2("^(x?y)", "xy", 0, 2); x2("\\w", "_", 0, 1); n("\\W", "_"); x2("(?=z)z", "z", 0, 1); n("(?=z).", "a"); x2("(?!z)a", "a", 0, 1); n("(?!z)a", "z"); x2("(?i:a)", "a", 0, 1); x2("(?i:a)", "A", 0, 1); x2("(?i:A)", "a", 0, 1); n("(?i:A)", "b"); x2("(?i:[A-Z])", "a", 0, 1); x2("(?i:[f-m])", "H", 0, 1); x2("(?i:[f-m])", "h", 0, 1); n("(?i:[f-m])", "e"); x2("(?i:[A-c])", "D", 0, 1); n("(?i:[^a-z])", "A"); n("(?i:[^a-z])", "a"); x2("(?i:[!-k])", "Z", 0, 1); x2("(?i:[!-k])", "7", 0, 1); x2("(?i:[T-}])", "b", 0, 1); x2("(?i:[T-}])", "{", 0, 1); x2("(?i:\\?a)", "?A", 0, 2); x2("(?i:\\*A)", "*a", 0, 2); n(".", "\n"); x2("(?m:.)", "\n", 0, 1); x2("(?m:a.)", "a\n", 0, 2); x2("(?m:.b)", "a\nb", 1, 3); x2(".*abc", "dddabdd\nddabc", 8, 13); x2("(?m:.*abc)", "dddabddabc", 0, 10); n("(?i)(?-i)a", "A"); n("(?i)(?-i:a)", "A"); x2("a?", "", 0, 0); x2("a?", "b", 0, 0); x2("a?", "a", 0, 1); x2("a*", "", 0, 0); x2("a*", "a", 0, 1); x2("a*", "aaa", 0, 3); x2("a*", "baaaa", 0, 0); n("a+", ""); x2("a+", "a", 0, 1); x2("a+", "aaaa", 0, 4); x2("a+", "aabbb", 0, 2); x2("a+", "baaaa", 1, 5); x2(".?", "", 0, 0); x2(".?", "f", 0, 1); x2(".?", "\n", 0, 0); x2(".*", "", 0, 0); x2(".*", "abcde", 0, 5); x2(".+", "z", 0, 1); x2(".+", "zdswer\n", 0, 6); x2("(.*)a\\1f", "babfbac", 0, 4); x2("(.*)a\\1f", "bacbabf", 3, 7); x2("((.*)a\\2f)", "bacbabf", 3, 7); x2("(.*)a\\1f", "baczzzzzz\nbazz\nzzzzbabf", 19, 23); x2("a|b", "a", 0, 1); x2("a|b", "b", 0, 1); x2("|a", "a", 0, 0); x2("(|a)", "a", 0, 0); x2("ab|bc", "ab", 0, 2); x2("ab|bc", "bc", 0, 2); x2("z(?:ab|bc)", "zbc", 0, 3); x2("a(?:ab|bc)c", "aabc", 0, 4); x2("ab|(?:ac|az)", "az", 0, 2); x2("a|b|c", "dc", 1, 2); x2("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "pqr", 0, 2); n("a|b|cd|efg|h|ijk|lmn|o|pq|rstuvwx|yz", "mn"); x2("a|^z", "ba", 1, 2); x2("a|^z", "za", 0, 1); x2("a|\\Gz", "bza", 2, 3); x2("a|\\Gz", "za", 0, 1); x2("a|\\Az", "bza", 2, 3); x2("a|\\Az", "za", 0, 1); x2("a|b\\Z", "ba", 1, 2); x2("a|b\\Z", "b", 0, 1); x2("a|b\\z", "ba", 1, 2); x2("a|b\\z", "b", 0, 1); x2("\\w|\\s", " ", 0, 1); n("\\w|\\w", " "); x2("\\w|%", "%", 0, 1); x2("\\w|[&$]", "&", 0, 1); x2("[b-d]|[^e-z]", "a", 0, 1); x2("(?:a|[c-f])|bz", "dz", 0, 1); x2("(?:a|[c-f])|bz", "bz", 0, 2); x2("abc|(?=zz)..f", "zzf", 0, 3); x2("abc|(?!zz)..f", "abf", 0, 3); x2("(?=za)..a|(?=zz)..a", "zza", 0, 3); n("(?>a|abd)c", "abdc"); x2("(?>abd|a)c", "abdc", 0, 4); x2("a?|b", "a", 0, 1); x2("a?|b", "b", 0, 0); x2("a?|b", "", 0, 0); x2("a*|b", "aa", 0, 2); x2("a*|b*", "ba", 0, 0); x2("a*|b*", "ab", 0, 1); x2("a+|b*", "", 0, 0); x2("a+|b*", "bbb", 0, 3); x2("a+|b*", "abbb", 0, 1); n("a+|b+", ""); x2("(a|b)?", "b", 0, 1); x2("(a|b)*", "ba", 0, 2); x2("(a|b)+", "bab", 0, 3); x2("(ab|ca)+", "caabbc", 0, 4); x2("(ab|ca)+", "aabca", 1, 5); x2("(ab|ca)+", "abzca", 0, 2); x2("(a|bab)+", "ababa", 0, 5); x2("(a|bab)+", "ba", 1, 2); x2("(a|bab)+", "baaaba", 1, 4); x2("(?:a|b)(?:a|b)", "ab", 0, 2); x2("(?:a*|b*)(?:a*|b*)", "aaabbb", 0, 3); x2("(?:a*|b*)(?:a+|b+)", "aaabbb", 0, 6); x2("(?:a+|b+){2}", "aaabbb", 0, 6); x2("h{0,}", "hhhh", 0, 4); x2("(?:a+|b+){1,2}", "aaabbb", 0, 6); n("ax{2}*a", "0axxxa1"); n("a.{0,2}a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXa0"); n("a.{0,2}?a", "0aXXXXa0"); x2("^a{2,}?a$", "aaa", 0, 3); x2("^[a-z]{2,}?$", "aaa", 0, 3); x2("(?:a+|\\Ab*)cc", "cc", 0, 2); n("(?:a+|\\Ab*)cc", "abcc"); x2("(?:^a+|b+)*c", "aabbbabc", 6, 8); x2("(?:^a+|b+)*c", "aabbbbc", 0, 7); x2("a|(?i)c", "C", 0, 1); x2("(?i)c|a", "C", 0, 1); x2("(?i)c|a", "A", 0, 1); x2("(?i:c)|a", "C", 0, 1); n("(?i:c)|a", "A"); x2("[abc]?", "abc", 0, 1); x2("[abc]*", "abc", 0, 3); x2("[^abc]*", "abc", 0, 0); n("[^abc]+", "abc"); x2("a?\?", "aaa", 0, 0); x2("ba?\?b", "bab", 0, 3); x2("a*?", "aaa", 0, 0); x2("ba*?", "baa", 0, 1); x2("ba*?b", "baab", 0, 4); x2("a+?", "aaa", 0, 1); x2("ba+?", "baa", 0, 2); x2("ba+?b", "baab", 0, 4); x2("(?:a?)?\?", "a", 0, 0); x2("(?:a?\?)?", "a", 0, 0); x2("(?:a?)+?", "aaa", 0, 1); x2("(?:a+)?\?", "aaa", 0, 0); x2("(?:a+)?\?b", "aaab", 0, 4); x2("(?:ab)?{2}", "", 0, 0); x2("(?:ab)?{2}", "ababa", 0, 4); x2("(?:ab)*{0}", "ababa", 0, 0); x2("(?:ab){3,}", "abababab", 0, 8); n("(?:ab){3,}", "abab"); x2("(?:ab){2,4}", "ababab", 0, 6); x2("(?:ab){2,4}", "ababababab", 0, 8); x2("(?:ab){2,4}?", "ababababab", 0, 4); x2("(?:ab){,}", "ab{,}", 0, 5); x2("(?:abc)+?{2}", "abcabcabc", 0, 6); x2("(?:X*)(?i:xa)", "XXXa", 0, 4); x2("(d+)([^abc]z)", "dddz", 0, 4); x2("([^abc]*)([^abc]z)", "dddz", 0, 4); x2("(\\w+)(\\wz)", "dddz", 0, 4); x3("(a)", "a", 0, 1, 1); x3("(ab)", "ab", 0, 2, 1); x2("((ab))", "ab", 0, 2); x3("((ab))", "ab", 0, 2, 1); x3("((ab))", "ab", 0, 2, 2); x3("((((((((((((((((((((ab))))))))))))))))))))", "ab", 0, 2, 20); x3("(ab)(cd)", "abcd", 0, 2, 1); x3("(ab)(cd)", "abcd", 2, 4, 2); x3("()(a)bc(def)ghijk", "abcdefghijk", 3, 6, 3); x3("(()(a)bc(def)ghijk)", "abcdefghijk", 3, 6, 4); x2("(^a)", "a", 0, 1); x3("(a)|(a)", "ba", 1, 2, 1); x3("(^a)|(a)", "ba", 1, 2, 2); x3("(a?)", "aaa", 0, 1, 1); x3("(a*)", "aaa", 0, 3, 1); x3("(a*)", "", 0, 0, 1); x3("(a+)", "aaaaaaa", 0, 7, 1); x3("(a+|b*)", "bbbaa", 0, 3, 1); x3("(a+|b?)", "bbbaa", 0, 1, 1); x3("(abc)?", "abc", 0, 3, 1); x3("(abc)*", "abc", 0, 3, 1); x3("(abc)+", "abc", 0, 3, 1); x3("(xyz|abc)+", "abc", 0, 3, 1); x3("([xyz][abc]|abc)+", "abc", 0, 3, 1); x3("((?i:abc))", "AbC", 0, 3, 1); x2("(abc)(?i:\\1)", "abcABC", 0, 6); x3("((?m:a.c))", "a\nc", 0, 3, 1); x3("((?=az)a)", "azb", 0, 1, 1); x3("abc|(.abd)", "zabd", 0, 4, 1); x2("(?:abc)|(ABC)", "abc", 0, 3); x3("(?i:(abc))|(zzz)", "ABC", 0, 3, 1); x3("a*(.)", "aaaaz", 4, 5, 1); x3("a*?(.)", "aaaaz", 0, 1, 1); x3("a*?(c)", "aaaac", 4, 5, 1); x3("[bcd]a*(.)", "caaaaz", 5, 6, 1); x3("(\\Abb)cc", "bbcc", 0, 2, 1); n("(\\Abb)cc", "zbbcc"); x3("(^bb)cc", "bbcc", 0, 2, 1); n("(^bb)cc", "zbbcc"); x3("cc(bb$)", "ccbb", 2, 4, 1); n("cc(bb$)", "ccbbb"); n("(\\1)", ""); n("\\1(a)", "aa"); n("(a(b)\\1)\\2+", "ababb"); n("(?:(?:\\1|z)(a))+$", "zaa"); x2("(?:(?:\\1|z)(a))+$", "zaaa", 0, 4); x2("(a)(?=\\1)", "aa", 0, 1); n("(a)$|\\1", "az"); x2("(a)\\1", "aa", 0, 2); n("(a)\\1", "ab"); x2("(a?)\\1", "aa", 0, 2); x2("(a?\?)\\1", "aa", 0, 0); x2("(a*)\\1", "aaaaa", 0, 4); x3("(a*)\\1", "aaaaa", 0, 2, 1); x2("a(b*)\\1", "abbbb", 0, 5); x2("a(b*)\\1", "ab", 0, 1); x2("(a*)(b*)\\1\\2", "aaabbaaabb", 0, 10); x2("(a*)(b*)\\2", "aaabbbb", 0, 7); x2("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 8); x3("(((((((a*)b))))))c\\7", "aaabcaaa", 0, 3, 7); x2("(a)(b)(c)\\2\\1\\3", "abcbac", 0, 6); x2("([a-d])\\1", "cc", 0, 2); x2("(\\w\\d\\s)\\1", "f5 f5 ", 0, 6); n("(\\w\\d\\s)\\1", "f5 f5"); x2("(who|[a-c]{3})\\1", "whowho", 0, 6); x2("...(who|[a-c]{3})\\1", "abcwhowho", 0, 9); x2("(who|[a-c]{3})\\1", "cbccbc", 0, 6); x2("(^a)\\1", "aa", 0, 2); n("(^a)\\1", "baa"); n("(a$)\\1", "aa"); n("(ab\\Z)\\1", "ab"); x2("(a*\\Z)\\1", "a", 1, 1); x2(".(a*\\Z)\\1", "ba", 1, 2); x3("(.(abc)\\2)", "zabcabc", 0, 7, 1); x3("(.(..\\d.)\\2)", "z12341234", 0, 9, 1); x2("((?i:az))\\1", "AzAz", 0, 4); n("((?i:az))\\1", "Azaz"); x2("(?<=a)b", "ab", 1, 2); n("(?<=a)b", "bb"); x2("(?<=a|b)b", "bb", 1, 2); x2("(?<=a|bc)b", "bcb", 2, 3); x2("(?<=a|bc)b", "ab", 1, 2); x2("(?<=a|bc||defghij|klmnopq|r)z", "rz", 1, 2); x2("(a)\\g<1>", "aa", 0, 2); x2("(?a)", "a", 0, 1); x2("(?ab)\\g", "abab", 0, 4); x2("(?.zv.)\\k", "azvbazvb", 0, 8); x2("(?<=\\g)|-\\zEND (?XyZ)", "XyZ", 3, 3); x2("(?|a\\g)+", "", 0, 0); x2("(?|\\(\\g\\))+$", "()(())", 0, 6); x3("\\g(?.){0}", "X", 0, 1, 1); x2("\\g(abc|df(?.YZ){2,8}){0}", "XYZ", 0, 3); x2("\\A(?(a\\g)|)\\z", "aaaa", 0, 4); x2("(?|\\g\\g)\\z|\\zEND (?a|(b)\\g)", "bbbbabba", 0, 8); x2("(?\\w+\\sx)a+\\k", " fg xaaaaaaaafg x", 2, 18); x3("(z)()()(?<_9>a)\\g<_9>", "zaa", 2, 3, 1); x2("(.)(((?<_>a)))\\k<_>", "zaa", 0, 3); x2("((?\\d)|(?\\w))(\\k|\\k)", "ff", 0, 2); x2("(?:(?)|(?efg))\\k", "", 0, 0); x2("(?:(?abc)|(?efg))\\k", "abcefgefg", 3, 9); n("(?:(?abc)|(?efg))\\k", "abcefg"); x2("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "a-pyumpyum", 2, 10); x3("(?:(?.)|(?..)|(?...)|(?....)|(?.....)|(?......)|(?.......)|(?........)|(?.........)|(?..........)|(?...........)|(?............)|(?.............)|(?..............))\\k$", "xxxxabcdefghijklmnabcdefghijklmn", 4, 18, 14); x3("(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?)(?aaa)(?)$", "aaa", 0, 3, 16); x2("(?a|\\(\\g\\))", "a", 0, 1); x2("(?a|\\(\\g\\))", "((((((a))))))", 0, 13); x3("(?a|\\(\\g\\))", "((((((((a))))))))", 0, 17, 1); x2("\\g|\\zEND(?.*abc$)", "abcxxxabc", 0, 9); x2("\\g<1>|\\zEND(.a.)", "bac", 0, 3); x3("\\g<_A>\\g<_A>|\\zEND(.a.)(?<_A>.b.)", "xbxyby", 3, 6, 1); x2("\\A(?:\\g|\\g|\\zEND (?a|c\\gc)(?b|d\\gd))$", "cdcbcdc", 0, 7); x2("\\A(?|a\\g)\\z|\\zEND (?\\g)", "aaaa", 0, 4); x2("(?(a|b\\gc){3,5})", "baaaaca", 1, 5); x2("(?(a|b\\gc){3,5})", "baaaacaaaaa", 0, 10); x2("(?\\(([^\\(\\)]++|\\g)*+\\))", "((a))", 0, 5); x2("()*\\1", "", 0, 0); x2("(?:()|())*\\1\\2", "", 0, 0); x3("(?:\\1a|())*", "a", 0, 0, 1); x2("x((.)*)*x", "0x1x2x3", 1, 6); x2("x((.)*)*x(?i:\\1)\\Z", "0x1x2x1X2", 1, 9); x2("(?:()|()|()|()|()|())*\\2\\5", "", 0, 0); x2("(?:()|()|()|(x)|()|())*\\2b\\5", "b", 0, 1); x2("\\xED\\xF2", "\xed\xf2", 0, 2); x2("", "", 0, 0); x2("", "", 0, 2); n("", ""); x2("", "", 0, 4); x2("", "", 0, 6); x2("", "", 0, 70); x2("", "", 2, 4); x2("", "", 2, 6); x2("\\xca\\xb8", "\xca\xb8", 0, 2); x2(".", "", 0, 2); x2("..", "", 0, 4); x2("(?u)\\w", "", 0, 2); n("(?u)\\W", ""); x2("(?u)[\\W]", "$", 2, 3); x2("\\S", "", 0, 2); x2("\\S", "", 0, 2); x2("\\b", "C ", 0, 0); x2("\\b", " ", 1, 1); x2("\\B", " ", 2, 2); x2("\\B", " ", 3, 3); x2("\\B", " ", 0, 0); x2("[]", "", 0, 2); n("[Ȃ]", ""); x2("[-]", "", 0, 2); n("[^]", ""); x2("(?u)[\\w]", "", 0, 2); n("[\\d]", ""); x2("[\\D]", "", 0, 2); n("[\\s]", ""); x2("[\\S]", "", 0, 2); x2("(?u)[\\w\\d]", "", 0, 2); x2("(?u)[\\w\\d]", " ", 3, 5); n("(?u)\\wS", " S"); x2("(?u)S\\W", "S ", 0, 5); x2("..", "", 0, 10); x2("(?u).\\w\\W..", " ", 0, 13); x2("(?u)\\s\\w", " ", 0, 9); x2(".", "", 0, 8); n(".", ""); x2(".", "", 0, 4); x2("^", "", 0, 2); x2("^$", "", 0, 2); x2("(?u)^\\w$", "", 0, 2); x2("(?u)^\\w$", "z", 0, 11); x2("(?u)^\\w...$", "z", 0, 13); x2("(?u)\\w\\w\\s\\W\\d", "a 4", 0, 12); x2("\\A", "", 0, 6); x2("ނ߂\\Z", "ނ߂", 0, 6); x2("\\z", "", 0, 6); x2("\\Z", "\n", 0, 6); x2("\\Gۂ", "ۂ", 0, 4); n("\\G", ""); n("Ƃ\\G", "Ƃ"); n("܂\\A", "܂"); n("\\A", "܂"); x2("(?=)", "", 0, 2); n("(?=).", ""); x2("(?!)", "", 0, 2); n("(?!)", ""); x2("(?i:)", "", 0, 2); x2("(?i:Ԃ)", "Ԃ", 0, 4); n("(?i:)", ""); x2("(?m:.)", "\n", 0, 3); x2("(?m:.)", "\n", 2, 5); x2("?", "", 0, 0); x2("?", "", 0, 0); x2("?", "", 0, 2); x2("*", "", 0, 0); x2("*", "", 0, 2); x2("q*", "qqq", 0, 6); x2("n*", "nnnn", 0, 0); n("R+", ""); x2("+", "", 0, 2); x2("+", "", 0, 8); x2("+", "", 0, 4); x2("+", "", 2, 10); x2(".?", "", 0, 2); x2(".*", "ς҂Ղ", 0, 8); x2(".+", "", 0, 2); x2(".+", "\n", 0, 8); x2("|", "", 0, 2); x2("|", "", 0, 2); x2("|", "", 0, 4); x2("|", "", 0, 4); x2("(?:|)", "", 0, 6); x2("(?:|)", "", 0, 8); x2("|(?:|)", "", 0, 4); x2("||", "", 2, 4); x2("|||||||||‚ĂƂȂ|ʂ", "", 0, 6); n("|||||||||‚ĂƂȂ|ʂ", ""); x2("|^", "Ԃ", 2, 4); x2("|^", "", 0, 2); x2("S|\\G", "ԋS", 4, 6); x2("S|\\G", "ԋS", 0, 2); x2("S|\\A", "bԋS", 3, 5); x2("S|\\A", "", 0, 2); x2("S|\\Z", "ԋS", 2, 4); x2("S|\\Z", "", 0, 2); x2("S|\\Z", "\n", 0, 2); x2("S|\\z", "ԋS", 2, 4); x2("S|\\z", "", 0, 2); x2("(?u)\\w|\\s", "", 0, 2); x2("(?u)\\w|%", "%", 0, 1); x2("(?u)\\w|[&$]", "&", 0, 2); x2("[-]", "", 0, 2); x2("[-]|[^-]", "", 0, 2); x2("[-]|[^-]", "", 0, 2); x2("[^]", "\n", 0, 1); x2("(?:|[-])|", "", 0, 2); x2("(?:|[-])|", "", 0, 4); x2("|(?=)..", "", 0, 6); x2("|(?!)..", "", 0, 6); x2("(?=)..|(?=)..", "", 0, 6); x2("(?<=|)", "", 4, 6); n("(?>|)", ""); x2("(?>|)", "", 0, 8); x2("?|", "", 0, 2); x2("?|", "", 0, 0); x2("?|", "", 0, 0); x2("*|", "", 0, 4); x2("*|*", "", 0, 0); x2("*|*", "", 0, 2); x2("[a]*|*", "a", 0, 3); x2("+|*", "", 0, 0); x2("+|*", "", 0, 6); x2("+|*", "", 0, 2); x2("+|*", "a", 0, 0); n("+|+", ""); x2("(|)?", "", 0, 2); x2("(|)*", "", 0, 4); x2("(|)+", "", 0, 6); x2("(|)+", "", 0, 8); x2("(|)+", "", 4, 12); x2("(|)+", "", 2, 10); x2("(|)+", "", 0, 4); x2("(|)+", "$$zzzz", 6, 10); x2("(|)+", "", 0, 10); x2("(|)+", "", 2, 4); x2("(|)+", "", 2, 8); x2("(?:|)(?:|)", "", 0, 4); x2("(?:*|*)(?:*|*)", "", 0, 6); x2("(?:*|*)(?:+|+)", "", 0, 12); x2("(?:+|+){2}", "", 0, 12); x2("(?:+|+){1,2}", "", 0, 12); x2("(?:+|\\A*)", "", 0, 4); n("(?:+|\\A*)", ""); x2("(?:^+|+)*", "", 12, 16); x2("(?:^+|+)*", "", 0, 14); x2("{0,}", "", 0, 8); x2("|(?i)c", "C", 0, 1); x2("(?i)c|", "C", 0, 1); x2("(?i:)|a", "a", 0, 1); n("(?i:)|a", "A"); x2("[]?", "", 0, 2); x2("[]*", "", 0, 6); x2("[^]*", "", 0, 0); n("[^]+", ""); x2("?\?", "", 0, 0); x2("?\?", "", 0, 6); x2("*?", "", 0, 0); x2("*?", "", 0, 2); x2("*?", "", 0, 8); x2("+?", "", 0, 2); x2("+?", "", 0, 4); x2("+?", "", 0, 8); x2("(?:V?)?\?", "V", 0, 0); x2("(?:V?\?)?", "V", 0, 0); x2("(?:?)+?", "", 0, 2); x2("(?:+)?\?", "", 0, 0); x2("(?:+)?\?", "ᑚ", 0, 8); x2("(?:)?{2}", "", 0, 0); x2("(?:S)?{2}", "SԋSԋS", 0, 8); x2("(?:S)*{0}", "SԋSԋS", 0, 0); x2("(?:S){3,}", "SԋSԋSԋS", 0, 16); n("(?:S){3,}", "SԋS"); x2("(?:S){2,4}", "SԋSԋS", 0, 12); x2("(?:S){2,4}", "SԋSԋSԋSԋS", 0, 16); x2("(?:S){2,4}?", "SԋSԋSԋSԋS", 0, 8); x2("(?:S){,}", "S{,}", 0, 7); x2("(?:)+?{2}", "", 0, 12); x3("()", "", 0, 2, 1); x3("(ΐ)", "ΐ", 0, 4, 1); x2("(())", "", 0, 4); x3("(())", "", 0, 4, 1); x3("(())", "", 0, 4, 2); x3("((((((((((((((((((((ʎq))))))))))))))))))))", "ʎq", 0, 4, 20); x3("()()", "", 0, 4, 1); x3("()()", "", 4, 8, 2); x3("()()()", "", 6, 12, 3); x3("(()()())", "", 6, 12, 4); x3(".*(tH)E}(()V^)C", "tHE}V^C", 10, 18, 2); x2("(^)", "", 0, 2); x3("()|()", "", 2, 4, 1); x3("(^)|()", "", 2, 4, 2); x3("(?)", "", 0, 2, 1); x3("(*)", "܂܂", 0, 6, 1); x3("(*)", "", 0, 0, 1); x3("(+)", "", 0, 14, 1); x3("(+|*)", "ӂӂӂւ", 0, 6, 1); x3("(+|?)", "", 0, 2, 1); x3("()?", "", 0, 6, 1); x3("()*", "", 0, 6, 1); x3("()+", "", 0, 6, 1); x3("(|)+", "", 0, 6, 1); x3("([Ȃɂ][]|)+", "", 0, 6, 1); x3("((?i:))", "", 0, 6, 1); x3("((?m:.))", "\n", 0, 5, 1); x3("((?=))", "", 0, 2, 1); x3("|(.)", "񂠂", 0, 8, 1); x3("*(.)", "", 8, 10, 1); x3("*?(.)", "", 0, 2, 1); x3("*?()", "", 8, 10, 1); x3("[]*(.)", "", 10, 12, 1); x3("(\\A)", "", 0, 4, 1); n("(\\A)", "񂢂"); x3("(^)", "", 0, 4, 1); n("(^)", "񂢂"); x3("($)", "", 4, 8, 1); n("($)", ""); x2("()\\1", "", 0, 4); n("()\\1", ""); x2("(?)\\1", "", 0, 4); x2("(?\?)\\1", "", 0, 0); x2("(*)\\1", "", 0, 8); x3("(*)\\1", "", 0, 4, 1); x2("(*)\\1", "", 0, 10); x2("(*)\\1", "", 0, 2); x2("(*)(*)\\1\\2", "", 0, 20); x2("(*)(*)\\2", "", 0, 14); x3("(*)(*)\\2", "", 6, 10, 2); x2("(((((((*)))))))\\7", "ۂۂۂ؂҂ۂۂ", 0, 16); x3("(((((((*)))))))\\7", "ۂۂۂ؂҂ۂۂ", 0, 6, 7); x2("()()()\\2\\1\\3", "͂ЂӂЂ͂", 0, 12); x2("([-])\\1", "", 0, 4); x2("(?u)(\\w\\d\\s)\\1", "5 5 ", 0, 8); n("(?u)(\\w\\d\\s)\\1", "5 5"); x2("(NH|[-]{3})\\1", "NHNH", 0, 8); x2("...(NH|[-]{3})\\1", "aNHNH", 0, 13); x2("(NH|[-]{3})\\1", "", 0, 12); x2("(^)\\1", "", 0, 4); n("(^)\\1", "߂ނ"); n("($)\\1", ""); n("(\\Z)\\1", ""); x2("(*\\Z)\\1", "", 2, 2); x2(".(*\\Z)\\1", "", 2, 4); x3("(.(₢)\\2)", "z₢₢", 0, 13, 1); x3("(.(..\\d.)\\2)", "12341234", 0, 10, 1); x2("((?i:v))\\1", "vv", 0, 10); x2("(?<>|\\(\\g<>\\))", "(((((())))))", 0, 14); x2("\\A(?:\\g<_1>|\\g<]_2>|\\zI (?<_1>|\\g<]_2>)(?<]_2>|F\\g<_1>F))$", "FFݎFF", 0, 26); x2("[[Ђ]]", "", 0, 2); x2("[[]]", "", 0, 2); n("[[^]]", ""); n("[^[]]", ""); x2("[^[^]]", "", 0, 2); x2("[[]&&]", "", 0, 2); n("[[]&&]", ""); n("[[]&&]", ""); x2("[-&&-&&-]", "", 0, 2); n("[^-&&-&&-]", ""); x2("[[^&&]&&-]", "", 0, 2); n("[[^&&]&&-]", ""); x2("[[^-&&]&&[^-]]", "", 0, 2); n("[[^-&&]&&[^-]]", ""); x2("[^[^]&&[^]]", "", 0, 2); x2("[^[^]&&[^]]", "", 0, 2); n("[^[^]&&[^]]", ""); x2("[-&&-]", "-", 0, 1); x2("[^[^a-z]&&[^bcdefg]q-w]", "", 0, 2); x2("[^[^a-z]&&[^bcdefg]g-w]", "f", 0, 1); x2("[^[^a-z]&&[^bcdefg]g-w]", "g", 0, 1); n("[^[^a-z]&&[^bcdefg]g-w]", "2"); x2("ao[W̃_E[h<\\/b>", "ao[W̃_E[h", 0, 32); x2(".o[W̃_E[h<\\/b>", "ao[W̃_E[h", 0, 32); fprintf(stdout, "\nRESULT SUCC: %d, FAIL: %d, ERROR: %d (by Onigmo %s)\n", nsucc, nfail, nerror, onig_version()); #ifndef POSIX_TEST onig_region_free(region, 1); onig_end(); #endif return ((nfail == 0 && nerror == 0) ? 0 : -1); } ================================================ FILE: src/Protocols/Protocol.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PROTOCOL_H #define PROTOCOL_H #pragma once #include class Protocol { public: Protocol(void) = default; virtual ~Protocol(void) = default; QByteArray name() const { return m_name; } protected: QByteArray m_name; }; #endif // PROTOCOL_H ================================================ FILE: src/Protocols/TelnetProtocol.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "TelnetProtocol.h" #include #include #include const char *arrTelnetCmds[] = { "XEOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DM", "BREAK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC" }; const char *arrTelnetOpts[] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP", "COM PORT CONTROL", "SUPPRESS LOCAL ECHO", "START TLS", "KERMIT", "SEND-URL", "FORWARD_X", }; std::string TelnetProtocol::GetCommandName(uchar chTelnetCmd) { if (chTelnetCmd >= TELCMD_XEOF && chTelnetCmd <= TELCMD_IAC) return arrTelnetCmds[chTelnetCmd - TELCMD_XEOF]; std::ostringstream oss; oss << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)chTelnetCmd << "(Unknown Telnet Command)"; return oss.str(); } std::string TelnetProtocol::GetOptionName(uchar chTelnetOption) { if (chTelnetOption >= TELOPT_BINARY && chTelnetOption <= TELOPT_FORWARD_X) { return arrTelnetOpts[chTelnetOption - TELOPT_BINARY];} else if (chTelnetOption == TELOPT_MCCP1) { return "MUD COMPRESSION PROTOCOL (V1)"; } else if (chTelnetOption == TELOPT_MCCP2) { return "MUD COMPRESSION PROTOCOL (V2)"; } else if (chTelnetOption == TELOPT_MSP) { return "MUD SOUND PROTOCOL"; } else if (chTelnetOption == TELOPT_MXP) { return "MUD EXTENSION PROTOCOL";} else if (chTelnetOption == TELOPT_PRAGMA_LOGON) { return "TELOPT PRAGMA LOGON"; } else if (chTelnetOption == TELOPT_SSPI_LOGON) { return "TELOPT SSPI LOGON"; } else if (chTelnetOption == TELOPT_PRAGMA_HEARTBEAT) { return "TELOPT PRAGMA HEARTBEAT"; } else if (chTelnetOption == TELOPT_EXOPL) { return "EXTENDED OPTIONS LIST"; } std::ostringstream oss; oss << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)chTelnetOption << "(Unknown Telnet Option)"; return oss.str(); } TelnetOptionVector &TelnetProtocol::GetOptionVector() { static TelnetOptionVector m_vTelnetOption; static std::once_flag flag; std::call_once(flag, [&]() { m_vTelnetOption.clear(); m_vTelnetOption.resize(TELOPT_INDEX_MAX); m_vTelnetOption[TELOPT_INDEX_NAWS].Init(TELOPT_NAWS, TELNET_CLIENT, TELOPT_STATE_INACTIVE_REQUESTED); m_vTelnetOption[TELOPT_INDEX_TTYPE].Init(TELOPT_TTYPE, TELNET_CLIENT, TELOPT_STATE_INACTIVE_REQUESTED); m_vTelnetOption[TELOPT_INDEX_ECHO].Init(TELOPT_ECHO, TELNET_SERVER, TELOPT_STATE_INACTIVE_REQUESTED); m_vTelnetOption[TELOPT_INDEX_SERVER_SGA].Init(TELOPT_SGA, TELNET_SERVER, TELOPT_STATE_INACTIVE_REQUESTED); m_vTelnetOption[TELOPT_INDEX_CLIENT_SGA].Init(TELOPT_SGA, TELNET_CLIENT, TELOPT_STATE_INACTIVE_REQUESTED); m_vTelnetOption[TELOPT_INDEX_SERVER_BIN].Init(TELOPT_BINARY, TELNET_SERVER, TELOPT_STATE_INACTIVE); m_vTelnetOption[TELOPT_INDEX_CLIENT_BIN].Init(TELOPT_BINARY, TELNET_CLIENT, TELOPT_STATE_INACTIVE); }); return m_vTelnetOption; } TelnetProtocol::TelnetProtocol() { m_name = "Telnet"; } ================================================ FILE: src/Protocols/TelnetProtocol.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef TELNETPROTOCOL_H #define TELNETPROTOCOL_H #pragma once #include #include "Protocol.h" typedef unsigned char uchar; /* TELNET Command Codes: */ constexpr uchar TELCMD_XEOF = 236; /* End of file: EOF is already used */ constexpr uchar TELCMD_SUSP = 237; /* Suspend process */ constexpr uchar TELCMD_ABORT = 238; /* Abort process */ constexpr uchar TELCMD_EOR = 239; /* end of record (transparent mode) */ constexpr uchar TELCMD_SE = 240; /* end sub negotiation */ constexpr uchar TELCMD_NOP = 241; /* nop */ constexpr uchar TELCMD_DM = 242; /* data mark--for connect. cleaning */ constexpr uchar TELCMD_BREAK = 243; /* break */ constexpr uchar TELCMD_IP = 244; /* interrupt process--permanently */ constexpr uchar TELCMD_AO = 245; /* abort output--but let prog finish*/ constexpr uchar TELCMD_AYT = 246; /* are you there */ constexpr uchar TELCMD_EC = 247; /* erase the current character */ constexpr uchar TELCMD_EL = 248; /* erase the current line */ constexpr uchar TELCMD_GA = 249; /* you may reverse the line */ constexpr uchar TELCMD_SB = 250; /* interpret as subnegotiation */ constexpr uchar TELCMD_WILL = 251; /* I will use option */ constexpr uchar TELCMD_WONT = 252; /* I won't use option */ constexpr uchar TELCMD_DO = 253; /* please, you use option */ constexpr uchar TELCMD_DONT = 254; /* you are not to use option */ constexpr uchar TELCMD_IAC = 255; /* interpret as command */ /* The telnet options represented as strings */ constexpr uchar TELOPT_BINARY = 0; // Binary Transmission - RFC 856 constexpr uchar TELOPT_ECHO = 1; // Echo - RFC 857 constexpr uchar TELOPT_RCP = 2; // Reconnection constexpr uchar TELOPT_SGA = 3; // Suppress Go Ahead - RFC 858 constexpr uchar TELOPT_NAMS = 4; // Approx Message Size Negotiation constexpr uchar TELOPT_STATUS = 5; // Status - RFC 859 constexpr uchar TELOPT_TM = 6; // Timing Mark - RFC 860 constexpr uchar TELOPT_RCTE = 7; // Remote controlled transmission and echo - RFC 563,726 constexpr uchar TELOPT_NAOL = 8; // Negotiate about output line width - NIC50005 constexpr uchar TELOPT_NAOP = 9; // Negotiate about output page size - NIC50005 constexpr uchar TELOPT_NAOCRD = 10; // Negotiate about CR disposition - RFC 652 constexpr uchar TELOPT_NAOHTS = 11; // Negotiate about horizontal tabstops - RFC 653 constexpr uchar TELOPT_NAOHTD = 12; // Negotiate about horizontal tab disposition - RFC 654 constexpr uchar TELOPT_NAOFFD = 13; // Negotiate about formfeed disposition - RFC 655 constexpr uchar TELOPT_NAOVTS = 14; // Negotiate about vertical tab stops - RFC 656 constexpr uchar TELOPT_NAOVTD = 15; // Negotiate about vertical tab disposition - RFC 657 constexpr uchar TELOPT_NAOLFD = 16; // Negotiate about output LF disposition - RFC 658 constexpr uchar TELOPT_XASCII = 17; // Extended ascic character set - RFC 698 constexpr uchar TELOPT_LOGOUT = 18; // Force logout - RFC 727 constexpr uchar TELOPT_BM = 19; // Byte Macro - RFC 735 constexpr uchar TELOPT_DET = 20; // Data Entry Terminal - RFC 732,1043 constexpr uchar TELOPT_SUPDUP = 21; // SUPDUP Protocol - RFC 734,736 constexpr uchar TELOPT_SUPDUPOUTPUT = 22; // SUPDUP Output - RFC 749 constexpr uchar TELOPT_SNDLOC = 23; // Send Location - RFC 779 constexpr uchar TELOPT_TTYPE = 24; // Terminal Type - RFC 1091 constexpr uchar TELOPT_EOR = 25; // End of Record - RFC 885 constexpr uchar TELOPT_TUID = 26; // TACACS User Identification - RFC 927 constexpr uchar TELOPT_OUTMRK = 27; // Output Marking - RFC 933 constexpr uchar TELOPT_TTYLOC = 28; // Terminal Location Number - RFC 946 constexpr uchar TELOPT_3270REGIME = 29; // Telnet 3270 Regime - RFC 1041 constexpr uchar TELOPT_X3PAD = 30; // X.3 PAD - RFC 1053 constexpr uchar TELOPT_NAWS = 31; // Negotiate window size - RFC 1073 constexpr uchar TELOPT_TSPEED = 32; // Terminal Speed - RFC 1079 constexpr uchar TELOPT_LFLOW = 33; // Remote Flow Control - RFC 1372 constexpr uchar TELOPT_LINEMODE = 34; // Linemode option - RFC 1184 constexpr uchar TELOPT_XDISPLOC = 35; // X Display Location - RFC 1096 constexpr uchar TELOPT_OLD_ENVIRON = 36; // Environment Option - RFC 1408 constexpr uchar TELOPT_AUTHENTICATION = 37; // Authenticate - RFC 1416,2941,2942,2943,2951 constexpr uchar TELOPT_ENCRYPT = 38; // Encryption Option - RFC 2946 constexpr uchar TELOPT_NEW_ENVIRON = 39; // New Environment Option - RFC 1572 constexpr uchar TELOPT_TN3270E = 40; // TN3270 enhancements - RFC 2355 constexpr uchar TELOPT_XAUTH = 41; // XAUTH constexpr uchar TELOPT_CHARSET = 42; // Negotiate charset to use - RFC 2066 constexpr uchar TELOPT_RSP = 43; // Telnet remote serial port constexpr uchar TELOPT_COM_PORT_OPTION = 44; // Com port control option - RFC 2217 constexpr uchar TELOPT_SLE = 45; // Telnet suppress local echo constexpr uchar TELOPT_STARTTLS = 46; // Telnet Start TLS constexpr uchar TELOPT_KERMIT = 47; // Automatic Kermit file transfer - RFC 2840 constexpr uchar TELOPT_SEND_URL = 48; // Send URL constexpr uchar TELOPT_FORWARD_X = 49; // X forwarding constexpr uchar TELOPT_MCCP1 = 85; // Mud Compression Protocol (v1) constexpr uchar TELOPT_MCCP2 = 86; // Mud Compression Protocol (v2) constexpr uchar TELOPT_MSP = 90; // Mud Sound Protocol constexpr uchar TELOPT_MXP = 91; // Mud eXtension Protocol constexpr uchar TELOPT_ZMP = 93; // Zenith Mud Protocol constexpr uchar TELOPT_PRAGMA_LOGON = 138; // Telnet option pragma logon constexpr uchar TELOPT_SSPI_LOGON = 139; // Telnet option SSPI login constexpr uchar TELOPT_PRAGMA_HEARTBEAT = 140; // Telnet option pragma heartbeat constexpr uchar TELOPT_GMCP = 201; // Generic Mud Communication Protocol constexpr uchar TELOPT_EXOPL = 255; // extended-options-list - RFC 861 /* Option Subnegotiation Constants: */ constexpr uchar TELSUB_IS = 0; // An option IS constexpr uchar TELSUB_SEND = 1; // Send an option constexpr uchar TELSUB_INFO = 2; // Environ: informational version of IS constexpr uchar TELSUB_NAME = 3; /* Keyboard Command Characters: */ constexpr char TELKEY_LF = '\n'; // Line Feed constexpr char TELKEY_CR = '\r'; // Carriage Return constexpr char TELKEY_BEL = '\a'; // Bell (attention signal) constexpr char TELKEY_BS = '\b'; // Back Space constexpr char TELKEY_HT = '\t'; // Horizontal Tab constexpr char TELKEY_VT = '\v'; // Vertical Tab constexpr char TELKEY_FF = '\f'; // Form Feed enum TelnetOptionIndex : uchar { TELOPT_INDEX_NAWS, TELOPT_INDEX_TSPEED, TELOPT_INDEX_TTYPE, TELOPT_INDEX_NEW_ENVIRON, TELOPT_INDEX_LFLOW, TELOPT_INDEX_LINEMODE, TELOPT_INDEX_ECHO, TELOPT_INDEX_SERVER_SGA, TELOPT_INDEX_CLIENT_SGA, TELOPT_INDEX_SERVER_BIN, TELOPT_INDEX_CLIENT_BIN, TELOPT_INDEX_MAX }; enum TelnetAction : uchar { TELACT_ABORT, // Abort Process TELACT_AO, // Abort Output TELACT_AYT, // Are You There TELACT_BREAK, // serial-line break TELACT_EC, // Erase Character TELACT_EL, // Erase Line TELACT_EOF, // end-of-file on session input TELACT_EOL, // Telnet end-of-line sequence (CRLF, as opposed to CR NUL that escapes a literal CR) TELACT_EOR, // End Of Record TELACT_GA, // Go Ahead TELACT_IP, // Interrupt Process TELACT_NOP, // transmit data with no effect TELACT_SUSP // Suspend Process }; enum TelnetSide : uchar { TELNET_SERVER, TELNET_CLIENT }; #define BIT_INACTIVE 0x00 #define BIT_ACTIVE 0x01 #define BIT_REQUESTED 0x10 enum TelnetOptionState { TELOPT_STATE_INACTIVE = BIT_INACTIVE, TELOPT_STATE_ACTIVE = BIT_ACTIVE, TELOPT_STATE_INACTIVE_REQUESTED = BIT_INACTIVE | BIT_REQUESTED, TELOPT_STATE_ACTIVE_REQUESTED = BIT_ACTIVE | BIT_REQUESTED }; struct TelnetOption { int nTelnetOption; TelnetSide eTelnetSide; TelnetOptionState eOptionState; TelnetOption() : nTelnetOption(-1), eTelnetSide(TELNET_SERVER), eOptionState(TELOPT_STATE_INACTIVE) {} void Init(uchar _nTelnetOption, TelnetSide _eTelnetSide, TelnetOptionState _eOptionState) { nTelnetOption = _nTelnetOption; eTelnetSide = _eTelnetSide; eOptionState = _eOptionState; } }; typedef std::vector TelnetOptionVector; typedef std::vector TelnetOptionStateVector; class TelnetProtocol : public Protocol { public: TelnetProtocol(); std::string GetCommandName(uchar chTelnetCmd); std::string GetOptionName(uchar chTelnetOpt); TelnetOptionVector &GetOptionVector(); }; #endif // TELNETPROTOCOL_H ================================================ FILE: src/Pty/ConPty.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ConPty.h" #include #ifdef Q_OS_WIN #include #endif #define CONPTY_MINIMAL_WINDOWS_VERSION 18309 class PipeThread : public QThread { public: PipeThread(ConPty *conpty, LPVOID pipe) : QThread(conpty) , m_conpty(conpty) , m_pipe(pipe) {} void run() final { constexpr DWORD BUFF_SIZE = 512; char szBuffer[BUFF_SIZE]; while (isInterruptionRequested() == false) { if (isInterruptionRequested()) { return; } DWORD bytesRead; bool readSuccess = ReadFile(m_pipe, szBuffer, BUFF_SIZE, &bytesRead, NULL); if (readSuccess == false) { m_conpty->setErrorCode(GetLastError()); return; } if (isInterruptionRequested()) { return; } if (readSuccess && bytesRead > 0) { m_conpty->appendBuffer(QByteArray(szBuffer, bytesRead)); } } } private: ConPty *m_conpty; LPVOID m_pipe; }; ConPty::ConPty(QObject *parent /*= nullptr*/) : m_inPipe(INVALID_HANDLE_VALUE) , m_outPipe(INVALID_HANDLE_VALUE) , m_pipeThread(nullptr) , m_ptyHandler(INVALID_HANDLE_VALUE) {} ConPty::~ConPty() { stop(); } void ConPty::appendBuffer(const QByteArray &buffer) { if (buffer.isEmpty() == false) { { ThreadLocker locker(m_mutex); m_buffer.append(buffer); } emit readyRead(); } } HRESULT ConPty::createPseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, qint16 rows, qint16 columns) { HRESULT hr = E_UNEXPECTED; HANDLE hPipePTYIn = INVALID_HANDLE_VALUE; HANDLE hPipePTYOut = INVALID_HANDLE_VALUE; if (CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) && CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0)) { #if COMPILE_CONPTY_ENABLED hr = CreatePseudoConsole({columns, rows}, hPipePTYIn, hPipePTYOut, 0, phPC); #endif if (INVALID_HANDLE_VALUE != hPipePTYOut) CloseHandle(hPipePTYOut); if (INVALID_HANDLE_VALUE != hPipePTYIn) CloseHandle(hPipePTYIn); } return hr; } HRESULT ConPty::initStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC) { HRESULT hr = E_UNEXPECTED; if (pStartupInfo) { SIZE_T attrListSize; pStartupInfo->StartupInfo.cb = sizeof(STARTUPINFOEX); InitializeProcThreadAttributeList(NULL, 1, 0, &attrListSize); pStartupInfo->lpAttributeList = reinterpret_cast(malloc(attrListSize)); if (pStartupInfo->lpAttributeList && InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize)) { hr = UpdateProcThreadAttribute( pStartupInfo->lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HPCON), NULL, NULL ) ? S_OK : HRESULT_FROM_WIN32(GetLastError()); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } } return hr; } bool ConPty::createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QStringList &environment, qint16 rows, qint16 columns) { if (isAvailable() == false) { setErrorString(tr("Windows 10 version below 1809 is not supported.")); return false; } stop(); HRESULT hr = createPseudoConsoleAndPipes(&m_ptyHandler, &m_inPipe, &m_outPipe, rows, columns); if (hr == S_OK) { m_startupInfo = std::make_unique(); m_processInformation = std::make_unique(); m_pipeThread = new PipeThread(this, m_inPipe); m_pipeThread->start(); if (initStartupInfoAttachedToPseudoConsole(m_startupInfo.get(), m_ptyHandler) == S_OK) { std::wstring env = environment.join(QChar('\0')).append(QChar('\0')).toStdWString(); if (arguments.isEmpty() == false) { command.append(" ").append(arguments); } LPWSTR szCommand = new wchar_t[command.size() + 1]; int commandLength = command.toWCharArray(szCommand); szCommand[commandLength] = '\0'; hr = CreateProcess( NULL, szCommand, NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, LPWSTR(env.data()), workingDirectory.isEmpty() ? NULL : workingDirectory.toStdWString().c_str(), &m_startupInfo->StartupInfo, m_processInformation.get() ) ? S_OK : GetLastError(); delete szCommand; szCommand = nullptr; } } if (hr == S_OK) { m_rows = rows; m_columns = columns; installWinProcessEventNotifier(m_processInformation->hProcess); } else { setErrorCode(GetLastError()); } return true; } bool ConPty::isAvailable() { qint32 buildNumber = QSysInfo::kernelVersion().split(".").last().toInt(); return (buildNumber >= CONPTY_MINIMAL_WINDOWS_VERSION) ? true : false; } QByteArray ConPty::readAll() { ThreadLocker locker(m_mutex); return std::move(m_buffer); } bool ConPty::resizeWindow(qint16 rows, qint16 columns) { bool success = true; if (rows != m_rows && columns != m_columns) { #if COMPILE_CONPTY_ENABLED HRESULT hr = (m_ptyHandler != INVALID_HANDLE_VALUE) ? ResizePseudoConsole(m_ptyHandler, { columns, rows }) : S_FALSE; success = (hr == S_OK) ? true : false; #endif if (success) { rows = m_rows; columns = m_columns; } } Q_ASSERT(success); return success; } void ConPty::stop() { if (m_pipeThread) { m_pipeThread->requestInterruption(); } if (m_processInformation) { uninstallWinProcessEventNotifier(m_processInformation->hProcess); CloseHandle(m_processInformation->hThread); CloseHandle(m_processInformation->hProcess); } if (m_startupInfo) { DeleteProcThreadAttributeList(m_startupInfo->lpAttributeList); free(m_startupInfo->lpAttributeList); } if (m_ptyHandler != INVALID_HANDLE_VALUE) { #if COMPILE_CONPTY_ENABLED ClosePseudoConsole(m_ptyHandler); #endif } if (m_inPipe != INVALID_HANDLE_VALUE) { CloseHandle(m_inPipe); } if (m_outPipe != INVALID_HANDLE_VALUE) { CloseHandle(m_outPipe); } if (m_pipeThread) { m_pipeThread->wait(1000); m_pipeThread->deleteLater(); } } qint64 ConPty::write(const QByteArray &text) { DWORD bytesWritten; WriteFile(m_outPipe, text.data(), text.size(), &bytesWritten, NULL); return bytesWritten; } ================================================ FILE: src/Pty/ConPty.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CONPTY_H #define CONPTY_H #pragma once #include "Pty.h" #ifdef Q_OS_WIN #include #endif // Q_OS_WIN class PipeThread; class ConPty : public Pty { Q_OBJECT public: ConPty(QObject *parent = nullptr); virtual ~ConPty(); void appendBuffer(const QByteArray &buffer); bool createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QStringList &environment, qint16 rows, qint16 columns) final; static bool isAvailable(); QByteArray readAll() final; bool resizeWindow(qint16 rows, qint16 columns) final; qint64 write(const QByteArray &text) final; private: HRESULT createPseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, qint16 rows, qint16 columns); HRESULT initStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC); void stop(); private: Q_DISABLE_COPY(ConPty) QByteArray m_buffer; PipeThread *m_pipeThread; HANDLE m_inPipe; HANDLE m_outPipe; HPCON m_ptyHandler; std::unique_ptr m_processInformation; std::unique_ptr m_startupInfo; }; #endif // CONPTY_H ================================================ FILE: src/Pty/Pty.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Pty.h" #ifdef Q_OS_WIN #include #include #endif // Q_OS_WIN Pty::Pty() : m_columns(-1) , m_errorCode(0) , m_rows(-1) #ifdef Q_OS_WIN , m_winProcessEventNotifier(nullptr) #endif {} QString Pty::errorString() { ThreadLocker locker(m_mutex); return std::move(m_errorString); } #ifdef Q_OS_WIN void Pty::installWinProcessEventNotifier(void *handle) { if (m_winProcessEventNotifier == nullptr) { m_winProcessEventNotifier = new QWinEventNotifier(handle, this); connect(m_winProcessEventNotifier, &QWinEventNotifier::activated, this, [this](HANDLE handle) { if (handle) { DWORD exitCode; if (GetExitCodeProcess(handle, &exitCode)) { setErrorString(QString("Process exited with code %1").arg( QString::number(exitCode, (exitCode >= 0xFF) ? 16 : 10).prepend((exitCode >= 0xFF) ? "0x" : "") )); } m_winProcessEventNotifier->setEnabled(false); } }); } if (m_winProcessEventNotifier->handle() != handle) { m_winProcessEventNotifier->setHandle(handle); m_winProcessEventNotifier->setEnabled(true); } } #endif void Pty::setErrorCode(int errorCode) { constexpr int bufferLength = 512; wchar_t buffer[bufferLength]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, LANG_NEUTRAL, buffer, bufferLength, NULL); QString lastError = QString::fromWCharArray(buffer); setErrorString(lastError); m_errorCode = errorCode; } void Pty::setErrorString(const QString &errorString) { if (errorString.isEmpty() == false) { { ThreadLocker locker(m_mutex); m_errorString = errorString; } emit errorOccurred(); } } #ifdef Q_OS_WIN void Pty::uninstallWinProcessEventNotifier(void *handle) { if (m_winProcessEventNotifier != nullptr && m_winProcessEventNotifier->handle() == handle) { m_winProcessEventNotifier->deleteLater(); m_winProcessEventNotifier = nullptr; } } #endif ================================================ FILE: src/Pty/Pty.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PTY_H #define PTY_H #include #include "Public/Spin.h" class QWinEventNotifier; class Pty : public QObject { Q_OBJECT public: Pty(); virtual ~Pty() = default; virtual bool createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QStringList &environment, qint16 rows, qint16 columns) = 0; int errorCode() const { return m_errorCode; } QString errorString(); virtual QByteArray readAll() = 0; virtual bool resizeWindow(qint16 rows, qint16 columns) = 0; void setErrorCode(int errorCode); void setErrorString(const QString &errorString); virtual qint64 write(const QByteArray &text) = 0; protected: #ifdef Q_OS_WIN void installWinProcessEventNotifier(void *handle); void uninstallWinProcessEventNotifier(void *handle); #endif Q_SIGNALS: void errorOccurred(); void readyRead(); protected: SpinMutex m_mutex; qint16 m_columns; qint16 m_rows; private: Q_DISABLE_COPY(Pty) int m_errorCode; QString m_errorString; #ifdef Q_OS_WIN QWinEventNotifier *m_winProcessEventNotifier; #endif }; #endif // PTY_H ================================================ FILE: src/Pty/UnixPty.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "UnixPty.h" #ifdef Q_OS_UNIX #include #include #include #include #include #include #include #include constexpr int BUFFER_SIZE = 0x800; // 2048 bytes ShellProcess::ShellProcess() : QProcess() , m_handleMaster(-1) , m_handleSlave(-1) { setProcessChannelMode(QProcess::MergedChannels); } void ShellProcess::setupChildProcess() { dup2(m_handleSlave, STDIN_FILENO); dup2(m_handleSlave, STDOUT_FILENO); dup2(m_handleSlave, STDERR_FILENO); pid_t sid = setsid(); ioctl(m_handleSlave, TIOCSCTTY, 0); tcsetpgrp(m_handleSlave, sid); struct utmpx utmpxInfo; memset(&utmpxInfo, 0, sizeof(utmpxInfo)); strncpy(utmpxInfo.ut_user, qgetenv("USER"), sizeof(utmpxInfo.ut_user)); QString device(m_handleSlaveName); if (device.startsWith("/dev/")) { device = device.mid(5); } const char *d = device.toLatin1().constData(); strncpy(utmpxInfo.ut_line, d, sizeof(utmpxInfo.ut_line)); strncpy(utmpxInfo.ut_id, d + strlen(d) - sizeof(utmpxInfo.ut_id), sizeof(utmpxInfo.ut_id)); struct timeval tv; gettimeofday(&tv, 0); utmpxInfo.ut_tv.tv_sec = tv.tv_sec; utmpxInfo.ut_tv.tv_usec = tv.tv_usec; utmpxInfo.ut_type = USER_PROCESS; utmpxInfo.ut_pid = getpid(); utmpxname(_PATH_UTMPX); setutxent(); pututxline(&utmpxInfo); endutxent(); #if !defined(Q_OS_UNIX) updwtmpx(_PATH_UTMPX, &loginInfo); #endif } UnixPty::UnixPty(QObject *parent /*= nullptr*/) : Pty(parent) , m_pid(0) , m_readMasterNotify(nullptr) { m_buffer = static_cast(malloc(BUFFER_SIZE)); } UnixPty::~UnixPty() { stop(); free(m_buffer); m_buffer = nullptr; } bool UnixPty::createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QProcessEnvironment &environment, int rows, int columns) { if (m_shellProcess.state() == QProcess::Running) { return false; } QFileInfo fileInfo(command); if (fileInfo.isRelative() || fileInfo.exists() == false) { setErrorString(tr("UnixPty: shell file path must be absolute")); return false; } bool success = false; do { int result = 0; m_shellProcess.m_handleMaster = ::posix_openpt(O_RDWR | O_NOCTTY); if (m_shellProcess.m_handleMaster < 0) { setError("Unable to open master"); break; } m_shellProcess.m_handleSlaveName = ptsname(m_shellProcess.m_handleMaster); if (m_shellProcess.m_handleSlaveName.isEmpty()) { setError("Unable to get slave name"); break; } result = grantpt(m_shellProcess.m_handleMaster); if (result != 0) { setError("Unable to change perms for slave"); break; } result = unlockpt(m_shellProcess.m_handleMaster); if (result != 0) { setError("Unable to unlock slave"); break; } m_shellProcess.m_handleSlave = ::open(m_shellProcess.m_handleSlaveName.toLatin1().data(), O_RDWR | O_NOCTTY); if (m_shellProcess.m_handleSlave < 0) { setError("Unable to open slave"); break; } int flags = fcntl(m_shellProcess.m_handleMaster, F_GETFL, 0); result = fcntl(m_shellProcess.m_handleMaster, F_SETFL, flags | O_NONBLOCK); if (result == -1) { setError("Unable to set non-blocking mode for master"); break; } result = fcntl(m_shellProcess.m_handleMaster, F_SETFD, FD_CLOEXEC); if (result == -1) { setError("Unable to set flags for master"); break; } result = fcntl(m_shellProcess.m_handleSlave, F_SETFD, FD_CLOEXEC); if (result == -1) { setError("Unable to set flags for slave"); break; } struct ::termios ttmode; if (terminalAttributes(&ttmode) == false) { break; } ttmode.c_iflag |= IXON; ttmode.c_iflag |= IUTF8; ttmode.c_lflag |= ECHO; #ifdef Q_OS_MACOS ttmode.c_cc[VDSUSP] = 25; ttmode.c_cc[VSTATUS] = 20; #endif if (setTerminalAttributes(&ttmode) == false) { break; } m_readMasterNotify = new QSocketNotifier(m_shellProcess.m_handleMaster, QSocketNotifier::Read, &m_shellProcess); m_readMasterNotify->setEnabled(true); m_readMasterNotify->moveToThread(m_shellProcess.thread()); QObject::connect(m_readMasterNotify, &QSocketNotifier::activated, [this](int socket) { Q_UNUSED(socket) int readSize = 0; QByteArray readData; do { readSize = ::read(m_shellProcess.m_handleMaster, m_buffer, BUFFER_SIZE); if (readSize == -1) { if (errno == EAGAIN) { QThread::yieldCurrentThread(); continue; } else { break; } } readData.append(QByteArray::fromRawData(m_buffer, readSize)); } while (readSize == BUFFER_SIZE || (readSize == -1 && errno == EAGAIN)); //last data block always < readSize if (readData.isEmpty() == false) { m_shellReadBuffer.append(readData); emit readyRead(); } }); m_shellProcess.setWorkingDirectory(workingDirectory); m_shellProcess.setProcessEnvironment(environment); m_shellProcess.setReadChannel(QProcess::StandardOutput); m_shellProcess.start(command, arguments.isEmpty() ? QStringList() : QStringList(arguments)); m_shellProcess.waitForStarted(); m_pid = m_shellProcess.processId(); success = resizeWindow(rows, columns); } while(0); if (success == false) { stop(); } Q_ASSERT(success == true); return success; } bool UnixPty::resizeWindow(int rows, int columns) { if (rows != m_rows || columns != m_columns) { bool success = false; struct winsize winSize; memset(&winSize, 0, sizeof(winSize)); winSize.ws_row = static_cast(rows); winSize.ws_col = static_cast(columns); if (ioctl(m_shellProcess.m_handleMaster, TIOCSWINSZ, &winSize) == 0 && ioctl(m_shellProcess.m_handleSlave, TIOCSWINSZ, &winSize) == 0) { m_rows = rows; m_columns = columns; success = true; } return success; } return true; } void UnixPty::setError(const char *error) { Pty::setErrorString(QString("%1: %2 -> %3").arg(tr("UnixPty"), tr(error), strerror(errno))); } bool UnixPty::setTerminalAttributes(struct ::termios *ttmode) { Q_ASSERT(m_shellProcess.m_handleMaster >= 0); int result = -1; if (m_shellProcess.m_handleMaster >=0) { result = tcsetattr(m_shellProcess.m_handleMaster, TCSANOW, ttmode); if (result != 0) { setError("Unable to set terminal attributes"); } } return (result == 0); } void UnixPty::stop() { m_shellProcess.m_handleSlaveName = QString(); if (m_shellProcess.m_handleSlave >= 0) { ::close(m_shellProcess.m_handleSlave); m_shellProcess.m_handleSlave = -1; } if (m_shellProcess.m_handleMaster >= 0) { ::close(m_shellProcess.m_handleMaster); m_shellProcess.m_handleMaster = -1; } if (m_shellProcess.state() == QProcess::Running) { m_readMasterNotify->disconnect(); m_readMasterNotify->deleteLater(); m_shellProcess.terminate(); m_shellProcess.waitForFinished(1000); if (m_shellProcess.state() == QProcess::Running) { QProcess::startDetached(QString("kill -9 %1").arg(m_pid)); m_shellProcess.kill(); m_shellProcess.waitForFinished(1000); } Q_ASSERT(m_shellProcess.state() == QProcess::NotRunning); } } bool UnixPty::terminalAttributes(struct ::termios *ttmode) { Q_ASSERT(m_shellProcess.m_handleMaster >= 0); int result = -1; if (m_shellProcess.m_handleMaster >= 0) { result = tcgetattr(m_shellProcess.m_handleMaster, ttmode); if (result != 0) { setError("Unable to get terminal attributes"); } } return (result == 0); } QByteArray UnixPty::readAll() { QByteArray shellReadBuffer = m_shellReadBuffer; m_shellReadBuffer.clear(); return shellReadBuffer; } qint64 UnixPty::write(const QByteArray &text) { int writeSize = ::write(m_shellProcess.m_handleMaster, text.constData(), text.size()); Q_ASSERT(writeSize == text.size()); if (writeSize == -1) { setError("Unable to write output"); } return writeSize; } bool UnixPty::isAvailable() { return true; } void UnixPty::moveToThread(QThread *targetThread) { m_shellProcess.moveToThread(targetThread); } #endif // Q_OS_UNIX ================================================ FILE: src/Pty/UnixPty.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef UNIXPTY_H #define UNIXPTY_H #pragma once #include #ifdef Q_OS_UNIX #include "Pty.h" #include #include #include class ShellProcess : public QProcess { Q_OBJECT public: ShellProcess(); private: void setupChildProcess() final; private: int m_handleMaster; int m_handleSlave; QString m_handleSlaveName; private: friend class UnixPty; }; class UnixPty : public Pty { public: UnixPty(QObject *parent = nullptr); virtual ~UnixPty(); bool createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QProcessEnvironment &environment, int rows, int columns) final; static bool isAvailable(); bool resizeWindow(int rows, int columns) final; QByteArray readAll() final; qint64 write(const QByteArray &text) final; private: void moveToThread(QThread *targetThread); void setError(const char *error); bool setTerminalAttributes(struct ::termios *ttmode); void stop(); bool terminalAttributes(struct ::termios *ttmode); private: qint64 m_pid; ShellProcess m_shellProcess; QSocketNotifier *m_readMasterNotify; char *m_buffer; QByteArray m_shellReadBuffer; }; #endif // Q_OS_UNIX #endif // UNIXPTY_H ================================================ FILE: src/Pty/WinPty.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "WinPty.h" #include #include #include #include const char *WINPTY_AGENT_NAME = "winpty-agent.exe"; const char *WINPTY_DLL_NAME = "winpty.dll"; QString castErrorToString(winpty_error_ptr_t error_ptr) { return QString::fromStdWString(winpty_error_msg(error_ptr)); } WinPty::WinPty(QObject *parent /*= nullptr*/) : m_ptyHandler(nullptr) , m_innerHandle(INVALID_HANDLE_VALUE) , m_outSocket(nullptr) , m_inSocket(nullptr) {} WinPty::~WinPty() { stop(); } bool WinPty::createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QStringList &environment, qint16 rows, qint16 columns) { bool success = false; winpty_error_ptr_t errorPtr = nullptr; QString errorString; do { stop(); if (isAvailable() == false) { errorString = tr("Winpty-agent.exe or winpty.dll not found!."); break; } command = command.trimmed(); if (command.startsWith("\"") && command.endsWith("\"")) { command.remove(command.length() - 1, 1); command.remove(0, 1); } QString commandWithArguments = command; if (commandWithArguments.contains(' ')) { commandWithArguments.prepend("\"").append("\""); } if (arguments.isEmpty() == false) { commandWithArguments.append(" ").append(arguments); } std::wstring env = environment.join(QChar('\0')).append(QChar('\0')).toStdWString(); winpty_config_t* startConfig = winpty_config_new(0, &errorPtr); if (startConfig == nullptr) { errorString = QString("WinPty Error: create start config -> %1").arg(castErrorToString(errorPtr)); break; } winpty_config_set_initial_size(startConfig, columns, rows); winpty_config_set_mouse_mode(startConfig, WINPTY_MOUSE_MODE_AUTO); m_ptyHandler = winpty_open(startConfig, &errorPtr); winpty_config_free(startConfig); if (m_ptyHandler == nullptr) { errorString = QString("WinPty Error: start agent -> %1").arg(castErrorToString(errorPtr)); break; } QString m_conInName = QString::fromWCharArray(winpty_conin_name(m_ptyHandler)); QString m_conOutName = QString::fromWCharArray(winpty_conout_name(m_ptyHandler)); m_outSocket = std::make_unique(); m_inSocket = std::make_unique(); m_outSocket->connectToServer(m_conInName, QIODevice::WriteOnly); m_outSocket->waitForConnected(); m_inSocket->connectToServer(m_conOutName, QIODevice::ReadOnly); m_inSocket->waitForConnected(); if (m_outSocket->state() != QLocalSocket::ConnectedState && m_inSocket->state() != QLocalSocket::ConnectedState) { errorString = QString("WinPty Error: Unable to connect local sockets -> %1 / %2") .arg(m_outSocket->errorString()) .arg(m_inSocket->errorString()); m_inSocket.reset(nullptr); m_outSocket.reset(nullptr); break; } connect(m_inSocket.get(), &QLocalSocket::readyRead, this, [this]() { emit readyRead(); }); winpty_spawn_config_t* spawnConfig = winpty_spawn_config_new( WINPTY_SPAWN_FLAG_AUTO_SHUTDOWN, command.toStdWString().c_str(), commandWithArguments.toStdWString().c_str(), workingDirectory.isEmpty() ? NULL : workingDirectory.toStdWString().c_str(), env.c_str(), &errorPtr ); if (spawnConfig == nullptr) { errorString = QString("WinPty Error: create spawn config -> %1").arg(castErrorToString(errorPtr)); break; } BOOL spawnSuccess = winpty_spawn(m_ptyHandler, spawnConfig, &m_innerHandle, nullptr, nullptr, &errorPtr); winpty_spawn_config_free(spawnConfig); if (spawnSuccess == FALSE) { errorString = QString("WinPty Error: start terminal process -> %1").arg(castErrorToString(errorPtr)); break; } success = true; } while (0); if (errorString.isEmpty() == false) { Q_ASSERT(success == false); winpty_error_free(errorPtr); setErrorString(errorString); } if (success) { m_columns = columns; m_rows = rows; installWinProcessEventNotifier(m_innerHandle); } return success; } QByteArray WinPty::readAll() { QByteArray buffer; if (m_inSocket) { buffer = m_inSocket->readAll(); Q_ASSERT(buffer.isEmpty() == false); } return buffer; } bool WinPty::resizeWindow(qint16 rows, qint16 columns) { bool success = true; if (rows != m_rows && columns != m_columns) { success = m_ptyHandler ? winpty_set_size(m_ptyHandler, columns, rows, nullptr) : false; if (success) { m_rows = rows; m_columns = columns; } } Q_ASSERT(success); return success; } void WinPty::stop() { if (m_ptyHandler != nullptr) { winpty_free(m_ptyHandler); m_ptyHandler = nullptr; } if (m_innerHandle != INVALID_HANDLE_VALUE) { uninstallWinProcessEventNotifier(m_innerHandle); CloseHandle(m_innerHandle); m_innerHandle = INVALID_HANDLE_VALUE; } m_outSocket.reset(nullptr); m_inSocket.reset(nullptr); } qint64 WinPty::write(const QByteArray &text) { qint64 bytesWritten = -1; if (m_outSocket) { bytesWritten = m_outSocket->write(text); Q_ASSERT(bytesWritten != -1); } return bytesWritten; } bool WinPty::isAvailable() { return QFile::exists(QCoreApplication::applicationDirPath() + "/" + WINPTY_AGENT_NAME) && QFile::exists(QCoreApplication::applicationDirPath() + "/" + WINPTY_DLL_NAME); } ================================================ FILE: src/Pty/WinPty.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef WINPTY_H #define WINPTY_H #pragma once #include "Pty.h" #ifdef Q_OS_WIN #include #endif // Q_OS_WIN #include "winpty_api.h" class QLocalSocket; class WinPty : public Pty { Q_OBJECT public: WinPty(QObject *parent = nullptr); virtual ~WinPty(); bool createProcess(QString command, const QString &arguments, const QString &workingDirectory, const QStringList &environment, qint16 rows, qint16 columns) final; static bool isAvailable(); QByteArray readAll() final; bool resizeWindow(qint16 rows, qint16 columns) final; qint64 write(const QByteArray &text) final; private: void stop(); private: Q_DISABLE_COPY(WinPty) winpty_t *m_ptyHandler; HANDLE m_innerHandle; std::unique_ptr m_inSocket; std::unique_ptr m_outSocket; }; #endif // WINPTY_H ================================================ FILE: src/Pty/ptyqt LICENSE ================================================ MIT License Copyright (c) 2019 Vitaly Petrov 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. ================================================ FILE: src/README.md ================================================ **Important: WindTerm is a partial open source project, and the source will be gradually opened.** **All released source codes (except thirdparty directory) are provided under the terms of Apache-2.0 license.** # Components Below is a list of (some) WindTerm components in alphabetical order, along with a brief description of each. ## Libssh An improved version based on libssh 0.95. Add support for pageant, external socket, and hmac-md5-96, hmac-sha1-96-etm@openssh.com, hmac-sha1-96, hmac-md5-96-etm@openssh.com. ## Onigmo An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use. ## Pty An improved version based on [ptyqt](https://github.com/kafeg/ptyqt). **Almost all the code was rewritten to make the pty more robust and stable.** ## Protocol/TelentProtocol.h/cpp An implementation of Telnet protocol. ## Utility/CircularBuffer.h A quick circular buffer template class. ## Utility/Cryptographic.h/cpp A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on. ## Utility/MemoryPointer.h A smart memory pointer. ## Utility/ScopeGuard.h A class of which the sole purpose is to run the function f in its destructor. This is useful for guaranteeing your cleanup code is executed. ## Utility/Spin.h A high-performance spin mutex and locker. ## Utility/ThreadLocal.h/cpp A high-performance thread local storage. ## Widgets/PopupWidget.h/cpp A popup widget. ## Widgets/Scrollbar.h/cpp A scrollbar supports 64-bit ranges. ## Widgets/Splitter.h/cpp A convenient splitter for showing and hiding widgets. ================================================ FILE: src/Utility/CircularBuffer.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CIRCULARBUFFER_H #define CIRCULARBUFFER_H #pragma once #include #include #define ROUND_UP_POW2(value) { (1 << (32 - qCountLeadingZeroBits(value))) } template class CircularBuffer { public: CircularBuffer(quint32 capacity) : m_currentIndex(0) { Q_ASSERT(capacity < (1 << 31)); m_capacity = ROUND_UP_POW2(capacity); m_mask = m_capacity - 1; m_buffer = static_cast(calloc(m_capacity, sizeof(qint64))); clear(); } ~CircularBuffer() { free(m_buffer); m_buffer = nullptr; } void append(const T &value) { m_buffer[++m_currentIndex & m_mask] = value; } const T &at(qint64 index) const { Q_ASSERT(index >= std::max(0, m_currentIndex + 1 - m_capacity) && index <= m_currentIndex); return m_buffer[index & m_mask]; } int capacity() const { return m_capacity; } void clear() { m_currentIndex = -1; memset(m_buffer, 0xFF, m_capacity * sizeof(qint64)); #ifdef _DEBUG for (int i = 0; i < m_capacity; i++) { Q_ASSERT(m_buffer[i] == -1); } #endif // _DEBUG } qint64 currentIndex() const { return m_currentIndex; } qint64 minIndex() const { return std::max(0, m_currentIndex + 1 - m_capacity); } const T &operator [](qint64 index) const { Q_ASSERT(index >= std::max(0, m_currentIndex + 1 - m_capacity) && index <= m_currentIndex); return m_buffer[index & m_mask]; } private: T *m_buffer; qint64 m_currentIndex; int m_capacity; int m_mask; }; class Int64CircularBuffer : public CircularBuffer { public: Int64CircularBuffer(quint32 capacity) : CircularBuffer(capacity) {} }; #endif // CIRCULARBUFFER_H ================================================ FILE: src/Utility/Cryptographic.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Cryptographic.h" #include #include #include #include "openssl/evp.h" constexpr int AES_256_IV_LENGTH = 16; constexpr int AES_256_KEY_LENGTH = 32; constexpr int PBKDF2_LENGTH = AES_256_IV_LENGTH + AES_256_KEY_LENGTH; constexpr int PBKDF2_ITERATION_COUNT = 100000; QByteArray Cryptographic::decrypt(const QByteArray &data, const QByteArray &pbkdf2) { return doCrypt(QByteArray::fromBase64(data), Cryptographic::key(pbkdf2), Cryptographic::iv(pbkdf2), 0); } QByteArray Cryptographic::doCrypt(QByteArray data, const QByteArray &key, const QByteArray &iv, int enc) { QByteArray crypted(data.length() + EVP_MAX_BLOCK_LENGTH, '\0'); int cryptedLength = 0; int length; EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CipherInit_ex( ctx, EVP_aes_256_cbc(), nullptr, reinterpret_cast(key.constData()), reinterpret_cast(iv.constData()), enc ); EVP_CipherUpdate( ctx, reinterpret_cast(crypted.data()), &length, reinterpret_cast(data.constData()), data.length() ); cryptedLength += length; EVP_CipherFinal_ex(ctx, reinterpret_cast(crypted.data() + cryptedLength), &length); cryptedLength += length; EVP_CIPHER_CTX_free(ctx); crypted.resize(cryptedLength); return crypted; } QByteArray Cryptographic::encrypt(const QByteArray &data, const QByteArray &pbkdf2) { QByteArray encrypted = doCrypt(data, Cryptographic::key(pbkdf2), Cryptographic::iv(pbkdf2), 1); return encrypted.toBase64(); } QByteArray Cryptographic::iv(const QByteArray &pbkdf2) { Q_ASSERT(pbkdf2.length() == PBKDF2_LENGTH); return QByteArray::fromRawData(pbkdf2.constData() + AES_256_KEY_LENGTH, AES_256_IV_LENGTH); } QByteArray Cryptographic::key(const QByteArray &pbkdf2) { Q_ASSERT(pbkdf2.length() == PBKDF2_LENGTH); return QByteArray::fromRawData(pbkdf2.constData(), AES_256_KEY_LENGTH); } QByteArray Cryptographic::pbkdf2(const QByteArray &password, const QByteArray &salt) { return QPasswordDigestor::deriveKeyPbkdf2(QCryptographicHash::Sha3_512, password, salt, PBKDF2_ITERATION_COUNT, PBKDF2_LENGTH); } QByteArray Cryptographic::salt() { QByteArray number = QByteArray::number(QRandomGenerator::system()->generate64()); QByteArray numberHash = QCryptographicHash::hash(number, QCryptographicHash::Sha512); return numberHash.toBase64(); } ================================================ FILE: src/Utility/Cryptographic.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CRYPTOGRAPHIC_H #define CRYPTOGRAPHIC_H #pragma once class QByteArray; class Cryptographic { public: Cryptographic() = default; static QByteArray decrypt(const QByteArray &data, const QByteArray &pbkdf2); static QByteArray encrypt(const QByteArray &data, const QByteArray &pbkdf2); static QByteArray pbkdf2(const QByteArray &password, const QByteArray &salt); static QByteArray salt(); private: static QByteArray doCrypt(QByteArray data, const QByteArray &key, const QByteArray &iv, int enc); static QByteArray iv(const QByteArray &pbkdf2); static QByteArray key(const QByteArray &pbkdf2); }; #endif // CRYPTOGRAPHIC_H ================================================ FILE: src/Utility/MemoryPointer.h ================================================ #ifndef MEMORYPOINTER_H #define MEMORYPOINTER_H #pragma once #include template struct MemoryPointer { typedef decltype(nullptr) nullptr_t; public: MemoryPointer() : uMemory({ 0 }) {} MemoryPointer(const MemoryPointer &other) = delete; MemoryPointer &MemoryPointer::operator=(const MemoryPointer &other) = delete; MemoryPointer &MemoryPointer::operator=(nullptr_t) noexcept { free(); uMemory = { 0 }; return (*this); } MemoryPointer(MemoryPointer &&other) noexcept { uMemory = other.uMemory; other.uMemory = { 0 }; } MemoryPointer& MemoryPointer::operator=(MemoryPointer &&other) noexcept { if (this != &other) { free(); uMemory = other.uMemory; other.uMemory = { 0 }; } return (*this); } ~MemoryPointer() { free(); } inline T *data() const { return static_cast(uMemory.pointer); } inline T *operator->() const { return data(); } inline T &operator*() const { return *data(); } inline operator T*() const { return data(); } inline operator bool() const noexcept { return data() != nullptr; } inline bool isNull() const { return uMemory.pointer == NULL; } private: void free() { if (uMemory.alloced) { ::free(reinterpret_cast(uMemory.pointer)); uMemory = { 0 }; } } private: union MemoryUnion { quint64 value; struct { quint64 alloced : 1; quint64 pointer : 48; }; }; MemoryUnion uMemory; }; template inline bool operator==(const T *o, const MemoryPointer &p) { return o == p.operator->(); } template inline bool operator==(const MemoryPointer &p, const T *o) { return p.operator->() == o; } template inline bool operator==(T *o, const MemoryPointer &p) { return o == p.operator->(); } template inline bool operator==(const MemoryPointer &p, T *o) { return p.operator->() == o; } template inline bool operator==(const MemoryPointer &lhs, const MemoryPointer &rhs) { return lhs.operator->() == rhs.operator->(); } template inline bool operator!=(const T *o, const MemoryPointer &p) { return o != p.operator->(); } template inline bool operator!= (const MemoryPointer &p, const T *o) { return p.operator->() != o; } template inline bool operator!=(T *o, const MemoryPointer &p) { return o != p.operator->(); } template inline bool operator!= (const MemoryPointer &p, T *o) { return p.operator->() != o; } template inline bool operator!= (const MemoryPointer &lhs, const MemoryPointer &rhs) { return lhs.operator->() != rhs.operator->(); } #endif // MEMORYPOINTER_H ================================================ FILE: src/Utility/ScopeGuard.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCOPEGUARD_H #define SCOPEGUARD_H class ScopeGuard { typedef std::function GuardFunction; public: ScopeGuard(GuardFunction acquire, GuardFunction release) : m_active(true) , m_release(std::move(release)) { acquire(); } ~ScopeGuard() { if (m_active) { m_release(); } } ScopeGuard() = delete; ScopeGuard(const ScopeGuard &) = delete; ScopeGuard &operator=(const ScopeGuard &) = delete; ScopeGuard(ScopeGuard &&other) : m_active(other.m_active) , m_release(std::move(other.m_release)) { other.cancel(); } void cancel() { m_active = false; } private: bool m_active; GuardFunction m_release; }; #endif // SCOPEGUARD_H ================================================ FILE: src/Utility/Spin.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SPIN_H #define SPIN_H #pragma once #include #include class SpinMutex { public: SpinMutex() { unlock(); } void yield(size_t nCount) { if (nCount < 2) { } else if (nCount < 16) { std::this_thread::yield(); } else if (nCount < 32) { std::this_thread::sleep_for(std::chrono::nanoseconds(100)); } else { std::this_thread::sleep_for(std::chrono::microseconds(10)); } } void lock() { for (size_t i = 0; !try_lock(); i++) { yield(i); } } void unlock() { flag.clear(std::memory_order_release); } bool try_lock() { return flag.test_and_set(std::memory_order_acquire) == false; } private: SpinMutex(const SpinMutex &) = delete; SpinMutex &operator=(const SpinMutex &) = delete; std::atomic_flag flag; }; template class ThreadLocker { public: ThreadLocker(LockType& m_, bool bLock_ = true) : m(m_), bLock(bLock_) { if (bLock) m.lock(); } ~ThreadLocker() { if (bLock) m.unlock(); } private: LockType& m; bool bLock; }; #endif // SPIN_H ================================================ FILE: src/Utility/ThreadLocal.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ThreadLocal.h" #include void ThreadLocalWatcher::stopWatchCurrentThread() { QThread::currentThread()->disconnect(this); } void ThreadLocalWatcher::watchCurrentThread() { boost::thread::id id = boost::this_thread::get_id(); connect(QThread::currentThread(), &QThread::finished, this, [this, id]() { clear(id); }); } ================================================ FILE: src/Utility/ThreadLocal.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef THREADLOCAL_H #define THREADLOCAL_H #include #include #include #include #include "Spin.h" #define STATIC_LOCAL_COUNT 6 class ThreadLocalWatcher : public QObject { Q_OBJECT public: ThreadLocalWatcher() = default; protected: void stopWatchCurrentThread(); void watchCurrentThread(); virtual void clear(const boost::thread::id &id) = 0; private: Q_DISABLE_COPY(ThreadLocalWatcher) }; template class ThreadLocal : public ThreadLocalWatcher { public: ThreadLocal() : m_mainThreadId(boost::this_thread::get_id()) { for (int i = 0; i < STATIC_LOCAL_COUNT; i++) { m_staticLocals[i] = nullptr; } } ~ThreadLocal() { clearAll(); } void clear(const boost::thread::id &id) { std::lock_guard lock(m_mutex); if (removeLocal(id)) { stopWatchCurrentThread(); } } void clearAll() { std::lock_guard lock(m_mutex); for (int i = 0; i < STATIC_LOCAL_COUNT; i++) { if (Local *local = m_staticLocals[i]) { delete local; m_staticLocals[i] = nullptr; } } if (m_dynamicLocals) { for (Local *local : *m_dynamicLocals) { delete local; } m_dynamicLocals.reset(nullptr); } } T *get() { boost::thread::id id = boost::this_thread::get_id(); for (const Local *local : m_staticLocals) { if (local && local->id == id) { return local->ptr; } } if (m_dynamicLocals) { std::lock_guard lock(m_mutex); for (const Local *local : *m_dynamicLocals) { if (local && local->id == id) { return local->ptr; } } } return nullptr; } boost::thread::id mainThreadId() const { return m_mainThreadId; } void reset(T *t) { std::lock_guard lock(m_mutex); boost::thread::id id = boost::this_thread::get_id(); bool removed = removeLocal(id); bool added = addLocal(id, t); if (id != m_mainThreadId) { if (removed) { if (added == false) { stopWatchCurrentThread(); } } else { if (added) { watchCurrentThread(); } } } } private: bool addLocal(const boost::thread::id &id, T *t) { if (t == nullptr) { return false; } for (int i = 0; i < STATIC_LOCAL_COUNT; i++) { if (m_staticLocals[i] == nullptr) { m_staticLocals[i] = new Local(id, t); return true; } } if (m_dynamicLocals.get() == nullptr) { m_dynamicLocals = std::make_unique(); } m_dynamicLocals->push_back(new Local(id, t)); return true; } bool removeLocal(const boost::thread::id &id) { for (int i = 0; i < STATIC_LOCAL_COUNT; i++) { Local *local = m_staticLocals[i]; if (local && local->id == id) { delete local; m_staticLocals[i] = nullptr; return true; } } if (m_dynamicLocals) { for (auto it = m_dynamicLocals->begin(); it != m_dynamicLocals->end(); ++it) { Local *local = *it; if (local && local->id == id) { delete local; m_dynamicLocals->erase(it); return true; } } } return false; } private: Q_DISABLE_COPY(ThreadLocal) struct Local { boost::thread::id id; T *ptr; Local(boost::thread::id id_, T *ptr_) : id(id_) , ptr(ptr_) {} ~Local() { delete ptr; ptr = nullptr; } }; typedef std::vector LocalVector; std::unique_ptr m_dynamicLocals; Local *m_staticLocals[STATIC_LOCAL_COUNT]; boost::thread::id m_mainThreadId; SpinMutex m_mutex; }; #endif // THREADLOCAL_H ================================================ FILE: src/Widgets/PopupWidget.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PopupWidget.h" #include #include #include #include #include #include #include #include #define TRIANGLE_HEIGHT 18 PopupWidget::PopupWidget(QWidget *parent /*= nullptr*/) : QFrame(parent) { setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::WindowDoesNotAcceptFocus); setAttribute(Qt::WA_ShowWithoutActivating, true); setAttribute(Qt::WA_X11DoNotAcceptFocus, true); setAttribute(Qt::WA_DeleteOnClose, true); setFocusPolicy(Qt::NoFocus); setFrameShape(QFrame::StyledPanel); setMouseTracking(true); createLayout(); } PopupWidget::~PopupWidget() { if (QAbstractButton *button = dynamic_cast(parent())) { if (QToolButton *toolButton = dynamic_cast(parent())) { if (QAction *action = toolButton->defaultAction()) { action->setChecked(false); } } button->setChecked(false); } // Kill any running effect qFadeEffect(0); } void PopupWidget::createLayout() { QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->setSpacing(0); setLayout(vBoxLayout); } bool PopupWidget::eventFilter(QObject *watched, QEvent *event) { switch (event->type()) { case QEvent::FocusOut: if (QWidget *widget = dynamic_cast(watched)) { if (isAncestorOf(widget) == false && QApplication::activePopupWidget() == nullptr) { bool hasMenuAncestor = false; do { if (widget->inherits("QMenu")) { hasMenuAncestor = true; break; } } while (widget = widget->parentWidget()); if (hasMenuAncestor == false) { close(); } } } break; case QEvent::KeyPress: { if (QKeyEvent *keyEvent = dynamic_cast(event)) { QWidget *activePopupWidget = QApplication::activePopupWidget(); if (keyEvent->matches(QKeySequence::Cancel)) { if (activePopupWidget) { activePopupWidget->close(); } else { close(); } return true; } else if (isAncestorOf(QApplication::focusWidget()) == false) { if (activePopupWidget == nullptr) { close(); } } } break; } case QEvent::NonClientAreaMouseButtonPress: case QEvent::WindowStateChange: close(); break; case QEvent::MouseButtonPress: { if (QMouseEvent *mouseEvent = dynamic_cast(event)) { do { QPoint globalPos = mouseEvent->globalPos(); if (rect().contains(mapFromGlobal(globalPos))) break; if (QAbstractButton *button = dynamic_cast(parentWidget())) { if (button->rect().contains(button->mapFromGlobal(globalPos))) { break; } } setAttribute(Qt::WA_NoMouseReplay); close(); } while (0); } break; } case QEvent::WindowDeactivate: { if (QWidget *parentWidget = this->parentWidget()) { if (parentWidget->isAncestorOf(QApplication::focusWidget()) == false) { close(); } } break; } } return false; } void PopupWidget::mousePressEvent(QMouseEvent *event) { setAttribute(Qt::WA_NoMouseReplay); QWidget::mousePressEvent(event); } void PopupWidget::setCentralWidget(QWidget *widget) { widget->layout()->setContentsMargins(QMargins()); widget->setParent(this); layout()->addWidget(widget); adjustSize(); } void PopupWidget::show(Area hArea, Area vArea) { Q_ASSERT(parentWidget() != nullptr); if (QWidget *parent = parentWidget()) { QPoint newPos; QPolygon triPolygon; QRect rectPolygon; QPoint pos = parent->mapToGlobal(QPoint()); QRect rect = parent->rect(); QRect screenRect = QApplication::desktop()->availableGeometry(this); int topMargin = style()->pixelMetric(QStyle::PM_LayoutTopMargin); int bottomMargin = style()->pixelMetric(QStyle::PM_LayoutBottomMargin); int leftMargin = style()->pixelMetric(QStyle::PM_LayoutLeftMargin); int rightMargin = style()->pixelMetric(QStyle::PM_LayoutRightMargin); int triangleHeight = std::max(TRIANGLE_HEIGHT, topMargin); if (pos.y() < height()) { if (vArea == TopArea) { vArea = BottomArea; } } else { if (vArea == BottomArea && screenRect.height() - pos.y() - rect.height() < height()) { vArea = TopArea; } } if (hArea == MiddleArea) { newPos.setX(qBound(0, pos.x() + (rect.width() - width()) / 2, screenRect.width() - width())); } else { if (hArea == LeftArea) { if (pos.x() + rect.width() < width()) { hArea = RightArea; } } else { if (screenRect.width() - pos.x() < width()) { hArea = LeftArea; } } newPos.setX((hArea == LeftArea) ? pos.x() + rect.width() - width() : pos.x()); } newPos.setY((vArea == BottomArea) ? pos.y() + rect.height() : pos.y() - height() - triangleHeight); int xCenter = pos.x() + (rect.width() / 2) - newPos.x(); if (vArea == TopArea) { triPolygon << QPoint(xCenter - triangleHeight, height()) << QPoint(xCenter, height() + triangleHeight) << QPoint(xCenter + triangleHeight, height()); rectPolygon = QRect(0, 0, width(), height()); layout()->setContentsMargins(leftMargin, topMargin, rightMargin, bottomMargin + triangleHeight * 2); } else { triPolygon << QPoint(xCenter - triangleHeight, triangleHeight) << QPoint(xCenter, 0) << QPoint(xCenter + triangleHeight, triangleHeight); rectPolygon = QRect(0, triangleHeight, width(), height()); layout()->setContentsMargins(leftMargin, topMargin + triangleHeight, rightMargin, bottomMargin); } QRegion triangle(triPolygon); QRegion rectangle(rectPolygon, QRegion::Rectangle); QRegion mask = rectangle.united(triangle); setMask(mask); move(newPos); QWidget::show(); qFadeEffect(this, 200); qApp->installEventFilter(this); } } ================================================ FILE: src/Widgets/PopupWidget.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef POPUPWIDGET_H #define POPUPWIDGET_H #pragma once #include class PopupWidget : public QFrame { Q_OBJECT public: explicit PopupWidget(QWidget *parent = nullptr); virtual ~PopupWidget(); enum Area { LeftArea, MiddleArea, RightArea, TopArea, BottomArea }; public: void setCentralWidget(QWidget *widget); void show(Area hArea, Area vArea); private: void createLayout(); bool eventFilter(QObject *watched, QEvent *event) override; void mousePressEvent(QMouseEvent *event) override; private: Q_DISABLE_COPY(PopupWidget) }; #endif // POPUPWIDGET_H ================================================ FILE: src/Widgets/ScrollBar.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ScrollBar.h" #include #include ScrollBar::ScrollBar(Qt::Orientation orientation, QWidget *parent /*= nullptr*/) : QScrollBar(orientation, parent) { m_maximum = QScrollBar::maximum(); m_minimum = QScrollBar::minimum(); m_value = QScrollBar::value(); setContextMenuPolicy(Qt::PreventContextMenu); createConnections(); } void ScrollBar::createConnections() { connect(this, &QScrollBar::valueChanged, this, [this](qint64 value) { if (m_maximum > INT_MAX) { value *= (double)m_maximum / INT_MAX; } if (m_value != value) { qint64 oldValue = m_value; m_value = value; emit valueChanged(m_value, oldValue); } }); connect(this, &QScrollBar::actionTriggered, this, [this](int action) { qint64 oldValue = m_value; switch (action) { case QAbstractSlider::SliderMove: if (m_maximum > INT_MAX) { m_value = (QScrollBar::sliderPosition() * ((double)m_maximum / INT_MAX)); } else { m_value = QScrollBar::sliderPosition(); } break; case QAbstractSlider::SliderPageStepAdd: m_value = std::min(m_maximum, m_value + pageStep()); break; case QAbstractSlider::SliderPageStepSub: m_value = std::max(m_minimum, m_value - pageStep()); break; case QAbstractSlider::SliderSingleStepAdd: m_value = std::min(m_maximum, m_value + singleStep()); break; case QAbstractSlider::SliderSingleStepSub: m_value = std::max(m_minimum, m_value - singleStep()); break; case QAbstractSlider::SliderToMaximum: m_value = m_maximum; break; case QAbstractSlider::SliderToMinimum: m_value = m_minimum; break; } if (m_maximum > INT_MAX) { Q_ASSERT(QScrollBar::maximum() == INT_MAX); QScrollBar::setSliderPosition(m_value * ((double)INT_MAX / m_maximum)); } if (m_value != oldValue) { emit valueChanged(m_value, oldValue); } }); } bool ScrollBar::setMaximum(qint64 maximum) { return setRange(std::min(m_minimum, maximum), maximum); } bool ScrollBar::setMinimum(qint64 minimum) { return setRange(minimum, std::max(minimum, m_maximum)); } bool ScrollBar::setPage(int page) { if (page > 0 && page != QScrollBar::pageStep()) { QScrollBar::setPageStep(page); emit pageChanged(page); return true; } return false; } bool ScrollBar::setRange(qint64 minimum, qint64 maximum) { if (minimum >= 0 && minimum <= maximum && (m_minimum != minimum || m_maximum != maximum)) { m_maximum = maximum; m_minimum = minimum; QScrollBar::setRange( (m_minimum > INT_MAX) ? INT_MAX : m_minimum, (m_maximum > INT_MAX) ? INT_MAX : m_maximum ); emit rangeChanged(minimum, maximum); return true; } return false; } bool ScrollBar::setSingleStep(int singleStep) { if (singleStep > 0 && singleStep != QScrollBar::singleStep()) { QScrollBar::setSingleStep(singleStep); emit singleStepChanged(singleStep); return true; } return false; } bool ScrollBar::setValue(qint64 value) { value = qBound(m_minimum, value, m_maximum); if (m_value != value) { qint64 oldValue = m_value; m_value = value; if (m_maximum > INT_MAX) { value *= (double)INT_MAX / m_maximum; } { QSignalBlocker blocker(this); QScrollBar::setValue(value); } emit valueChanged(m_value, oldValue); return true; } return false; } ================================================ FILE: src/Widgets/ScrollBar.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SCROLLBAR_H #define SCROLLBAR_H #pragma once #include class ScrollBar : public QScrollBar { Q_OBJECT public: explicit ScrollBar(Qt::Orientation orientation, QWidget *parent = nullptr); virtual ~ScrollBar() = default; qint64 maximum() const { return m_maximum; } qint64 minimum() const { return m_minimum; } bool setMaximum(qint64 maximum); bool setMinimum(qint64 minimum); bool setPage(int page); bool setRange(qint64 minimum, qint64 maximum); bool setSingleStep(int singleStep); bool setValue(qint64 value); qint64 value() const { return m_value; } private: void createConnections(); Q_SIGNALS: void pageChanged(int page) const; void rangeChanged(qint64 minimum, qint64 maximum) const; void singleStepChanged(int singleStep) const; void valueChanged(qint64 value, qint64 oldValue) const; private: Q_DISABLE_COPY(ScrollBar) qint64 m_maximum; qint64 m_minimum; qint64 m_value; }; #endif // SCROLLBAR_H ================================================ FILE: src/Widgets/Splitter.cpp ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Splitter.h" #include #include const char* const SPLITTER_RATIO = "ratio"; Splitter::Splitter(QWidget *parent) : QSplitter(parent) , m_mainIndex(0) {} Splitter::~Splitter() {} void Splitter::showIndex(int index) { if (isIndexVisible(index)) return; emit showIndexRequested(index); if (QSplitterHandle *handle = this->handle(index)) { QList sizes = this->sizes(); int total = 0; for (int size : sizes) { total += size; } float ratio = handle->property(SPLITTER_RATIO).toFloat(); if (ratio == 0.0) { ratio = 0.18f; } int offset = 0; int size = total * ratio; if (index > 0) { for (int i = 0; i < index; i++) { offset += sizes[i]; } offset -= size; } else { offset = size; } if (index <= m_mainIndex) { index += 1; } moveSplitter(offset, index); } } void Splitter::hideIndex(int index) { if (isIndexVisible(index) == false) return; emit hideIndexRequested(index); if (QSplitterHandle *handle = this->handle(index)) { QList sizes = this->sizes(); int size = sizes[index]; float total = 0; for (int size : sizes) { total += size; } handle->setProperty(SPLITTER_RATIO, size / total); int offset = 0; for (int i = 0; i <= index; i++) { if (i == index && index <= m_mainIndex) break; offset += sizes[i]; } if (index <= m_mainIndex) { index += 1; } moveSplitter(offset, index); } } bool Splitter::isIndexVisible(int index) { if (index >= 0 && index < count()) { return sizes()[index] > 0; } Q_ASSERT(false); return false; } void Splitter::setIndexVisible(int index, bool visible) { if (visible) { showIndex(index); } else { hideIndex(index); } } void Splitter::setMainIndex(int mainIndex) { m_mainIndex = mainIndex; } bool Splitter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonDblClick) { if (QSplitterHandle *handle = dynamic_cast(obj)) { for (int i = 0; i < count(); i++) { if (handle == this->handle(i)) { if (i <= m_mainIndex && i > 0) { i--; } bool visible = isIndexVisible(i); setIndexVisible(i, !visible); break; } } } } return QSplitter::eventFilter(obj, event); } QSplitterHandle *Splitter::createHandle() { QSplitterHandle *handle = QSplitter::createHandle(); handle->installEventFilter(this); return handle; } ================================================ FILE: src/Widgets/Splitter.h ================================================ /* * Copyright 2020, WindTerm. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SPLITTER_H #define SPLITTER_H #pragma once #include extern const char* const SPLITTER_RATIO; class Splitter : public QSplitter { Q_OBJECT public: explicit Splitter(QWidget *parent = 0); ~Splitter(); void showIndex(int index); void hideIndex(int index); bool isIndexVisible(int index); void setIndexVisible(int index, bool visible); void setMainIndex(int mainIndex); protected: bool eventFilter(QObject *obj, QEvent *event); QSplitterHandle *createHandle(); Q_SIGNALS: void showIndexRequested(int index); void hideIndexRequested(int index); private: Q_DISABLE_COPY(Splitter) int m_mainIndex; }; #endif // SPLITTER_H ================================================ FILE: src/libssh/.arcconfig ================================================ { "phabricator.uri" : "https://bugs.libssh.org/", "history.immutable": true } ================================================ FILE: src/libssh/.gitlab-ci.yml ================================================ variables: BUILD_IMAGES_PROJECT: libssh/build-images FEDORA_BUILD: buildenv-fedora CENTOS7_BUILD: buildenv-centos7 TUMBLEWEED_BUILD: buildenv-tumbleweed MINGW_BUILD: buildenv-mingw # pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON centos7/openssl_1.0.x/x86_64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD script: - mkdir -p obj && cd obj && cmake3 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/openssl_1.1.x/x86_64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/openssl_1.1.x/x86_64/fips: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - echo 1 > /etc/system-fips - update-crypto-policies --set FIPS - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/openssl_1.1.x/x86_64/minimal: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=OFF -DWITH_SERVER=OFF -DWITH_ZLIB=OFF -DWITH_PCAP=OFF -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DWITH_GEX=OFF .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ # Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite # so, this is only enabled for unit tests right now. # TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON fedora/address-sanitizer: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=AddressSanitizer -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ # This is disabled as it report OpenSSL issues # It also has ethe same issues with cwrap as AddressSanitizer .fedora/memory-sanitizer: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=MemorySanitizer -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/undefined-sanitizer: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=UndefinedSanitizer -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/csbuild: variables: GIT_DEPTH: "100" image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - | if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") fi # Check if the commit exists in this branch # This is not the case for a force push git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20") export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA" - csbuild --build-dir=obj-csbuild --build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)" --git-commit-range $CI_COMMIT_RANGE --color --print-current --print-fixed tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj-csbuild/ # That is a specific runner that we cannot enable universally. # We restrict it to builds under the $BUILD_IMAGES_PROJECT project. freebsd/x86_64: image: script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make && ctest --output-on-failure tags: - freebsd except: - tags only: - branches@libssh/libssh-mirror - branches@cryptomilk/libssh-mirror artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/libgcrypt/x86_64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ fedora/mbedtls/x86_64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ # Unit testing only, no client and pkd testing, because cwrap is not available # for MinGW fedora/mingw64: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD script: - export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin - export WINEDEBUG=-all - mkdir -p obj && cd obj && mingw64-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ # Unit testing only, no client and pkd testing, because cwrap is not available # for MinGW fedora/mingw32: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD script: - export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin - export WINEDEBUG=-all - mkdir -p obj && cd obj && mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/openssl_1.1.x/x86_64/gcc: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/openssl_1.1.x/x86/gcc: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/openssl_1.1.x/x86_64/gcc7: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/openssl_1.1.x/x86/gcc7: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake -DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/openssl_1.1.x/x86_64/clang: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/docs: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake .. && make docs tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/undefined-sanitizer: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=UndefinedSanitizer -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && make -j$(nproc) && ctest --output-on-failure tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/ tumbleweed/static-analysis: image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD script: - export CCC_CC=clang - export CCC_CXX=clang++ - mkdir -p obj && cd obj && scan-build cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON -DSERVER_TESTING=ON .. && scan-build --status-bugs -o scan make -j$(nproc) tags: - shared except: - tags artifacts: expire_in: 1 week when: on_failure paths: - obj/scan visualstudio/x86_64: variables: ErrorActionPreference: STOP script: - $env:VCPKG_DEFAULT_TRIPLET="x64-windows" - mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1} - cmake -A x64 -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE" -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. - cmake --build . - ctest --output-on-failure tags: - vs2017 - windows except: - tags only: - branches@libssh/libssh-mirror - branches@ansasaki/libssh-mirror - branches@cryptomilk/libssh-mirror - branches@jjelen/libssh-mirror artifacts: expire_in: 1 week when: on_failure paths: - obj/ visualstudio/x86: variables: ErrorActionPreference: STOP script: - $env:VCPKG_DEFAULT_TRIPLET="x86-windows" - mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1} - cmake -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE" -DPICKY_DEVELOPER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON .. - cmake --build . - ctest --output-on-failure tags: - vs2017 - windows except: - tags only: - branches@libssh/libssh-mirror - branches@ansasaki/libssh-mirror - branches@cryptomilk/libssh-mirror - branches@jjelen/libssh-mirror artifacts: expire_in: 1 week when: on_failure paths: - obj/ ================================================ FILE: src/libssh/AUTHORS ================================================ Author(s): Aris Adamantiadis (project initiator) Andreas Schneider (developer) Nick Zitzmann (mostly client SFTP stuff) Norbert Kiesel (getaddrinfo and other patches) Jean-Philippe Garcia Ballester (Port to libgcrypt and configure.in voodoo, debian packaging) Contributor(s): Laurent Bigonville (debian packaging) ================================================ FILE: src/libssh/BSD ================================================ Some parts are under the BSDv2 License : Copyright (c) 2000 Markus Friedl. 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 ``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 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. ================================================ FILE: src/libssh/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.3.0) cmake_policy(SET CMP0048 NEW) # Specify search path for CMake modules to be loaded by include() # and find_package() list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") # Add defaults for cmake # Those need to be set before the project() call. include(DefineCMakeDefaults) include(DefineCompilerFlags) project(libssh VERSION 0.9.5 LANGUAGES C) # global needed variable set(APPLICATION_NAME ${PROJECT_NAME}) # SOVERSION scheme: CURRENT.AGE.REVISION # If there was an incompatible interface change: # Increment CURRENT. Set AGE and REVISION to 0 # If there was a compatible interface change: # Increment AGE. Set REVISION to 0 # If the source code was changed, but there were no interface changes: # Increment REVISION. set(LIBRARY_VERSION "4.8.6") set(LIBRARY_SOVERSION "4") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked # add definitions include(DefinePlatformDefaults) include(DefineOptions.cmake) include(CPackConfig.cmake) include(GNUInstallDirs) include(CompilerChecks.cmake) # disallow in-source build include(MacroEnsureOutOfSourceBuild) macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") # Copy library files to a lib sub-directory set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") # search for libraries if (WITH_ZLIB) find_package(ZLIB REQUIRED) endif (WITH_ZLIB) if (WITH_GCRYPT) find_package(GCrypt 1.5.0 REQUIRED) if (NOT GCRYPT_FOUND) message(FATAL_ERROR "Could not find GCrypt") endif (NOT GCRYPT_FOUND) elseif(WITH_MBEDTLS) find_package(MbedTLS REQUIRED) if (NOT MBEDTLS_FOUND) message(FATAL_ERROR "Could not find mbedTLS") endif (NOT MBEDTLS_FOUND) else (WITH_GCRYPT) find_package(OpenSSL) if (NOT OPENSSL_FOUND) find_package(GCrypt) if (NOT GCRYPT_FOUND) find_package(MbedTLS) if (NOT MBEDTLS_FOUND) message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS") endif (NOT MBEDTLS_FOUND) endif (NOT GCRYPT_FOUND) endif (NOT OPENSSL_FOUND) endif(WITH_GCRYPT) if (UNIT_TESTING) find_package(CMocka REQUIRED) endif () # Find out if we have threading available set(CMAKE_THREAD_PREFER_PTHREADS ON) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads) if (WITH_GSSAPI) find_package(GSSAPI) endif (WITH_GSSAPI) if (WITH_NACL) find_package(NaCl) if (NOT NACL_FOUND) set(WITH_NACL OFF) endif (NOT NACL_FOUND) endif (WITH_NACL) if (BSD OR SOLARIS OR OSX) find_package(Argp) endif (BSD OR SOLARIS OR OSX) # Disable symbol versioning in non UNIX platforms if (UNIX) find_package(ABIMap 0.3.1) else (UNIX) set(WITH_SYMBOL_VERSIONING OFF) endif (UNIX) # config.h checks include(ConfigureChecks.cmake) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) # check subdirectories add_subdirectory(doc) add_subdirectory(include) add_subdirectory(src) # pkg-config file if (UNIX) configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT pkgconfig ) endif (UNIX) # CMake config files include(CMakePackageConfigHelpers) set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX}) # libssh-config-version.cmake write_basic_package_version_file(libssh-config-version.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} COMPONENT devel) if (WITH_EXAMPLES) add_subdirectory(examples) endif (WITH_EXAMPLES) if (UNIT_TESTING) include(AddCMockaTest) add_subdirectory(tests) endif (UNIT_TESTING) ### SOURCE PACKAGE if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND) # Get the current ABI version from source get_filename_component(current_abi_path "${CMAKE_SOURCE_DIR}/src/ABI/current" ABSOLUTE) # Check if the ABI version should be updated file(READ ${current_abi_path} CURRENT_ABI_CONTENT) string(STRIP "${CURRENT_ABI_CONTENT}" CURRENT_ABI_VERSION) if (LIBRARY_VERSION VERSION_GREATER CURRENT_ABI_VERSION) set(UPDATE_ABI TRUE) endif () if (UPDATE_ABI) message(STATUS "Library version bumped to ${LIBRARY_VERSION}: Updating ABI") # Get the list of header files get_file_list(${PROJECT_NAME}_header_list DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libssh" FILES_PATTERNS "*.h") # Extract the symbols marked as "LIBSSH_API" from the header files extract_symbols(${PROJECT_NAME}.symbols HEADERS_LIST ${PROJECT_NAME}_header_list FILTER_PATTERN "LIBSSH_API" COPY_TO "${CMAKE_SOURCE_DIR}/src/ABI/${PROJECT_NAME}-${LIBRARY_VERSION}.symbols") if (WITH_ABI_BREAK) set(ALLOW_ABI_BREAK "BREAK_ABI") endif() # Target we can depend on in 'make dist' set(_SYMBOL_TARGET "${PROJECT_NAME}.map") # Set the path to the current map file set(MAP_PATH "${CMAKE_SOURCE_DIR}/src/${_SYMBOL_TARGET}") # Generate the symbol version map file generate_map_file(${_SYMBOL_TARGET} SYMBOLS ${PROJECT_NAME}.symbols RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION} CURRENT_MAP ${MAP_PATH} COPY_TO ${MAP_PATH} FINAL ${ALLOW_ABI_BREAK}) # Write the current version to the source file(WRITE ${current_abi_path} ${LIBRARY_VERSION}) endif(UPDATE_ABI) endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND) add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET}) # Link compile database for clangd execute_process(COMMAND cmake -E create_symlink "${CMAKE_BINARY_DIR}/compile_commands.json" "${CMAKE_SOURCE_DIR}/compile_commands.json") message(STATUS "********************************************") message(STATUS "********** ${PROJECT_NAME} build options : **********") message(STATUS "zlib support: ${WITH_ZLIB}") message(STATUS "libgcrypt support: ${WITH_GCRYPT}") message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}") message(STATUS "libnacl support: ${WITH_NACL}") message(STATUS "SFTP support: ${WITH_SFTP}") message(STATUS "Server support : ${WITH_SERVER}") message(STATUS "GSSAPI support : ${WITH_GSSAPI}") message(STATUS "GEX support : ${WITH_GEX}") message(STATUS "Pcap debugging support : ${WITH_PCAP}") message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}") message(STATUS "Unit testing: ${UNIT_TESTING}") message(STATUS "Client code testing: ${CLIENT_TESTING}") message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}") set(_SERVER_TESTING OFF) if (WITH_SERVER) set(_SERVER_TESTING ${SERVER_TESTING}) endif() message(STATUS "Server code testing: ${_SERVER_TESTING}") if (WITH_INTERNAL_DOC) message(STATUS "Internal documentation generation") else (WITH_INTERNAL_DOC) message(STATUS "Public API documentation generation") endif (WITH_INTERNAL_DOC) message(STATUS "Benchmarks: ${WITH_BENCHMARKS}") message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}") message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}") message(STATUS "Release is final: ${WITH_FINAL}") message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}") if (WITH_SERVER) message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}") endif() message(STATUS "********************************************") ================================================ FILE: src/libssh/COPYING ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Linking with OpenSSL 17. In addition, as a special exception, we give permission to link the code of its release of libssh with the OpenSSL project's "OpenSSL" library (or with modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must obey the GNU Lesser General Public License in all respects for all of the code used other than "OpenSSL". If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. END OF TERMS AND CONDITIONS ================================================ FILE: src/libssh/CPackConfig.cmake ================================================ ### GENERAL SETTINGS set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH Library") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team") set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) # SOURCE GENERATOR set(CPACK_SOURCE_GENERATOR "TXZ") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") ### NSIS INSTALLER if (WIN32) set(CPACK_GENERATOR "ZIP") ### nsis generator find_package(NSIS) if (NSIS_MAKE) set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS") set(CPACK_NSIS_DISPLAY_NAME "The SSH Library") set(CPACK_NSIS_COMPRESSOR "/SOLID zlib") set(CPACK_NSIS_MENU_LINKS "https://www.libssh.org/" "libssh homepage") endif (NSIS_MAKE) endif (WIN32) set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh") set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION}) set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries") set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C/C++ Headers") set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION "Libraries used to build programs which use libssh") set(CPACK_COMPONENT_HEADERS_DESCRIPTION "C/C++ header files for use with libssh") set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") set(CPACK_COMPONENT_HEADERS_GROUP "Development") include(CPack) ================================================ FILE: src/libssh/CTestConfig.cmake ================================================ set(UPDATE_TYPE "true") set(CTEST_PROJECT_NAME "libssh") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_DROP_METHOD "https") set(CTEST_DROP_SITE "test.libssh.org") set(CTEST_DROP_LOCATION "/submit.php?project=libssh") set(CTEST_DROP_SITE_CDASH TRUE) ================================================ FILE: src/libssh/ChangeLog ================================================ ChangeLog ========== version 0.9.5 (released 2020-XX-XX) * CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232) * Improve handling of library initialization (T222) * Fix parsing of subsecond times in SFTP (T219) * Make the documentation reproducible * Remove deprecated API usage in OpenSSL * Fix regression of ssh_channel_poll_timeout() returning SSH_AGAIN * Define version in one place (T226) * Prevent invalid free when using different C runtimes than OpenSSL (T229) * Compatibility improvements to testsuite version 0.9.4 (released 2020-04-09) * Fixed CVE-2020-1730 - Possible DoS in client and server when handling AES-CTR keys with OpenSSL * Added diffie-hellman-group14-sha256 * Fixed serveral possible memory leaks version 0.9.3 (released 2019-12-10) * Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution * SSH-01-003 Client: Missing NULL check leads to crash in erroneous state * SSH-01-006 General: Various unchecked Null-derefs cause DOS * SSH-01-007 PKI Gcrypt: Potential UAF/double free with RSA pubkeys * SSH-01-010 SSH: Deprecated hash function in fingerprinting * SSH-01-013 Conf-Parsing: Recursive wildcards in hostnames lead to DOS * SSH-01-014 Conf-Parsing: Integer underflow leads to OOB array access * SSH-01-001 State Machine: Initial machine states should be set explicitly * SSH-01-002 Kex: Differently bound macros used to iterate same array * SSH-01-005 Code-Quality: Integer sign confusion during assignments * SSH-01-008 SCP: Protocol Injection via unescaped File Names * SSH-01-009 SSH: Update documentation which RFCs are implemented * SSH-01-012 PKI: Information leak via uninitialized stack buffer version 0.9.2 (released 2019-11-07) * Fixed libssh-config.cmake * Fixed issues with rsa algorithm negotiation (T191) * Fixed detection of OpenSSL ed25519 support (T197) version 0.9.1 (released 2019-10-25) * Added support for Ed25519 via OpenSSL * Added support for X25519 via OpenSSL * Added support for localuser in Match keyword * Fixed Match keyword to be case sensitive * Fixed compilation with LibreSSL * Fixed error report of channel open (T75) * Fixed sftp documentation (T137) * Fixed known_hosts parsing (T156) * Fixed build issue with MinGW (T157) * Fixed build with gcc 9 (T164) * Fixed deprecation issues (T165) * Fixed known_hosts directory creation (T166) version 0.9.0 (released 2019-06-28) * Added support for AES-GCM * Added improved rekeying support * Added performance improvements * Disabled blowfish support by default * Fixed several ssh config parsing issues * Added support for DH Group Exchange KEX * Added support for Encrypt-then-MAC mode * Added support for parsing server side configuration file * Added support for ECDSA/Ed25519 certificates * Added FIPS 140-2 compatibility * Improved known_hosts parsing * Improved documentation * Improved OpenSSL API usage for KEX, DH, and signatures version 0.8.7 (released 2019-02-25) * Fixed handling extension flags in the server implementation * Fixed exporting ed25519 private keys * Fixed corner cases for rsa-sha2 signatures * Fixed some issues with connector version 0.8.6 (released 2018-12-24) * Fixed compilation issues with different OpenSSL versions * Fixed StrictHostKeyChecking in new knownhosts API * Fixed ssh_send_keepalive() with packet filter * Fixed possible crash with knownhosts options * Fixed issus with rekeying * Fixed strong ECDSA keys * Fixed some issues with rsa-sha2 extentions * Fixed access violation in ssh_init() (static linking) * Fixed ssh_channel_close() handling version 0.8.5 (released 2018-10-29) * Added support to get known_hosts locations with ssh_options_get() * Fixed preferred algorithm for known hosts negotiations * Fixed KEX with some server implementations (e.g. Cisco) * Fixed issues with MSVC * Fixed keyboard-interactive auth in server mode (regression from CVE-2018-10933) * Fixed gssapi auth in server mode (regression from CVE-2018-10933) * Fixed socket fd handling with proxy command * Fixed a memory leak with OpenSSL version 0.8.4 (released 2018-10-16) * Fixed CVE-2018-10933 * Fixed building without globbing support * Fixed possible memory leaks * Avoid SIGPIPE on sockets version 0.8.3 (released 2018-09-21) * Added support for rsa-sha2 * Added support to parse private keys in openssh container format (other than ed25519) * Added support for diffie-hellman-group18-sha512 and diffie-hellman-group16-sha512 * Added ssh_get_fingerprint_hash() * Added ssh_pki_export_privkey_base64() * Added support for Match keyword in config file * Improved performance and reduced memory footprint for sftp * Fixed ecdsa publickey auth * Fixed reading a closed channel * Added support to announce posix-rename@openssh.com and hardlink@openssh.com in the sftp server version 0.8.2 (released 2018-08-30) * Added sha256 fingerprints for pubkeys * Improved compiler flag detection * Fixed race condition in reading sftp messages * Fixed doxygen generation and added modern style * Fixed library initialization on Windows * Fixed __bounded__ attribute detection * Fixed a bug in the options parser * Fixed documentation for new knwon_hosts API version 0.8.1 (released 2018-08-13) * Fixed version number in the header * Fixed version number in pkg-config and cmake config * Fixed library initialization * Fixed attribute detection version 0.8.0 (released 2018-08-10) * Removed support for deprecated SSHv1 protocol * Added new connector API for clients * Added new known_hosts parsing API * Added support for OpenSSL 1.1 * Added support for chacha20-poly1305 cipher * Added crypto backend for mbedtls crypto library * Added ECDSA support with gcrypt backend * Added advanced client and server testing using cwrap.org * Added support for curve25519-sha256 alias * Added support for global known_hosts file * Added support for symbol versioning * Improved ssh_config parsing * Improved threading support version 0.7.5 (released 2017-04-13) * Fixed a memory allocation issue with buffers * Fixed PKI on Windows * Fixed some SSHv1 functions * Fixed config hostname expansion version 0.7.4 (released 2017-02-03) * Added id_ed25519 to the default identity list * Fixed sftp EOF packet handling * Fixed ssh_send_banner() to confirm with RFC 4253 * Fixed some memory leaks version 0.7.3 (released 2016-01-23) * Fixed CVE-2016-0739 * Fixed ssh-agent on big endian * Fixed some documentation issues version 0.7.2 (released 2015-09-15) * Fixed OpenSSL detection on Windows * Fixed return status for ssh_userauth_agent() * Fixed KEX to prefer hmac-sha2-256 * Fixed sftp packet handling * Fixed return values of ssh_key_is_(public|private) * Fixed bug in global success reply version 0.7.1 (released 2015-06-30) * Fixed SSH_AUTH_PARTIAL auth with auto public key * Fixed memory leak in session options * Fixed allocation of ed25519 public keys * Fixed channel exit-status and exit-signal * Reintroduce ssh_forward_listen() version 0.7.0 (released 2015-05-11) * Added support for ed25519 keys * Added SHA2 algorithms for HMAC * Added improved and more secure buffer handling code * Added callback for auth_none_function * Added support for ECDSA private key signing * Added more tests * Fixed a lot of bugs * Improved API documentation version 0.6.5 (released 2015-04-29) * Fixed CVE-2015-3146 * Fixed port handling in config file * Fixed the build with libgcrypt * Fixed SFTP endian issues (rlo #179) * Fixed uninitilized sig variable (rlo #167) * Fixed polling issues which could result in a hang * Fixed handling of EINTR in ssh_poll() (rlo #186) * Fixed C99 issues with __func__ * Fixed some memory leaks * Improved macro detection on Windows version 0.6.4 (released 2014-12-19) * Fixed CVE-2014-8132. * Added SHA-2 for session ID signing with ECDSA keys. * Added support for ECDSA host keys. * Added support for more ECDSA hostkey algorithms. * Added ssh_pki_key_ecdsa_name() API. * Fixed setting the bindfd only after successful listen. * Fixed issues with user created sockets. * Fixed several issues in libssh C++ wrapper. * Fixed several documentation issues. * Fixed channel exit-signal request. * Fixed X11 request screen number in messages. * Fixed several memory leaks. version 0.6.3 (released 2014-03-04) * Fixed CVE-2014-0017. * Fixed memory leak with ecdsa signatures. version 0.6.2 (released 2014-03-04) * security: fix for vulnerability CVE-2014-0017 version 0.6.1 (released 2014-02-08) * Added support for libgcrypt 1.6. * Added ssh_channel_accept_forward(). * Added known_hosts heuristic during connection (#138). * Added getters for session cipher names. * Fixed decrypt of zero length buffer. * Fixed padding in RSA signature blobs. * Fixed DSA signature extraction. * Fixed some memory leaks. * Fixed read of non-connected socket. * Fixed thread dectection. version 0.6.0 (released 2014-01-08) * Added new publicy key API. * Added new userauth API. * Added ssh_get_publickey_hash() function. * Added ssh_get_poll_flags() function. * Added gssapi-mic userauth. * Added GSSAPIServerIdentity option. * Added GSSAPIClientIdentity option. * Added GSSAPIDelegateCredentials option. * Added new callback based server API. * Added Elliptic Curve DSA (ECDSA) support (with OpenSSL). * Added Elliptic Curve Diffie Hellman (ECDH) support. * Added Curve25519 for ECDH key exchange. * Added improved logging system. * Added SSH-agent forwarding. * Added key-reexchange. * Added more unit tests. * Improved documentation. * Fixed timeout handling. version 0.5.5 (released 2013-07-26) * BUG 103: Fix ProxyCommand parsing. * Fix setting -D_FORTIFY_SOURCE=2. * Fix pollset error return if emtpy. * Fix NULL pointer checks in channel functions. * Several bugfixes. version 0.5.4 (released 2013-01-22) * CVE-2013-0176 - NULL dereference leads to denial of service * Fixed several NULL pointer dereferences in SSHv1. * Fixed a free crash bug in options parsing. version 0.5.3 (released 2012-11-20) * CVE-2012-4559 Fixed multiple double free() flaws. * CVE-2012-4560 Fixed multiple buffer overflow flaws. * CVE-2012-4561 Fixed multiple invalid free() flaws. * BUG #84 - Fix bug in sftp_mkdir not returning on error. * BUG #85 - Fixed a possible channel infinite loop if the connection dropped. * BUG #88 - Added missing channel request_state and set it to accepted. * BUG #89 - Reset error state to no error on successful SSHv1 authentiction. * Fixed a possible use after free in ssh_free(). * Fixed multiple possible NULL pointer dereferences. * Fixed multiple memory leaks in error paths. * Fixed timeout handling. * Fixed regression in pre-connected socket setting. * Handle all unknown global messages. version 0.5.2 (released 2011-09-17) * Increased window size x10. * Fixed SSHv1. * Fixed bugged lists. * Fixed use-after-free + inconsistent callbacks call in poll. * Fixed scp documentation. * Fixed possible infinite loop in channel_read(). * Fixed handling of short reads of sftp_async_read(). * Fixed handling request service timeout in blocking mode. * Fixed ssh_auth_list() documentation. * Fixed incorrect return values in ssh_channel_write(). * Fixed an infinite loop in the termination callback. * Fixed handling of SSH_AGAIN in channel_open(). * Fixed "status -5 inflating zlib packet" version 0.5.1 (released 2011-08-09) * Added checks for NULL pointers in string.c. * Set the channel max packet size to 32768. * Don't (de)compress empty buffers. * Fixed ssh_scp_write so it works when doing recursive copy. * Fixed another source of endless wait. * Fixed an endless loop in case of a channel_open error. * Fixed session timeout handling. * Fixed ssh_channel_from_local() loop. * Fixed permissions of scp example when we copy a file. * Workaround ssh_get_user_home_dir on LDAP users. * Added pkg-config support for libssh_threads. * Fixed compilation without server and sftp modes. * Fix static .lib overwriting on Windows. version 0.5.0 (released 2011-06-01) * Added ssh_ prefix to all functions. * Added complete Windows support. * Added improved server support. * Added unit tests for a lot of functions. * Added asynchronous service request. * Added a multiplatform ssh_getpass() function. * Added a tutorial. * Added a lot of documentation. * Fixed a lot of bugs. * Fixed several memory leaks. version 0.4.8 (released 2011-01-15) * Fixed memory leaks in session signing. * Fixed memory leak in ssh_print_hexa. * Fixed problem with ssh_connect w/ timeout and fd > 1024. * Fixed some warnings on OS/2. * Fixed installation path for OS/2. version 0.4.7 (released 2010-12-28) * Fixed a possible memory leak in ssh_get_user_home(). * Fixed a memory leak in sftp_xstat. * Fixed uninitialized fd->revents member. * Fixed timout value in ssh_channel_accept(). * Fixed length checks in ssh_analyze_banner(). * Fixed a possible data overread and crash bug. * Fixed setting max_fd which breaks ssh_select(). * Fixed some pedantic build warnings. * Fixed a memory leak with session->bindaddr. version 0.4.6 (released 2010-09-03) * Added a cleanup function to free the ws2_32 library. * Fixed build with gcc 3.4. * Fixed the Windows build on Vista and newer. * Fixed the usage of WSAPoll() on Windows. * Fixed "@deprecated" in doxygen * Fixed some mingw warnings. * Fixed handling of opened channels. * Fixed keepalive problem on older openssh servers. * Fixed testing for big endian on Windows. * Fixed the Windows preprocessor macros and defines. version 0.4.5 (released 2010-07-13) * Added option to bind a client to an ip address. * Fixed the ssh socket polling function. * Fixed Windows related bugs in bsd_poll(). * Fixed serveral build warnings. version 0.4.4 (released 2010-06-01) * Fixed a bug in the expand function for escape sequences. * Fixed a bug in the tilde expand function. * Fixed a bug in setting the options. version 0.4.3 (released 2010-05-18) * Added global/keepalive responses. * Added runtime detection of WSAPoll(). * Added a select(2) based poll-emulation if poll(2) is not available. * Added a function to expand an escaped string. * Added a function to expand the tilde from a path. * Added a proxycommand support. * Added ssh_privatekey_type public function * Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR. * Fixed sftp_chown. * Fixed sftp_rename on protocol version 3. * Fixed a blocking bug in channel_poll. * Fixed config parsing wich has overwritten user specified values. * Fixed hashed [host]:port format in knownhosts * Fixed Windows build. * Fixed doublefree happening after a negociation error. * Fixed aes*-ctr with <= OpenSSL 0.9.7b. * Fixed some documentation. * Fixed exec example which has broken read usage. * Fixed broken algorithm choice for server. * Fixed a typo that we don't export all symbols. * Removed the unneeded dependency to doxygen. * Build examples only on the Linux plattform. version 0.4.2 (released 2010-03-15) * Added owner and group information in sftp attributes. * Added missing SSH_OPTIONS_FD option. * Added printout of owner and group in the sftp example. * Added a prepend function for ssh_list. * Added send back replies to openssh's keepalives. * Fixed documentation in scp code * Fixed longname parsing, this only workings with readdir. * Fixed and added support for several identity files. * Fixed sftp_parse_longname() on Windows. * Fixed a race condition bug in ssh_scp_close() * Remove config support for SSHv1 Cipher variable. * Rename ssh_list_add to ssh_list_append. * Rename ssh_list_get_head to ssh_list_pop_head version 0.4.1 (released 2010-02-13) * Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption. * Added an example for exec. * Added private key type detection feature in privatekey_from_file(). * Fixed zlib compression fallback. * Fixed kex bug that client preference should be prioritary * Fixed known_hosts file set by the user. * Fixed a memleak in channel_accept(). * Fixed underflow when leave_function() are unbalanced * Fixed memory corruption in handle_channel_request_open(). * Fixed closing of a file handle case of errors in privatekey_from_file(). * Fixed ssh_get_user_home_dir() to be thread safe. * Fixed the doxygen documentation. version 0.4.0 (released 2009-12-10) * Added scp support. * Added support for sending signals (RFC 4254, section 6.9). * Added MSVC support. * Added support for ~/.ssh/config. * Added sftp extension support. * Added X11 forwarding support for client. * Added forward listening. * Added support for openssh extensions (statvfs, fstatvfs). * Added a cleaned up interface for setting options. * Added a generic way to handle sockets asynchronously. * Added logging of the sftp flags used to open a file. * Added full poll() support and poll-emulation for win32. * Added missing 64bit functions in sftp. * Added support for ~/ and SSH_DIR/ in filenames instead of %s/. * Fixed Fix channel_get_exit_status bug. * Fixed calltrace logging to make it optional. * Fixed compilation on Solaris. * Fixed resolving of ip addresses. * Fixed libssh compilation without server support. * Fixed possible memory corruptions (ticket #14). version 0.3.4 (released 2009-09-14) * Added ssh_basename and ssh_dirname. * Added a portable ssh_mkdir function. * Added a sftp_tell64() function. * Added missing NULL pointer checks to crypt_set_algorithms_server. * Fixed ssh_write_knownhost if ~/.ssh doesn't exist. * Fixed a possible integer overflow in buffer_get_data(). * Fixed possible security bug in packet_decrypt(). * Fixed a possible stack overflow in agent code. version 0.3.3 (released 2009-08-18) * Fixed double free pointer crash in dsa_public_to_string. * Fixed channel_get_exit_status bug. * Fixed ssh_finalize which didn't clear the flag. * Fixed memory leak introduced by previous bugfix. * Fixed channel_poll broken when delayed EOF recvd. * Fixed stupid "can't parse known host key" bug. * Fixed possible memory corruption (ticket #14). version 0.3.2 (released 2009-08-05) * Added ssh_init() function. * Added sftp_readlink() function. * Added sftp_symlink() function. * Fixed ssh_write_knownhost(). * Fixed compilation on Solaris. * Fixed SSHv1 compilation. version 0.3.1 (released 2009-07-14) * Added return code SSH_SERVER_FILE_NOT_FOUND. * Fixed compilation of SSHv1. * Fixed several memory leaks. * Fixed possible infinite loops. * Fixed a possible crash bug. * Fixed build warnings. * Fixed cmake on BSD. version 0.3.1 (released 2009-07-14) * Added return code SSH_SERVER_FILE_NOT_FOUND. * Fixed compilation of SSHv1. * Fixed several memory leaks. * Fixed possible infinite loops. * Fixed a possible crash bug. * Fixed build warnings. * Fixed cmake on BSD. version 0.3 (released 2009-05-21) * Added support for ssh-agent authentication. * Added POSIX like sftp implementation. * Added error checking to all functions. * Added const to arguments where it was needed. * Added a channel_get_exit_status() function. * Added a channel_read_buffer() function, channel_read() is now a POSIX like function. * Added a more generic auth callback function. * Added printf attribute checking for log and error functions. * Added runtime function tracer support. * Added NSIS build support with CPack. * Added openssh hashed host support. * Added API documentation for all public functions. * Added asynchronous SFTP read function. * Added a ssh_bind_set_fd() function. * Fixed known_hosts parsing. * Fixed a lot of build warnings. * Fixed the Windows build. * Fixed a lot of memory leaks. * Fixed a double free corruption in the server support. * Fixed the "ssh_accept:" bug in server support. * Fixed important channel bugs. * Refactored the socket handling. * Switched to CMake build system. * Improved performance. version 0.2 (released 2007-11-29) * General cleanup * More comprehensive API * Up-to-date Doxygen documentation of each public function * Basic server-based support * Libgcrypt support (alternative to openssl and its license) * SSH1 support (disabled by default) * Added 3des-cbc * A lot of bugfixes version 0.11-dev * Server implementation development. * Small bug corrected when connecting to sun ssh servers. * Channel wierdness corrected (writing huge data packets) * Channel_read_nonblocking added * Channel bug where stderr wasn't correctly read fixed. * Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO * Connect_status callback. * Priv.h contains the internal functions, libssh.h the public interface * Options_set_timeout (thx marcelo) really working. * Tcp tunneling through channel_open_forward. * Channel_request_exec() * Channel_request_env() * Ssh_get_pubkey_hash() * Ssh_is_server_known() * Ssh_write_known_host() * Options_set_ssh_dir * How could this happen ! there weren't any channel_close ! * Nasty channel_free bug resolved. * Removed the unsigned long all around the code. use only u8,u32 & u64. * It now compiles and runs under amd64 ! * Channel_request_pty_size * Channel_change_pty_size * Options_copy() * Ported the doc to an HTML file. * Small bugfix in packet.c * Prefixed error constants with SSH_ * Sftp_stat, sftp_lstat, sftp_fstat. thanks Michel Bardiaux for the patch. * Again channel number mismatch fixed. * Fixed a bug in ssh_select making the select fail when a signal has been caught. * Keyboard-interactive authentication working. version 0.1 (released 2004-03-05) * Begining of sftp subsystem implementation. * Some cleanup into channels implementation * Now every channel functions is called by its CHANNEL handler. * Added channel_poll() and channel_read(). * Changed the client so it uses the new channel_poll and channel_read interface * Small use-after-free bug with channels resolved * Changed stupidities in lot of function names. * Removed a debug output file opened by default. * Added API.txt, the libssh programmer handbook. * Various bug fixes from Nick Zitzmann. * Developed a cryptographic structure for handling protocols. * An autoconf script which took me half of a day to set up. * A ssh_select wrapper has been written. version 0.0.4 (released 2003-10-10) * Some terminal code (eof handling) added * Channels bugfix (it still needs some tweaking though) * Zlib support * Added a wrapper.c file. The goal is to provide a similar API to every cryptographic functions. bignums and sha/md5 are wrapped now. * More work than it first looks. * Support for other crypto libs planed (lighter libs) * Fixed stupid select() bug. * Libssh now compiles and links with openssl 0.9.6 * RSA pubkey authentication code now works ! version 0.0.3 (released 2003-09-15) * Added install target in makefile * Some cleanup in headers files and source code * Change default banner and project name to libssh. * New file auth.c to support more and more authentication ways * Bugfix(read offbyone) in send_kex * A base64 parser. don't read the source, it's awful. pure 0xbadc0de. * Changed the client filename to "ssh". logic isn't it ? * Dss publickey authentication ! still need to wait for the rsa one * Bugfix in packet.c * New misc.c contains misc functions version 0.0.2 (released 2003-09-03) * Initial release. * Client supports both ssh and dss hostkey verification, but doesn't compare them to openssh's files. (~/.ssh/known_hosts) * The only supported authentication method is password. * Compiles on linux and openbsd. freebsd and netbsd should work, too * Lot of work which hasn't been discussed here. ================================================ FILE: src/libssh/CompilerChecks.cmake ================================================ include(AddCCompilerFlag) include(CheckCCompilerFlagSSP) if (UNIX) # # Check for -Werror turned on if possible # # This will prevent that compiler flags are detected incorrectly. # check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR) if (REQUIRED_FLAGS_WERROR) set(CMAKE_REQUIRED_FLAGS "-Werror") if (PICKY_DEVELOPER) list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror") endif() endif() add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS) #add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wsign-compare" SUPPORTED_COMPILER_FLAGS) check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT) if (REQUIRED_FLAGS_WFORMAT) list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat") set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat") endif() add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS) # Allow zero for a variadic macro argument string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID) if ("${_C_COMPILER_ID}" STREQUAL "clang") add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS) endif() add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS) if (CMAKE_BUILD_TYPE) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel)) add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS) endif() endif() check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG) if (WITH_STACK_PROTECTOR_STRONG) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong") # This is needed as Solaris has a seperate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong") endif() else (WITH_STACK_PROTECTOR_STRONG) check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR) if (WITH_STACK_PROTECTOR) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector") # This is needed as Solaris has a seperate libssp if (SOLARIS) list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector") endif() endif() endif (WITH_STACK_PROTECTOR_STRONG) check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION) if (WITH_STACK_CLASH_PROTECTION) list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection") endif() if (PICKY_DEVELOPER) add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS) endif() add_c_compiler_flag("-Wno-deprecated-declarations" DEPRECATION_COMPILER_FLAGS) # Unset CMAKE_REQUIRED_FLAGS unset(CMAKE_REQUIRED_FLAGS) endif() if (MSVC) add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS) add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS) endif() # This removes this annoying warning # "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]" if (OSX) add_c_compiler_flag("-Wno-deprecated-declarations" SUPPORTED_COMPILER_FLAGS) endif() set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE) set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE) if (DEPRECATION_COMPILER_FLAGS) set(DEFAULT_C_NO_DEPRECATION_FLAGS ${DEPRECATION_COMPILER_FLAGS} CACHE INTERNAL "Default no deprecation flags" FORCE) endif() ================================================ FILE: src/libssh/ConfigureChecks.cmake ================================================ include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckSymbolExists) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckTypeSize) include(CheckStructHasMember) include(TestBigEndian) set(PACKAGE ${PROJECT_NAME}) set(VERSION ${PROJECT_VERSION}) set(SYSCONFDIR ${CMAKE_INSTALL_SYSCONFDIR}) set(BINARYDIR ${CMAKE_BINARY_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR}) function(COMPILER_DUMPVERSION _OUTPUT_VERSION) # Remove whitespaces from the argument. # This is needed for CC="ccache gcc" cmake .. string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}") execute_process( COMMAND ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion OUTPUT_VARIABLE _COMPILER_VERSION ) string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" _COMPILER_VERSION "${_COMPILER_VERSION}") set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) endfunction() if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) compiler_dumpversion(GNUCC_VERSION) if (NOT GNUCC_VERSION EQUAL 34) set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden") check_c_source_compiles( "void __attribute__((visibility(\"default\"))) test() {} int main(void){ return 0; } " WITH_VISIBILITY_HIDDEN) unset(CMAKE_REQUIRED_FLAGS) endif (NOT GNUCC_VERSION EQUAL 34) endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) # HEADER FILES set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARGP_INCLUDE_DIR}) check_include_file(argp.h HAVE_ARGP_H) unset(CMAKE_REQUIRED_INCLUDES) check_include_file(pty.h HAVE_PTY_H) check_include_file(utmp.h HAVE_UTMP_H) check_include_file(termios.h HAVE_TERMIOS_H) check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(stdint.h HAVE_STDINT_H) check_include_file(util.h HAVE_UTIL_H) check_include_file(libutil.h HAVE_LIBUTIL_H) check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/utime.h HAVE_SYS_UTIME_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H) check_include_file(arpa/inet.h HAVE_ARPA_INET_H) check_include_file(byteswap.h HAVE_BYTESWAP_H) check_include_file(glob.h HAVE_GLOB_H) check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H) if (WIN32) check_include_file(io.h HAVE_IO_H) check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H) if (NOT HAVE_WSPIAPI_H) message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions") endif (NOT HAVE_WSPIAPI_H) check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H) endif (WIN32) if (OPENSSL_FOUND) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/des.h HAVE_OPENSSL_DES_H) if (NOT HAVE_OPENSSL_DES_H) message(FATAL_ERROR "Could not detect openssl/des.h") endif() set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H) if (NOT HAVE_OPENSSL_AES_H) message(FATAL_ERROR "Could not detect openssl/aes.h") endif() if (WITH_BLOWFISH_CIPHER) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H) endif() set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY) check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519) if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND FOUND_OPENSSL_ED25519) set(HAVE_OPENSSL_ED25519 1) endif() set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) endif() if (CMAKE_HAVE_PTHREAD_H) set(HAVE_PTHREAD_H 1) endif (CMAKE_HAVE_PTHREAD_H) if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS) if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H) set(HAVE_OPENSSL_ECC 1) endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H) if (HAVE_OPENSSL_ECC) set(HAVE_ECC 1) endif (HAVE_OPENSSL_ECC) endif () if (NOT WITH_MBEDTLS) set(HAVE_DSA 1) endif (NOT WITH_MBEDTLS) # FUNCTIONS check_function_exists(isblank HAVE_ISBLANK) check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(strndup HAVE_STRNDUP) check_function_exists(strtoull HAVE_STRTOULL) check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO) check_function_exists(memset_s HAVE_MEMSET_S) if (HAVE_GLOB_H) check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_GL_FLAGS_MEMBER) check_function_exists(glob HAVE_GLOB) endif (HAVE_GLOB_H) if (NOT WIN32) check_function_exists(vsnprintf HAVE_VSNPRINTF) check_function_exists(snprintf HAVE_SNPRINTF) endif (NOT WIN32) if (WIN32) check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF) check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) check_symbol_exists(_vsnprintf_s "stdio.h" HAVE__VSNPRINTF_S) check_symbol_exists(_vsnprintf "stdio.h" HAVE__VSNPRINTF) check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF) check_symbol_exists(_snprintf_s "stdio.h" HAVE__SNPRINTF_S) if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL) check_symbol_exists(htonll winsock2.h HAVE_HTONLL) set(CMAKE_REQUIRED_LIBRARIES ws2_32) check_symbol_exists(select "winsock2.h;ws2tcpip.h" HAVE_SELECT) check_symbol_exists(poll "winsock2.h;ws2tcpip.h" HAVE_SELECT) # The getaddrinfo function is defined to the WspiapiGetAddrInfo inline function check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO) unset(CMAKE_REQUIRED_LIBRARIES) endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) check_function_exists(_strtoui64 HAVE__STRTOUI64) set(HAVE_SELECT TRUE) check_symbol_exists(SecureZeroMemory "windows.h" HAVE_SECURE_ZERO_MEMORY) else (WIN32) check_function_exists(poll HAVE_POLL) check_function_exists(select HAVE_SELECT) check_function_exists(getaddrinfo HAVE_GETADDRINFO) check_symbol_exists(ntohll arpa/inet.h HAVE_NTOHLL) check_symbol_exists(htonll arpa/inet.h HAVE_HTONLL) endif (WIN32) if (UNIX) if (NOT LINUX) # libsocket (Solaris) check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET) if (HAVE_LIBSOCKET) set(HAVE_GETADDRINFO TRUE) set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} socket) endif (HAVE_LIBSOCKET) # libnsl/inet_pton (Solaris) check_library_exists(nsl inet_pton "" HAVE_LIBNSL) if (HAVE_LIBNSL) set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} nsl) endif (HAVE_LIBNSL) # librt check_library_exists(rt nanosleep "" HAVE_LIBRT) endif (NOT LINUX) check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME) if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME) set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} rt) endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME) check_library_exists(util forkpty "" HAVE_LIBUTIL) check_function_exists(cfmakeraw HAVE_CFMAKERAW) check_function_exists(__strtoull HAVE___STRTOULL) endif (UNIX) set(LIBSSH_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries") # LIBRARIES if (OPENSSL_FOUND) set(HAVE_LIBCRYPTO 1) endif (OPENSSL_FOUND) if (GCRYPT_FOUND) set(HAVE_LIBGCRYPT 1) if (GCRYPT_VERSION VERSION_GREATER "1.4.6") set(HAVE_GCRYPT_ECC 1) set(HAVE_ECC 1) endif (GCRYPT_VERSION VERSION_GREATER "1.4.6") endif (GCRYPT_FOUND) if (MBEDTLS_FOUND) set(HAVE_LIBMBEDCRYPTO 1) set(HAVE_ECC 1) endif (MBEDTLS_FOUND) if (CMAKE_USE_PTHREADS_INIT) set(HAVE_PTHREAD 1) endif (CMAKE_USE_PTHREADS_INIT) if (UNIT_TESTING) if (CMOCKA_FOUND) set(CMAKE_REQUIRED_LIBRARIES ${CMOCKA_LIBRARIES}) check_function_exists(cmocka_set_test_filter HAVE_CMOCKA_SET_TEST_FILTER) unset(CMAKE_REQUIRED_LIBRARIES) endif () endif () # OPTIONS check_c_source_compiles(" __thread int tls; int main(void) { return 0; }" HAVE_GCC_THREAD_LOCAL_STORAGE) check_c_source_compiles(" __declspec(thread) int tls; int main(void) { return 0; }" HAVE_MSC_THREAD_LOCAL_STORAGE) ########################################################### # For detecting attributes we need to treat warnings as # errors if (UNIX OR MINGW) # Get warnings for attributs check_c_compiler_flag("-Wattributes" REQUIRED_FLAGS_WERROR) if (REQUIRED_FLAGS_WERROR) string(APPEND CMAKE_REQUIRED_FLAGS "-Wattributes ") endif() # Turn warnings into errors check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR) if (REQUIRED_FLAGS_WERROR) string(APPEND CMAKE_REQUIRED_FLAGS "-Werror ") endif() endif () check_c_source_compiles(" void test_constructor_attribute(void) __attribute__ ((constructor)); void test_constructor_attribute(void) { return; } int main(void) { return 0; }" HAVE_CONSTRUCTOR_ATTRIBUTE) check_c_source_compiles(" void test_destructor_attribute(void) __attribute__ ((destructor)); void test_destructor_attribute(void) { return; } int main(void) { return 0; }" HAVE_DESTRUCTOR_ATTRIBUTE) check_c_source_compiles(" #define FALL_THROUGH __attribute__((fallthrough)) int main(void) { int i = 2; switch (i) { case 0: FALL_THROUGH; case 1: break; default: break; } return 0; }" HAVE_FALLTHROUGH_ATTRIBUTE) if (NOT WIN32) check_c_source_compiles(" #define __unused __attribute__((unused)) static int do_nothing(int i __unused) { return 0; } int main(void) { int i; i = do_nothing(5); if (i > 5) { return 1; } return 0; }" HAVE_UNUSED_ATTRIBUTE) endif() check_c_source_compiles(" #include int main(void) { char buf[] = \"This is some content\"; memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"g\"(&buf) : \"memory\"); return 0; }" HAVE_GCC_VOLATILE_MEMORY_PROTECTION) check_c_source_compiles(" #include int main(void) { printf(\"%s\", __func__); return 0; }" HAVE_COMPILER__FUNC__) check_c_source_compiles(" #include int main(void) { printf(\"%s\", __FUNCTION__); return 0; }" HAVE_COMPILER__FUNCTION__) # This is only available with OpenBSD's gcc implementation */ if (OPENBSD) check_c_source_compiles(" #define ARRAY_LEN 16 void test_attr(const unsigned char *k) __attribute__((__bounded__(__minbytes__, 2, 16))); int main(void) { return 0; }" HAVE_GCC_BOUNDED_ATTRIBUTE) endif(OPENBSD) # Stop treating warnings as errors unset(CMAKE_REQUIRED_FLAGS) # Check for version script support file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 { global: sym; }; VERS_2 { global: sym; } VERS_1; ") set(CMAKE_REQUIRED_FLAGS "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/conftest.map\"") check_c_source_compiles("int main(void) { return 0; }" HAVE_LD_VERSION_SCRIPT) unset(CMAKE_REQUIRED_FLAGS) file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map") if (WITH_DEBUG_CRYPTO) set(DEBUG_CRYPTO 1) endif (WITH_DEBUG_CRYPTO) if (WITH_DEBUG_PACKET) set(DEBUG_PACKET 1) endif (WITH_DEBUG_PACKET) if (WITH_DEBUG_CALLTRACE) set(DEBUG_CALLTRACE 1) endif (WITH_DEBUG_CALLTRACE) if (WITH_GSSAPI AND NOT GSSAPI_FOUND) set(WITH_GSSAPI 0) endif (WITH_GSSAPI AND NOT GSSAPI_FOUND) # ENDIAN if (NOT WIN32) test_big_endian(WORDS_BIGENDIAN) endif (NOT WIN32) ================================================ FILE: src/libssh/DefineOptions.cmake ================================================ option(WITH_GSSAPI "Build with GSSAPI support" ON) option(WITH_ZLIB "Build with ZLIB support" ON) option(WITH_SFTP "Build with SFTP support" ON) option(WITH_SERVER "Build with SSH server support" ON) option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF) option(WITH_DEBUG_PACKET "Build with packet debug output" OFF) option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON) option(WITH_GCRYPT "Compile against libgcrypt" OFF) option(WITH_MBEDTLS "Compile against libmbedtls" OFF) option(WITH_BLOWFISH_CIPHER "Compile with blowfish support" OFF) option(WITH_PCAP "Compile with Pcap generation support" ON) option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF) option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(UNIT_TESTING "Build with unit tests" OFF) option(CLIENT_TESTING "Build with client tests; requires openssh" OFF) option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF) option(WITH_BENCHMARKS "Build benchmarks tools" OFF) option(WITH_EXAMPLES "Build examples" ON) option(WITH_NACL "Build with libnacl (curve25519)" ON) option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON) option(WITH_ABI_BREAK "Allow ABI break" OFF) option(WITH_GEX "Enable DH Group exchange mechanisms" ON) option(FUZZ_TESTING "Build with fuzzer for the server" OFF) option(PICKY_DEVELOPER "Build with picky developer flags" OFF) if (WITH_ZLIB) set(WITH_LIBZ ON) else (WITH_ZLIB) set(WITH_LIBZ OFF) endif (WITH_ZLIB) if (WITH_BENCHMARKS) set(UNIT_TESTING ON) set(CLIENT_TESTING ON) endif() if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING) set(BUILD_STATIC_LIB ON) endif() if (WITH_NACL) set(WITH_NACL ON) endif (WITH_NACL) if (WITH_ABI_BREAK) set(WITH_SYMBOL_VERSIONING ON) endif (WITH_ABI_BREAK) if (NOT GLOBAL_BIND_CONFIG) set(GLOBAL_BIND_CONFIG "/etc/ssh/libssh_server_config") endif (NOT GLOBAL_BIND_CONFIG) if (NOT GLOBAL_CLIENT_CONFIG) set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config") endif (NOT GLOBAL_CLIENT_CONFIG) ================================================ FILE: src/libssh/INSTALL ================================================ # How to build from source ## Requirements ### Common requirements In order to build libssh, you need to install several components: - A C compiler - [CMake](https://www.cmake.org) >= 2.6.0. - [openssl](https://www.openssl.org) >= 0.9.8 or - [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4 - [libz](https://www.zlib.net) >= 1.2 optional: - [cmocka](https://cmocka.org/) >= 1.1.0 - [socket_wrapper](https://cwrap.org/) >= 1.1.5 - [nss_wrapper](https://cwrap.org/) >= 1.1.2 - [uid_wrapper](https://cwrap.org/) >= 1.2.0 - [pam_wrapper](https://cwrap.org/) >= 1.0.1 Note that these version numbers are version we know works correctly. If you build and run libssh successfully with an older version, please let us know. For Windows use vcpkg: https://github.com/Microsoft/vcpkg which you can use to install openssl and zlib. libssh itself is also part of vcpkg! ## Building First, you need to configure the compilation, using CMake. Go inside the `build` dir. Create it if it doesn't exist. GNU/Linux, MacOS X, MSYS/MinGW: cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. make On Windows you should choose a makefile gernerator with -G or use cmake-gui.exe .. To enable additional client tests against a local OpenSSH server, add the compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH server package and some wrapper libraries (see optional requirements) to be installed. If you're interested in server testing, then a OpenSSH client should be installed on the system and if possible also dropbear. Once that is done enable server support with -DWITH_SERVER=ON and enable testing of it with -DSERVER_TESTING=ON. ## Testing build make test ### CMake standard options Here is a list of the most interesting options provided out of the box by CMake. - CMAKE_BUILD_TYPE: The type of build (can be Debug Release MinSizeRel RelWithDebInfo) - CMAKE_INSTALL_PREFIX: The prefix to use when running make install (Default to /usr/local on GNU/Linux and MacOS X) - CMAKE_C_COMPILER: The path to the C compiler - CMAKE_CXX_COMPILER: The path to the C++ compiler ### CMake options defined for libssh Options are defined in the following files: - DefineOptions.cmake They can be changed with the -D option: `cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_ZLIB=OFF ..` ### Browsing/editing CMake options In addition to passing options on the command line, you can browse and edit CMake options using `cmakesetup` (Windows), `cmake-gui` or `ccmake` (GNU/Linux and MacOS X). - Go to the build dir - On Windows: run `cmakesetup` - On GNU/Linux and MacOS X: run `ccmake ..` ### Useful Windows options: If you have installed OpenSSL or ZLIB in non standard directories, maybe you want to set: OPENSSL_ROOT_DIR and ZLIB_ROOT_DIR ## Installing If you want to install libssh after compilation run: make install ## Running The libssh binary can be found in the `build/src` directory. You can use `build/examples/samplessh` which is a sample client to test libssh on UNIX. ## About this document This document is written using [Markdown][] syntax, making it possible to provide usable information in both plain text and HTML format. Whenever modifying this document please use [Markdown][] syntax. [markdown]: https://www.daringfireball.net/projects/markdown ================================================ FILE: src/libssh/README ================================================ _ _ _ _ (_) (_) (_) (_) (_) _ (_) _ _ _ _ _ (_) _ (_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _ (_) (_) (_) (_) _ (_) _ (_) (_) (_) (_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org The SSH library ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1* Why ? -_-_-_-_-_ Why not ? :) I've began to work on my own implementation of the ssh protocol because i didn't like the currently public ones. Not any allowed you to import and use the functions as a powerful library, and so i worked on a library-based SSH implementation which was non-existing in the free and open source software world. 2* How/Who ? -_-_-_-_-_-_-_ If you downloaded this file, you must know what it is : a library for accessing ssh client services through C libraries calls in a simple manner. Everybody can use this software under the terms of the LGPL - see the COPYING file If you ask yourself how to compile libssh, please read INSTALL before anything. 3* Where ? -_-_-_-_-_-_ https://www.libssh.org 4* Contributing -_-_-_-_-_-_-_-_-_ Please read the file 'SubmittingPatches' next to this README file. It explains our copyright policy and how you should send patches for upstream inclusion. Have fun and happy libssh hacking! The libssh Team ================================================ FILE: src/libssh/README.CodingStyle ================================================ Coding conventions in the libssh tree ====================================== =========== Quick Start =========== Coding style guidelines are about reducing the number of unnecessary reformatting patches and making things easier for developers to work together. You don't have to like them or even agree with them, but once put in place we all have to abide by them (or vote to change them). However, coding style should never outweigh coding itself and so the guidelines described here are hopefully easy enough to follow as they are very common and supported by tools and editors. The basic style for C code, is the Linux kernel coding style (See Documentation/CodingStyle in the kernel source tree). This closely matches what libssh developers use already anyways, with a few exceptions as mentioned below. But to save you the trouble of reading the Linux kernel style guide, here are the highlights. * Maximum Line Width is 80 Characters The reason is not about people with low-res screens but rather sticking to 80 columns prevents you from easily nesting more than one level of if statements or other code blocks. * Use 4 Spaces to Indent * No Trailing Whitespace Clean up your files before committing. * Follow the K&R guidelines. We won't go through all of them here. Do you have a copy of "The C Programming Language" anyways right? ============= Editor Hints ============= Emacs ------ Add the follow to your $HOME/.emacs file: (add-hook 'c-mode-hook (lambda () (c-set-style "linux") (c-toggle-auto-state))) Vim ---- For the basic vi editor included with all variants of \*nix, add the following to $HOME/.vimrc: set ts=4 sw=4 et cindent You can use the Vim gitmodline plugin to store this in the git config: https://git.cryptomilk.org/projects/vim-gitmodeline.git/ For Vim, the following settings in $HOME/.vimrc will also deal with displaying trailing whitespace: if has("syntax") && (&t_Co > 2 || has("gui_running")) syntax on function! ActivateInvisibleCharIndicator() syntax match TrailingSpace "[ \t]\+$" display containedin=ALL highlight TrailingSpace ctermbg=Red endf autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator() endif " Show tabs, trailing whitespace, and continued lines visually set list listchars=tab:»·,trail:·,extends:… " highlight overly long lines same as TODOs. set textwidth=80 autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/' ========================== FAQ & Statement Reference ========================== Comments --------- Comments should always use the standard C syntax. C++ style comments are not currently allowed. The lines before a comment should be empty. If the comment directly belongs to the following code, there should be no empty line after the comment, except if the comment contains a summary of multiple following code blocks. This is good: ... int i; /* * This is a multi line comment, * which explains the logical steps we have to do: * * 1. We need to set i=5, because... * 2. We need to call complex_fn1 */ /* This is a one line comment about i = 5. */ i = 5; /* * This is a multi line comment, * explaining the call to complex_fn1() */ ret = complex_fn1(); if (ret != 0) { ... /** * @brief This is a doxygen comment. * * This is a more detailed explanation of * this simple function. * * @param[in] param1 The parameter value of the function. * * @param[out] result1 The result value of the function. * * @return 0 on success and -1 on error. */ int example(int param1, int *result1); This is bad: ... int i; /* * This is a multi line comment, * which explains the logical steps we have to do: * * 1. We need to set i=5, because... * 2. We need to call complex_fn1 */ /* This is a one line comment about i = 5. */ i = 5; /* * This is a multi line comment, * explaining the call to complex_fn1() */ ret = complex_fn1(); if (ret != 0) { ... /*This is a one line comment.*/ /* This is a multi line comment, with some more words...*/ /* * This is a multi line comment, * with some more words...*/ Indention & Whitespace & 80 columns ------------------------------------ To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When wrapping parameters for function calls, align the parameter list with the first parameter on the previous line. For example, var1 = foo(arg1, arg2, arg3); The previous example is intended to illustrate alignment of function parameters across lines and not as encourage for gratuitous line splitting. Never split a line before columns 70 - 79 unless you have a really good reason. Be smart about formatting. If, switch, & Code blocks -------------------------- Always follow an 'if' keyword with a space but don't include additional spaces following or preceding the parentheses in the conditional. This is good: if (x == 1) This is bad: if ( x == 1 ) or if (x==1) Yes we have a lot of code that uses the second and third form and we are trying to clean it up without being overly intrusive. Note that this is a rule about parentheses following keywords and not functions. Don't insert a space between the name and left parentheses when invoking functions. Braces for code blocks used by for, if, switch, while, do..while, etc. should begin on the same line as the statement keyword and end on a line of their own. You should always include braces, even if the block only contains one statement. NOTE: Functions are different and the beginning left brace should be located in the first column on the next line. If the beginning statement has to be broken across lines due to length, the beginning brace should be on a line of its own. The exception to the ending rule is when the closing brace is followed by another language keyword such as else or the closing while in a do..while loop. Good examples: if (x == 1) { printf("good\n"); } for (x = 1; x < 10; x++) { print("%d\n", x); } for (really_really_really_really_long_var_name = 0; really_really_really_really_long_var_name < 10; really_really_really_really_long_var_name++) { print("%d\n", really_really_really_really_long_var_name); } do { printf("also good\n"); } while (1); Bad examples: while (1) { print("I'm in a loop!\n"); } for (x=1; x<10; x++) { print("no good\n"); } if (i < 10) print("I should be in braces.\n"); Goto ----- While many people have been academically taught that "goto"s are fundamentally evil, they can greatly enhance readability and reduce memory leaks when used as the single exit point from a function. But in no libssh world what so ever is a goto outside of a function or block of code a good idea. Good Examples: int function foo(int y) { int *z = NULL; int rc = 0; if (y < 10) { z = malloc(sizeof(int)*y); if (z == NULL) { rc = 1; goto done; } } print("Allocated %d elements.\n", y); done: if (z != NULL) { free(z); } return rc; } Initialize pointers ------------------- All pointer variables MUST be initialized to NULL. History has demonstrated that uninitialized pointer variables have lead to various bugs and security issues. Pointers MUST be initialized even if the assignment directly follows the declaration, like pointer2 in the example below, because the instructions sequence may change over time. Good Example: char *pointer1 = NULL; char *pointer2 = NULL; pointer2 = some_func2(); ... pointer1 = some_func1(); Typedefs --------- libssh tries to avoid "typedef struct { .. } x_t;" so we do always try to use "struct x { .. };". We know there are still such typedefs in the code, but for new code, please don't do that anymore. Make use of helper variables ----------------------------- Please try to avoid passing function calls as function parameters in new code. This makes the code much easier to read and it's also easier to use the "step" command within gdb. Good Example: char *name; name = get_some_name(); if (name == NULL) { ... } rc = some_function_my_name(name); ... Bad Example: rc = some_function_my_name(get_some_name()); ... Please try to avoid passing function return values to if- or while-conditions. The reason for this is better handling of code under a debugger. Good example: x = malloc(sizeof(short) * 10); if (x == NULL) { fprintf(stderr, "Unable to alloc memory!\n"); } Bad example: if ((x = malloc(sizeof(short)*10)) == NULL ) { fprintf(stderr, "Unable to alloc memory!\n"); } There are exceptions to this rule. One example is walking a data structure in an iterator style: while ((opt = poptGetNextOpt(pc)) != -1) { ... do something with opt ... } But in general, please try to avoid this pattern. Control-Flow changing macros ----------------------------- Macros like STATUS_NOT_OK_RETURN that change control flow (return/goto/etc) from within the macro are considered bad, because they look like function calls that never change control flow. Please do not introduce them. ================================================ FILE: src/libssh/README.mbedtls ================================================ mbedTLS and libssh in multithreaded applications ================================================== To use libssh with mbedTLS in a multithreaded application, mbedTLS has to be built with threading support enabled. If threading support is not available and multi threading is used, ssh_init will fail. More information about building mbedTLS with threading support can be found in the mbedTLS documentation. ================================================ FILE: src/libssh/README.md ================================================ [![pipeline status](https://gitlab.com/libssh/libssh-mirror/badges/master/pipeline.svg)](https://gitlab.com/libssh/libssh-mirror/commits/master) ``` _ _ _ _ (_) (_) (_) (_) (_) _ (_) _ _ _ _ _ (_) _ (_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _ (_) (_) (_) (_) _ (_) _ (_) (_) (_) (_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org The SSH library ``` # Why? Why not ? :) I've began to work on my own implementation of the ssh protocol because i didn't like the currently public ones. Not any allowed you to import and use the functions as a powerful library, and so i worked on a library-based SSH implementation which was non-existing in the free and open source software world. # How/Who? If you downloaded this file, you must know what it is : a library for accessing ssh client services through C libraries calls in a simple manner. Everybody can use this software under the terms of the LGPL - see the COPYING file If you ask yourself how to compile libssh, please read INSTALL before anything. # Where ? https://www.libssh.org # Contributing Please read the file 'SubmittingPatches' next to this README file. It explains our copyright policy and how you should send patches for upstream inclusion. Have fun and happy libssh hacking! The libssh Team ================================================ FILE: src/libssh/SubmittingPatches ================================================ How to contribute a patch to libssh ==================================== Please checkout the libssh source code using git. Change the code and then use "git format-patch" to create a patch. The patch should be signed (see below) and send it to libssh@libssh.org, or attach it to a bug report at https://red.libssh.org/ For larger code changes, breaking the changes up into a set of simple patches, each of which does a single thing, are much easier to review. Patch sets like that will most likely have an easier time being merged into the libssh code than large single patches that make lots of changes in one large diff. Ownership of the contributed code ================================== libssh is a project with distributed copyright ownership, which means we prefer the copyright on parts of libssh to be held by individuals rather than corporations if possible. There are historical legal reasons for this, but one of the best ways to explain it is that it's much easier to work with individuals who have ownership than corporate legal departments if we ever need to make reasonable compromises with people using and working with libssh. We track the ownership of every part of libssh via https://git.libssh.org, our source code control system, so we know the provenance of every piece of code that is committed to libssh. So if possible, if you're doing libssh changes on behalf of a company who normally owns all the work you do please get them to assign personal copyright ownership of your changes to you as an individual, that makes things very easy for us to work with and avoids bringing corporate legal departments into the picture. If you can't do this we can still accept patches from you owned by your employer under a standard employment contract with corporate copyright ownership. It just requires a simple set-up process first. We use a process very similar to the way things are done in the Linux Kernel community, so it should be very easy to get a sign off from your corporate legal department. The only changes we've made are to accommodate the license we use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2. The process is called signing. How to sign your work ---------------------- Once you have permission to contribute to libssh from your employer, simply email a copy of the following text from your corporate email address to: contributing@libssh.org libssh Developer's Certificate of Origin. Version 1.0 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the appropriate version of the GNU General Public License; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the GNU General Public License, in the appropriate version; or (c) The contribution was provided directly to me by some other person who certified (a) or (b) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all metadata and personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with the libssh Team's policies and the requirements of the GNU GPL where they are relevant. (e) I am granting this work to this project under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at the option of the project) any later version. https://www.gnu.org/licenses/lgpl-2.1.html We will maintain a copy of that email as a record that you have the rights to contribute code to libssh under the required licenses whilst working for the company where the email came from. Then when sending in a patch via the normal mechanisms described above, add a line that states: Signed-off-by: Random J Developer using your real name and the email address you sent the original email you used to send the libssh Developer's Certificate of Origin to us (sorry, no pseudonyms or anonymous contributions.) That's it! Such code can then quite happily contain changes that have copyright messages such as: (c) Example Corporation. and can be merged into the libssh codebase in the same way as patches from any other individual. You don't need to send in a copy of the libssh Developer's Certificate of Origin for each patch, or inside each patch. Just the sign-off message is all that is required once we've received the initial email. Have fun and happy libssh hacking ! The libssh Team ================================================ FILE: src/libssh/cmake/Modules/AddCCompilerFlag.cmake ================================================ # # add_c_compiler_flag("-Werror" SUPPORTED_CFLAGS) # # Copyright (c) 2018 Andreas Schneider # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(CheckCCompilerFlag) macro(add_c_compiler_flag _COMPILER_FLAG _OUTPUT_VARIABLE) string(TOUPPER ${_COMPILER_FLAG} _COMPILER_FLAG_NAME) string(REGEX REPLACE "^-" "" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}") string(REGEX REPLACE "(-|=|\ )" "_" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}") check_c_compiler_flag("${_COMPILER_FLAG}" WITH_${_COMPILER_FLAG_NAME}_FLAG) if (WITH_${_COMPILER_FLAG_NAME}_FLAG) #string(APPEND ${_OUTPUT_VARIABLE} "${_COMPILER_FLAG} ") list(APPEND ${_OUTPUT_VARIABLE} ${_COMPILER_FLAG}) endif() endmacro() ================================================ FILE: src/libssh/cmake/Modules/AddCMockaTest.cmake ================================================ # # Copyright (c) 2007 Daniel Gollub # Copyright (c) 2007-2018 Andreas Schneider # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. #.rst: # AddCMockaTest # ------------- # # This file provides a function to add a test # # Functions provided # ------------------ # # :: # # add_cmocka_test(target_name # SOURCES src1 src2 ... srcN # [COMPILE_OPTIONS opt1 opt2 ... optN] # [LINK_LIBRARIES lib1 lib2 ... libN] # [LINK_OPTIONS lopt1 lop2 .. loptN] # ) # # ``target_name``: # Required, expects the name of the test which will be used to define a target # # ``SOURCES``: # Required, expects one or more source files names # # ``COMPILE_OPTIONS``: # Optional, expects one or more options to be passed to the compiler # # ``LINK_LIBRARIES``: # Optional, expects one or more libraries to be linked with the test # executable. # # ``LINK_OPTIONS``: # Optional, expects one or more options to be passed to the linker # # # Example: # # .. code-block:: cmake # # add_cmocka_test(my_test # SOURCES my_test.c other_source.c # COMPILE_OPTIONS -g -Wall # LINK_LIBRARIES mylib # LINK_OPTIONS -Wl,--enable-syscall-fixup # ) # # Where ``my_test`` is the name of the test, ``my_test.c`` and # ``other_source.c`` are sources for the binary, ``-g -Wall`` are compiler # options to be used, ``mylib`` is a target of a library to be linked, and # ``-Wl,--enable-syscall-fixup`` is an option passed to the linker. # enable_testing() include(CTest) if (CMAKE_CROSSCOMPILING) if (WIN32) find_program(WINE_EXECUTABLE NAMES wine) set(TARGET_SYSTEM_EMULATOR ${WINE_EXECUTABLE}) endif() endif() function(ADD_CMOCKA_TEST _TARGET_NAME) set(one_value_arguments ) set(multi_value_arguments SOURCES COMPILE_OPTIONS LINK_LIBRARIES LINK_OPTIONS ) cmake_parse_arguments(_add_cmocka_test "" "${one_value_arguments}" "${multi_value_arguments}" ${ARGN} ) if (NOT DEFINED _add_cmocka_test_SOURCES) message(FATAL_ERROR "No sources provided for target ${_TARGET_NAME}") endif() add_executable(${_TARGET_NAME} ${_add_cmocka_test_SOURCES}) if (DEFINED _add_cmocka_test_COMPILE_OPTIONS) target_compile_options(${_TARGET_NAME} PRIVATE ${_add_cmocka_test_COMPILE_OPTIONS} ) endif() if (DEFINED _add_cmocka_test_LINK_LIBRARIES) target_link_libraries(${_TARGET_NAME} PRIVATE ${_add_cmocka_test_LINK_LIBRARIES} ) endif() if (DEFINED _add_cmocka_test_LINK_OPTIONS) set_target_properties(${_TARGET_NAME} PROPERTIES LINK_FLAGS ${_add_cmocka_test_LINK_OPTIONS} ) endif() add_test(${_TARGET_NAME} ${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME} ) endfunction (ADD_CMOCKA_TEST) ================================================ FILE: src/libssh/cmake/Modules/COPYING-CMAKE-SCRIPTS ================================================ 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 copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. ================================================ FILE: src/libssh/cmake/Modules/CheckCCompilerFlagSSP.cmake ================================================ # - Check whether the C compiler supports a given flag in the # context of a stack checking compiler option. # CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE) # # FLAG - the compiler flag # VARIABLE - variable to store the result # # This actually calls check_c_source_compiles. # See help for CheckCSourceCompiles for a listing of variables # that can modify the build. # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # Requires cmake 3.10 #include_guard(GLOBAL) include(CheckCSourceCompiles) macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") set(CMAKE_REQUIRED_FLAGS "${_FLAG}") check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT}) set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") endmacro(CHECK_C_COMPILER_FLAG_SSP) ================================================ FILE: src/libssh/cmake/Modules/DefineCMakeDefaults.cmake ================================================ # Always include srcdir and builddir in include path # This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in # about every subdir # since cmake 2.4.0 set(CMAKE_INCLUDE_CURRENT_DIR ON) # Put the include dirs which are in the source or build tree # before all other include dirs, so the headers in the sources # are prefered over the already installed ones # since cmake 2.4.1 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # Use colored output # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) # Create the compile command database for clang by default set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Always build with -fPIC set(CMAKE_POSITION_INDEPENDENT_CODE ON) ================================================ FILE: src/libssh/cmake/Modules/DefineCompilerFlags.cmake ================================================ if (UNIX AND NOT WIN32) # Activate with: -DCMAKE_BUILD_TYPE=Profiling set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the C compiler during PROFILING builds.") set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the CXX compiler during PROFILING builds.") set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.") set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.") set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage" CACHE STRING "Flags used by the linker during PROFILING builds.") # Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.") set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.") # Activate with: -DCMAKE_BUILD_TYPE=MemorySanitizer set(CMAKE_C_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" CACHE STRING "Flags used by the C compiler during MEMORYSANITIZER builds.") set(CMAKE_CXX_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" CACHE STRING "Flags used by the CXX compiler during MEMORYSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" CACHE STRING "Flags used by the linker during MEMORYSANITIZER builds.") # Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover" CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.") set(CMAKE_CXX_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover" CACHE STRING "Flags used by the CXX compiler during UNDEFINEDSANITIZER builds.") set(CMAKE_SHARED_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_MODULE_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.") set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined" CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.") endif() ================================================ FILE: src/libssh/cmake/Modules/DefinePlatformDefaults.cmake ================================================ # Set system vars if (CMAKE_SYSTEM_NAME MATCHES "Linux") set(LINUX TRUE) endif(CMAKE_SYSTEM_NAME MATCHES "Linux") if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set(FREEBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") set(OPENBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") if (CMAKE_SYSTEM_NAME MATCHES "NetBSD") set(NETBSD TRUE) set(BSD TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") set(SOLARIS TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)") if (CMAKE_SYSTEM_NAME MATCHES "OS2") set(OS2 TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "OS2") if (CMAKE_SYSTEM_NAME MATCHES "Darwin") set (OSX TRUE) endif (CMAKE_SYSTEM_NAME MATCHES "Darwin") ================================================ FILE: src/libssh/cmake/Modules/ExtractSymbols.cmake ================================================ # # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # #.rst: # ExtractSymbols # -------------- # # This is a helper script for FindABImap.cmake. # # Extract symbols from header files and output a list to a file. # This script is run in build time to extract symbols from the provided header # files. This way, symbols added or removed can be checked and used to update # the symbol version script. # # All symbols followed by the character ``'('`` are extracted. If a # ``FILTER_PATTERN`` is provided, only the lines containing the given string are # considered. # # Expected defined variables # -------------------------- # # ``HEADERS_LIST_FILE``: # Required, expects a file containing the list of header files to be parsed. # # ``OUTPUT_PATH``: # Required, expects the output file path. # # Optionally defined variables # ---------------------------- # # ``FILTER_PATTERN``: # Expects a string. Only lines containing the given string will be considered # when extracting symbols. # if (NOT DEFINED OUTPUT_PATH) message(SEND_ERROR "OUTPUT_PATH not defined") endif() if (NOT DEFINED HEADERS_LIST_FILE) message(SEND_ERROR "HEADERS not defined") endif() file(READ ${HEADERS_LIST_FILE} HEADERS_LIST) set(symbols) foreach(header ${HEADERS_LIST}) # Filter only lines containing the FILTER_PATTERN file(STRINGS ${header} contain_filter REGEX "^.*${FILTER_PATTERN}.*[(]" ) # Remove function-like macros foreach(line ${contain_filter}) if (NOT ${line} MATCHES ".*#[ ]*define") list(APPEND not_macro ${line}) endif() endforeach() set(functions) # Get only the function names followed by '(' foreach(line ${not_macro}) string(REGEX MATCHALL "[a-zA-Z0-9_]+[ ]*[(]" func ${line}) list(APPEND functions ${func}) endforeach() set(extracted_symbols) # Remove '(' foreach(line ${functions}) string(REGEX REPLACE "[(]" "" symbol ${line}) string(STRIP "${symbol}" symbol) list(APPEND extracted_symbols ${symbol}) endforeach() list(APPEND symbols ${extracted_symbols}) endforeach() list(REMOVE_DUPLICATES symbols) list(SORT symbols) string(REPLACE ";" "\n" symbols_list "${symbols}") file(WRITE ${OUTPUT_PATH} "${symbols_list}") ================================================ FILE: src/libssh/cmake/Modules/FindABIMap.cmake ================================================ # # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # #.rst: # FindABIMap # ---------- # # This file provides functions to generate the symbol version script. It uses # the ``abimap`` tool to generate and update the linker script file. It can be # installed by calling:: # # $ pip install abimap # # The ``function generate_map_file`` generates a symbol version script # containing the provided symbols. It defines a custom command which sets # ``target_name`` as its ``OUTPUT``. # # The experimental function ``extract_symbols()`` is provided as a simple # parser to extract the symbols from C header files. It simply extracts symbols # followed by an opening '``(``'. It is recommended to use a filter pattern to # select the lines to be considered. It defines a custom command which sets # ``target_name`` as its output. # # The helper function ``get_files_list()`` is provided to find files given a # name pattern. It defines a custom command which sets ``target_name`` as its # output. # # Functions provided # ------------------ # # :: # # generate_map_file(target_name # RELEASE_NAME_VERSION release_name # SYMBOLS symbols_target # [CURRENT_MAP cur_map] # [FINAL] # [BREAK_ABI] # [COPY_TO output] # ) # # ``target_name``: # Required, expects the name of the file to receive the generated symbol # version script. It should be added as a dependency for the library. Use the # linker option ``--version-script filename`` to add the version information # to the symbols when building the library. # # ``RELEASE_NAME_VERSION``: # Required, expects a string containing the name and version information to be # added to the symbols in the format ``lib_name_1_2_3``. # # ``SYMBOLS``: # Required, expects a target with the property ``LIST_FILE`` containing a path # to a file containing the list of symbols to be added to the symbol version # script. # # ``CURRENT_MAP``: # Optional. If given, the new set of symbols will be checked against the # ones contained in the ``cur_map`` file and updated properly. If an # incompatible change is detected and ``BREAK_ABI`` is not defined, the build # will fail. # # ``FINAL``: # Optional. If given, will provide the ``--final`` option to ``abimap`` tool, # which will mark the modified release in the symbol version script with a # special comment, preventing later changes. This option should be set when # creating a library release and the resulting map file should be stored with # the source code. # # ``BREAK_ABI``: # Optional. If provided, will use ``abimap`` ``--allow-abi-break`` option, which # accepts incompatible changes to the set of symbols. This is necessary if any # previously existing symbol were removed. # # ``COPY_TO``: # Optional, expects a string containing the path to where the generated # map file will be copied. # # Example: # # .. code-block:: cmake # # find_package(ABIMap) # generate_map_file("lib.map" # RELEASE_NAME_VERSION "lib_1_0_0" # SYMBOLS symbols # ) # # Where the target ``symbols`` has its property ``LIST_FILE`` set to the path to # a file containing:: # # ``symbol1`` # ``symbol2`` # # This example would result in the symbol version script to be created in # ``${CMAKE_CURRENT_BINARY_DIR}/lib.map`` containing the provided symbols. # # :: # # get_files_list(target_name # DIRECTORIES dir1 [dir2 ...] # FILES_PATTERNS exp1 [exp2 ...] # [COPY_TO output] # ) # # ``target_name``: # Required, expects the name of the target to be created. A file named as # ``${target_name}.list`` will be created in # ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of files found. # # ``DIRECTORIES``: # Required, expects a list of directories paths. Only absolute paths are # supported. # # ``FILES_PATTERN``: # Required, expects a list of matching expressions to find the files to be # considered in the directories. # # ``COPY_TO``: # Optional, expects a string containing the path to where the file containing # the list of files will be copied. # # This command searches the directories provided in ``DIRECTORIES`` for files # matching any of the patterns provided in ``FILES_PATTERNS``. The obtained list # is written to the path specified by ``output``. A target named ``target_name`` # will be created and its property ``LIST_FILE`` will be set to contain # ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list`` # # Example: # # .. code-block:: cmake # # find_package(ABIMap) # get_files_list(target # DIRECTORIES "/include/mylib" # FILES_PATTERNS "*.h" # COPY_TO "my_list.txt" # ) # # Consider that ``/include/mylib`` contains 3 files, ``h1.h``, ``h2.h``, and # ``h3.hpp`` # # Will result in a file ``my_list.txt`` containing:: # # ``h1.h;h2.h`` # # And the target ``target`` will have its property ``LIST_FILE`` set to contain # ``${CMAKE_CURRENT_BINARY_DIR}/target.list`` # # :: # # extract_symbols(target_name # HEADERS_LIST headers_list_target # [FILTER_PATTERN pattern] # [COPY_TO output] # ) # # ``target_name``: # Required, expects the name of the target to be created. A file named after # the string given in ``target_name`` will be created in # ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of symbols. # # ``HEADERS_LIST``: # Required, expects a target with the property ``LIST_FILE`` set, containing a # file path. Such file must contain a list of files paths. # # ``FILTER_PATTERN``: # Optional, expects a string. Only the lines containing the filter pattern # will be considered. # # ``COPY_TO``: # Optional, expects a string containing the path to where the file containing # the found symbols will be copied. # # This command extracts the symbols from the files listed in # ``headers_list`` and write them on the ``output`` file. If ``pattern`` # is provided, then only the lines containing the string given in ``pattern`` # will be considered. It is recommended to provide a ``FILTER_PATTERN`` to mark # the lines containing exported function declaration, since this function is # experimental and can return wrong symbols when parsing the header files. A # target named ``target_name`` will be created with the property ``LIST_FILE`` # set to contain ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``. # # Example: # # .. code-block:: cmake # # find_package(ABIMap) # extract_symbols("lib.symbols" # HEADERS_LIST "headers_target" # FILTER_PATTERN "API_FUNCTION" # ) # # Where ``LIST_FILE`` property in ``headers_target`` points to a file # containing:: # # header1.h;header2.h # # Where ``header1.h`` contains:: # # API_FUNCTION int exported_func1(int a, int b); # # ``header2.h`` contains:: # # API_FUNCTION int exported_func2(int a); # # int private_func2(int b); # # Will result in a file ``lib.symbols.list`` in ``${CMAKE_CURRENT_BINARY_DIR}`` # containing:: # # ``exported_func1`` # ``exported_func2`` # # Search for python which is required if (ABIMap_FIND_REQURIED) find_package(PythonInterp REQUIRED) else() find_package(PythonInterp) endif() if (PYTHONINTERP_FOUND) # Search for abimap tool used to generate the map files find_program(ABIMAP_EXECUTABLE NAMES abimap DOC "path to the abimap executable") mark_as_advanced(ABIMAP_EXECUTABLE) if (NOT ABIMAP_EXECUTABLE AND UNIX) message(STATUS "Could not find `abimap` in PATH." " It can be found in PyPI as `abimap`" " (try `pip install abimap`)") endif () if (ABIMAP_EXECUTABLE) # Get the abimap version execute_process(COMMAND ${ABIMAP_EXECUTABLE} version OUTPUT_VARIABLE ABIMAP_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE) # If the version string starts with abimap-, strip it if ("abimap" STRLESS_EQUAL ${ABIMAP_VERSION_STRING}) string(REGEX REPLACE "abimap-" "" ABIMAP_VERSION_STRING "${ABIMAP_VERSION_STRING}") endif() endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(ABIMap REQUIRED_VARS ABIMAP_EXECUTABLE VERSION_VAR ABIMAP_VERSION_STRING) endif() if (ABIMAP_FOUND) # Define helper scripts set(_EXTRACT_SYMBOLS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/ExtractSymbols.cmake) set(_GENERATE_MAP_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GenerateMap.cmake) set(_GET_FILES_LIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GetFilesList.cmake) function(get_file_list _TARGET_NAME) set(one_value_arguments COPY_TO ) set(multi_value_arguments DIRECTORIES FILES_PATTERNS ) cmake_parse_arguments(_get_files_list "" "${one_value_arguments}" "${multi_value_arguments}" ${ARGN} ) # The DIRS argument is required if (NOT DEFINED _get_files_list_DIRECTORIES) message(FATAL_ERROR "No directories paths provided. Provide a list of" " directories paths containing header files.") endif() # The FILES_PATTERNS argument is required if (NOT DEFINED _get_files_list_FILES_PATTERNS) message(FATAL_ERROR "No matching expressions provided. Provide a list" " of matching patterns for the header files.") endif() set(_FILES_LIST_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list) get_filename_component(_get_files_list_OUTPUT_PATH "${_FILES_LIST_OUTPUT_PATH}" ABSOLUTE) add_custom_target( ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} -DOUTPUT_PATH="${_get_files_list_OUTPUT_PATH}" -DDIRECTORIES="${_get_files_list_DIRECTORIES}" -DFILES_PATTERNS="${_get_files_list_FILES_PATTERNS}" -P ${_GET_FILES_LIST_SCRIPT} COMMENT "Searching for files" ) if (DEFINED _get_files_list_COPY_TO) # Copy the generated file back to the COPY_TO add_custom_target(${_TARGET_NAME} ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}" ) else() add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_TARGET_NAME}_int ) endif() set_target_properties(${_TARGET_NAME} PROPERTIES LIST_FILE ${_FILES_LIST_OUTPUT_PATH} ) endfunction() function(extract_symbols _TARGET_NAME) set(one_value_arguments FILTER_PATTERN HEADERS_LIST COPY_TO ) set(multi_value_arguments ) cmake_parse_arguments(_extract_symbols "" "${one_value_arguments}" "${multi_value_arguments}" ${ARGN} ) # The HEADERS_LIST_FILE argument is required if (NOT DEFINED _extract_symbols_HEADERS_LIST) message(FATAL_ERROR "No target provided in HEADERS_LIST. Provide a" " target with the property LIST_FILE set as the" " path to the file containing the list of headers.") endif() get_filename_component(_SYMBOLS_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list" ABSOLUTE ) get_target_property(_HEADERS_LIST_FILE ${_extract_symbols_HEADERS_LIST} LIST_FILE ) add_custom_target( ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} -DOUTPUT_PATH="${_SYMBOLS_OUTPUT_PATH}" -DHEADERS_LIST_FILE="${_HEADERS_LIST_FILE}" -DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN} -P ${_EXTRACT_SYMBOLS_SCRIPT} DEPENDS ${_extract_symbols_HEADERS_LIST} COMMENT "Extracting symbols from headers" ) if (DEFINED _extract_symbols_COPY_TO) # Copy the generated file back to the COPY_TO add_custom_target(${_TARGET_NAME} ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}" ) else() add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_TARGET_NAME}_int ) endif() set_target_properties(${_TARGET_NAME} PROPERTIES LIST_FILE ${_SYMBOLS_OUTPUT_PATH} ) endfunction() function(generate_map_file _TARGET_NAME) set(options FINAL BREAK_ABI ) set(one_value_arguments RELEASE_NAME_VERSION SYMBOLS CURRENT_MAP COPY_TO ) set(multi_value_arguments ) cmake_parse_arguments(_generate_map_file "${options}" "${one_value_arguments}" "${multi_value_arguments}" ${ARGN} ) if (NOT DEFINED _generate_map_file_SYMBOLS) message(FATAL_ERROR "No target provided in SYMBOLS. Provide a target" " with the property LIST_FILE set as the path to" " the file containing the list of symbols.") endif() if (NOT DEFINED _generate_map_file_RELEASE_NAME_VERSION) message(FATAL_ERROR "Release name and version not provided." " (e.g. libname_1_0_0)") endif() get_target_property(_SYMBOLS_FILE ${_generate_map_file_SYMBOLS} LIST_FILE ) # Set generated map file path get_filename_component(_MAP_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}" ABSOLUTE ) add_custom_target( ${_TARGET_NAME}_int ALL COMMAND ${CMAKE_COMMAND} -DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE} -DSYMBOLS="${_SYMBOLS_FILE}" -DCURRENT_MAP=${_generate_map_file_CURRENT_MAP} -DOUTPUT_PATH="${_MAP_OUTPUT_PATH}" -DFINAL=${_generate_map_file_FINAL} -DBREAK_ABI=${_generate_map_file_BREAK_ABI} -DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION} -P ${_GENERATE_MAP_SCRIPT} DEPENDS ${_generate_map_file_SYMBOLS} COMMENT "Generating the map ${_TARGET_NAME}" ) # Add a custom command setting the map as OUTPUT to allow it to be added as # a generated source add_custom_command( OUTPUT ${_MAP_OUTPUT_PATH} DEPENDS ${_TARGET_NAME} ) if (DEFINED _generate_map_file_COPY_TO) # Copy the generated map back to the COPY_TO add_custom_target(${_TARGET_NAME} ALL COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH} ${_generate_map_file_COPY_TO} DEPENDS ${_TARGET_NAME}_int COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}" ) else() add_custom_target(${_TARGET_NAME} ALL DEPENDS ${_TARGET_NAME}_int ) endif() endfunction() endif (ABIMAP_FOUND) ================================================ FILE: src/libssh/cmake/Modules/FindArgp.cmake ================================================ # - Try to find ARGP # Once done this will define # # ARGP_ROOT_DIR - Set this variable to the root installation of ARGP # # Read-Only variables: # ARGP_FOUND - system has ARGP # ARGP_INCLUDE_DIR - the ARGP include directory # ARGP_LIBRARIES - Link these to use ARGP # ARGP_DEFINITIONS - Compiler switches required for using ARGP # #============================================================================= # Copyright (c) 2011-2016 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # set(_ARGP_ROOT_HINTS ) set(_ARGP_ROOT_PATHS "$ENV{PROGRAMFILES}/argp" ) find_path(ARGP_ROOT_DIR NAMES include/argp.h HINTS ${_ARGP_ROOT_HINTS} PATHS ${_ARGP_ROOT_PATHS} ) mark_as_advanced(ARGP_ROOT_DIR) find_path(ARGP_INCLUDE_DIR NAMES argp.h PATHS ${ARGP_ROOT_DIR}/include ) find_library(ARGP_LIBRARY NAMES argp PATHS ${ARGP_ROOT_DIR}/lib ) if (ARGP_LIBRARY) set(ARGP_LIBRARIES ${ARGP_LIBRARIES} ${ARGP_LIBRARY} ) endif (ARGP_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(ARGP DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR) # show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES) ================================================ FILE: src/libssh/cmake/Modules/FindCMocka.cmake ================================================ # - Try to find CMocka # Once done this will define # # CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka # # Read-Only variables: # CMOCKA_FOUND - system has CMocka # CMOCKA_INCLUDE_DIR - the CMocka include directory # CMOCKA_LIBRARIES - Link these to use CMocka # CMOCKA_DEFINITIONS - Compiler switches required for using CMocka # #============================================================================= # Copyright (c) 2011-2012 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # set(_CMOCKA_ROOT_HINTS ) set(_CMOCKA_ROOT_PATHS "$ENV{PROGRAMFILES}/cmocka" ) find_path(CMOCKA_ROOT_DIR NAMES include/cmocka.h HINTS ${_CMOCKA_ROOT_HINTS} PATHS ${_CMOCKA_ROOT_PATHS} ) mark_as_advanced(CMOCKA_ROOT_DIR) find_path(CMOCKA_INCLUDE_DIR NAMES cmocka.h PATHS ${CMOCKA_ROOT_DIR}/include ) find_library(CMOCKA_LIBRARY NAMES cmocka PATHS ${CMOCKA_ROOT_DIR}/lib ) if (CMOCKA_LIBRARY) set(CMOCKA_LIBRARIES ${CMOCKA_LIBRARIES} ${CMOCKA_LIBRARY} ) endif (CMOCKA_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR) # show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES) ================================================ FILE: src/libssh/cmake/Modules/FindGCrypt.cmake ================================================ # - Try to find GCrypt # Once done this will define # # GCRYPT_FOUND - system has GCrypt # GCRYPT_INCLUDE_DIRS - the GCrypt include directory # GCRYPT_LIBRARIES - Link these to use GCrypt # GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt # #============================================================================= # Copyright (c) 2009-2012 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # set(_GCRYPT_ROOT_HINTS $ENV{GCRYTPT_ROOT_DIR} ${GCRYPT_ROOT_DIR}) set(_GCRYPT_ROOT_PATHS "$ENV{PROGRAMFILES}/libgcrypt") set(_GCRYPT_ROOT_HINTS_AND_PATHS HINTS ${_GCRYPT_ROOT_HINTS} PATHS ${_GCRYPT_ROOT_PATHS}) find_path(GCRYPT_INCLUDE_DIR NAMES gcrypt.h HINTS ${_GCRYPT_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES include ) find_library(GCRYPT_LIBRARY NAMES gcrypt gcrypt11 libgcrypt-11 HINTS ${_GCRYPT_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES lib ) find_library(GCRYPT_ERROR_LIBRARY NAMES gpg-error libgpg-error-0 libgpg-error6-0 HINTS ${_GCRYPT_ROOT_HINTS_AND_PATHS} ) set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY}) if (GCRYPT_INCLUDE_DIR) file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]") string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}") endif (GCRYPT_INCLUDE_DIR) include(FindPackageHandleStandardArgs) if (GCRYPT_VERSION) find_package_handle_standard_args(GCrypt REQUIRED_VARS GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES VERSION_VAR GCRYPT_VERSION FAIL_MESSAGE "Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR" ) else (GCRYPT_VERSION) find_package_handle_standard_args(GCrypt "Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR" GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES) endif (GCRYPT_VERSION) # show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES) ================================================ FILE: src/libssh/cmake/Modules/FindGSSAPI.cmake ================================================ # - Try to find GSSAPI # Once done this will define # # KRB5_CONFIG - Path to krb5-config # GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI # # Read-Only variables: # GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found # GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found # GSSAPI_FOUND - system has GSSAPI # GSSAPI_INCLUDE_DIR - the GSSAPI include directory # GSSAPI_LIBRARIES - Link these to use GSSAPI # GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI # #============================================================================= # Copyright (c) 2013 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # find_path(GSSAPI_ROOT_DIR NAMES include/gssapi.h include/gssapi/gssapi.h HINTS ${_GSSAPI_ROOT_HINTS} PATHS ${_GSSAPI_ROOT_PATHS} ) mark_as_advanced(GSSAPI_ROOT_DIR) if (UNIX) find_program(KRB5_CONFIG NAMES krb5-config PATHS ${GSSAPI_ROOT_DIR}/bin /opt/local/bin) mark_as_advanced(KRB5_CONFIG) if (KRB5_CONFIG) # Check if we have MIT KRB5 execute_process( COMMAND ${KRB5_CONFIG} --vendor RESULT_VARIABLE _GSSAPI_VENDOR_RESULT OUTPUT_VARIABLE _GSSAPI_VENDOR_STRING) if ((_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") OR (_GSSAPI_VENDOR_STRING MATCHES ".*MITKerberosShim.*")) set(GSSAPI_FLAVOR_MIT TRUE) else() execute_process( COMMAND ${KRB5_CONFIG} --libs gssapi RESULT_VARIABLE _GSSAPI_LIBS_RESULT OUTPUT_VARIABLE _GSSAPI_LIBS_STRING) if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*") set(GSSAPI_FLAVOR_HEIMDAL TRUE) endif() endif() # Get the include dir execute_process( COMMAND ${KRB5_CONFIG} --cflags gssapi RESULT_VARIABLE _GSSAPI_INCLUDE_RESULT OUTPUT_VARIABLE _GSSAPI_INCLUDE_STRING) string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}") string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}") endif() if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL) # Check for HEIMDAL find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(_GSSAPI heimdal-gssapi) endif (PKG_CONFIG_FOUND) if (_GSSAPI_FOUND) set(GSSAPI_FLAVOR_HEIMDAL TRUE) else() find_path(_GSSAPI_ROKEN NAMES roken.h PATHS ${GSSAPI_ROOT_DIR}/include ${_GSSAPI_INCLUDEDIR}) if (_GSSAPI_ROKEN) set(GSSAPI_FLAVOR_HEIMDAL TRUE) endif() endif () endif() endif (UNIX) find_path(GSSAPI_INCLUDE_DIR NAMES gssapi.h gssapi/gssapi.h PATHS ${GSSAPI_ROOT_DIR}/include ${_GSSAPI_INCLUDEDIR} ) if (GSSAPI_FLAVOR_MIT) find_library(GSSAPI_LIBRARY NAMES gssapi_krb5 PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(KRB5_LIBRARY NAMES krb5 PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(K5CRYPTO_LIBRARY NAMES k5crypto PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(COM_ERR_LIBRARY NAMES com_err PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) if (GSSAPI_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${GSSAPI_LIBRARY} ) endif (GSSAPI_LIBRARY) if (KRB5_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${KRB5_LIBRARY} ) endif (KRB5_LIBRARY) if (K5CRYPTO_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${K5CRYPTO_LIBRARY} ) endif (K5CRYPTO_LIBRARY) if (COM_ERR_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${COM_ERR_LIBRARY} ) endif (COM_ERR_LIBRARY) endif (GSSAPI_FLAVOR_MIT) if (GSSAPI_FLAVOR_HEIMDAL) find_library(GSSAPI_LIBRARY NAMES gssapi PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(KRB5_LIBRARY NAMES krb5 PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(HCRYPTO_LIBRARY NAMES hcrypto PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(COM_ERR_LIBRARY NAMES com_err PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(HEIMNTLM_LIBRARY NAMES heimntlm PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(HX509_LIBRARY NAMES hx509 PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(ASN1_LIBRARY NAMES asn1 PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(WIND_LIBRARY NAMES wind PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) find_library(ROKEN_LIBRARY NAMES roken PATHS ${GSSAPI_ROOT_DIR}/lib ${_GSSAPI_LIBDIR} ) if (GSSAPI_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${GSSAPI_LIBRARY} ) endif (GSSAPI_LIBRARY) if (KRB5_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${KRB5_LIBRARY} ) endif (KRB5_LIBRARY) if (HCRYPTO_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HCRYPTO_LIBRARY} ) endif (HCRYPTO_LIBRARY) if (COM_ERR_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${COM_ERR_LIBRARY} ) endif (COM_ERR_LIBRARY) if (HEIMNTLM_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HEIMNTLM_LIBRARY} ) endif (HEIMNTLM_LIBRARY) if (HX509_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${HX509_LIBRARY} ) endif (HX509_LIBRARY) if (ASN1_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${ASN1_LIBRARY} ) endif (ASN1_LIBRARY) if (WIND_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${WIND_LIBRARY} ) endif (WIND_LIBRARY) if (ROKEN_LIBRARY) set(GSSAPI_LIBRARIES ${GSSAPI_LIBRARIES} ${WIND_LIBRARY} ) endif (ROKEN_LIBRARY) endif (GSSAPI_FLAVOR_HEIMDAL) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR) if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) set(GSSAPI_FOUND TRUE) endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES) # show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES) ================================================ FILE: src/libssh/cmake/Modules/FindMbedTLS.cmake ================================================ # - Try to find mbedTLS # Once done this will define # # MBEDTLS_FOUND - system has mbedTLS # MBEDTLS_INCLUDE_DIRS - the mbedTLS include directory # MBEDTLS_LIBRARIES - Link these to use mbedTLS # MBEDTLS_DEFINITIONS - Compiler switches required for using mbedTLS #============================================================================= # Copyright (c) 2017 Sartura d.o.o. # # Author: Juraj Vijtiuk # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # set(_MBEDTLS_ROOT_HINTS $ENV{MBEDTLS_ROOT_DIR} ${MBEDTLS_ROOT_DIR}) set(_MBEDTLS_ROOT_PATHS "$ENV{PROGRAMFILES}/libmbedtls") set(_MBEDTLS_ROOT_HINTS_AND_PATHS HINTS ${_MBEDTLS_ROOT_HINTS} PATHS ${_MBEDTLS_ROOT_PATHS}) find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/config.h HINTS ${_MBEDTLS_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES include ) find_library(MBEDTLS_SSL_LIBRARY NAMES mbedtls HINTS ${_MBEDTLS_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES lib ) find_library(MBEDTLS_CRYPTO_LIBRARY NAMES mbedcrypto HINTS ${_MBEDTLS_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES lib ) find_library(MBEDTLS_X509_LIBRARY NAMES mbedx509 HINTS ${_MBEDTLS_ROOT_HINTS_AND_PATHS} PATH_SUFFIXES lib ) set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY} ${MBEDTLS_X509_LIBRARY}) if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h") file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX "^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"") string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" MBEDTLS_VERSION "${_mbedtls_version_str}") endif () include(FindPackageHandleStandardArgs) if (MBEDTLS_VERSION) find_package_handle_standard_args(MbedTLS REQUIRED_VARS MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES VERSION_VAR MBEDTLS_VERSION FAIL_MESSAGE "Could NOT find mbedTLS, try to set the path to mbedTLS root folder in the system variable MBEDTLS_ROOT_DIR" ) else (MBEDTLS_VERSION) find_package_handle_standard_args(MBedTLS "Could NOT find mbedTLS, try to set the path to mbedLS root folder in the system variable MBEDTLS_ROOT_DIR" MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES) endif (MBEDTLS_VERSION) # show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES) ================================================ FILE: src/libssh/cmake/Modules/FindNSIS.cmake ================================================ # - Try to find NSIS # Once done this will define # # NSIS_ROOT_PATH - Set this variable to the root installation of NSIS # # Read-Only variables: # # NSIS_FOUND - system has NSIS # NSIS_MAKE - NSIS creator executable # #============================================================================= # Copyright (c) 2010-2013 Andreas Schneider # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # if (WIN32) set(_x86 "(x86)") set(_NSIS_ROOT_PATHS "$ENV{ProgramFiles}/NSIS" "$ENV{ProgramFiles${_x86}}/NSIS" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]") find_path(NSIS_ROOT_PATH NAMES Include/Library.nsh PATHS ${_NSIS_ROOT_PATHS} ) mark_as_advanced(NSIS_ROOT_PATH) endif (WIN32) find_program(NSIS_MAKE NAMES makensis PATHS ${NSIS_ROOT_PATH} ) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE) if (NSIS_MAKE) set(NSIS_FOUND TRUE) endif (NSIS_MAKE) mark_as_advanced(NSIS_MAKE) ================================================ FILE: src/libssh/cmake/Modules/FindNaCl.cmake ================================================ # - Try to find NaCl # Once done this will define # # NACL_FOUND - system has NaCl # NACL_INCLUDE_DIRS - the NaCl include directory # NACL_LIBRARIES - Link these to use NaCl # NACL_DEFINITIONS - Compiler switches required for using NaCl # # Copyright (c) 2010 Andreas Schneider # Copyright (c) 2013 Aris Adamantiadis # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (NACL_LIBRARIES AND NACL_INCLUDE_DIRS) # in cache already set(NACL_FOUND TRUE) else (NACL_LIBRARIES AND NACL_INCLUDE_DIRS) find_path(NACL_INCLUDE_DIR NAMES nacl/crypto_box_curve25519xsalsa20poly1305.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include ) find_library(NACL_LIBRARY NAMES nacl PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(NACL_INCLUDE_DIRS ${NACL_INCLUDE_DIR} ) if (NACL_LIBRARY) set(NACL_LIBRARIES ${NACL_LIBRARIES} ${NACL_LIBRARY} ) endif (NACL_LIBRARY) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NaCl DEFAULT_MSG NACL_LIBRARIES NACL_INCLUDE_DIRS) # show the NACL_INCLUDE_DIRS and NACL_LIBRARIES variables only in the advanced view mark_as_advanced(NACL_INCLUDE_DIRS NACL_LIBRARIES) endif (NACL_LIBRARIES AND NACL_INCLUDE_DIRS) ================================================ FILE: src/libssh/cmake/Modules/GenerateMap.cmake ================================================ # # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # #.rst: # GenerateMap # ----------- # # This is a helper script for FindABImap.cmake. # # Generates a symbols version script using the abimap tool. # This script is run in build time to use the correct command depending on the # existence of the file provided ``CURRENT_MAP``. # # If the file exists, the ``abimap update`` subcommand is used to update the # existing map. Otherwise, the ``abimap new`` subcommand is used to create a new # map file. # # If the file provided in ``CURRENT_MAP`` exists, it is copied to the # ``OUTPUT_PATH`` before updating. # This is required because ``abimap`` do not generate output if no symbols were # changed when updating an existing file. # # Expected defined variables # -------------------------- # # ``SYMBOLS``: # Required file containing the symbols to be used as input. Usually this is # the ``OUTPUT`` generated by ``extract_symbols()`` function provided in # FindABImap.cmake # # ``RELEASE_NAME_VERSION``: # Required, expects the library name and version information to be added to # the symbols in the format ``library_name_1_2_3`` # # ``CURRENT_MAP``: # Required, expects the path to the current map file (or the path were it # should be) # # ``OUTPUT_PATH``: # Required, expects the output file path. # # ``ABIMAP_EXECUTABLE``: # Required, expects the path to the ``abimap`` tool. # # Optionally defined variables # ---------------------------- # # ``FINAL``: # If defined, will mark the modified set of symbols in the symbol version # script as final, preventing later changes using ``abimap``. # # ``BREAK_ABI``: # If defined, the build will not fail if symbols were removed. # If defined and a symbol is removed, a new release is created containing # all symbols from all released versions. This makes an incompatible release. # if (NOT DEFINED RELEASE_NAME_VERSION) message(SEND_ERROR "RELEASE_NAME_VERSION not defined") endif() if (NOT DEFINED SYMBOLS) message(SEND_ERROR "SYMBOLS not defined") endif() if (NOT DEFINED CURRENT_MAP) message(SEND_ERROR "CURRENT_MAP not defined") endif() if (NOT DEFINED OUTPUT_PATH) message(SEND_ERROR "OUTPUT_PATH not defined") endif() if (NOT ABIMAP_EXECUTABLE) message(SEND_ERROR "ABIMAP_EXECUTABLE not defined") endif() set(ARGS_LIST) if (FINAL) list(APPEND ARGS_LIST "--final") endif() if (EXISTS ${CURRENT_MAP}) if (BREAK_ABI) list(APPEND ARGS_LIST "--allow-abi-break") endif() execute_process( COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CURRENT_MAP} ${OUTPUT_PATH} COMMAND ${ABIMAP_EXECUTABLE} update ${ARGS_LIST} -r ${RELEASE_NAME_VERSION} -i ${SYMBOLS} -o ${OUTPUT_PATH} ${CURRENT_MAP} RESULT_VARIABLE result ) else () execute_process( COMMAND ${ABIMAP_EXECUTABLE} new ${ARGS_LIST} -r ${RELEASE_NAME_VERSION} -i ${SYMBOLS} -o ${OUTPUT_PATH} RESULT_VARIABLE result ) endif() if (NOT "${result}" STREQUAL "0") message(SEND_ERROR "Map generation failed") endif() ================================================ FILE: src/libssh/cmake/Modules/GetFilesList.cmake ================================================ # # Copyright (c) 2018 Anderson Toshiyuki Sasaki # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # #.rst: # GetFilesList # ------------ # # This is a helper script for FindABImap.cmake. # # Search in the provided directories for files matching the provided pattern. # The list of files is then written to the output file. # # Expected defined variables # -------------------------- # # ``DIRECTORIES``: # Required, expects a list of directories paths. # # ``FILES_PATTERNS``: # Required, expects a list of patterns to be used to search files # # ``OUTPUT_PATH``: # Required, expects the output file path. if (NOT DEFINED DIRECTORIES) message(SEND_ERROR "DIRECTORIES not defined") endif() if (NOT DEFINED FILES_PATTERNS) message(SEND_ERROR "FILES_PATTERNS not defined") endif() if (NOT DEFINED OUTPUT_PATH) message(SEND_ERROR "OUTPUT_PATH not defined") endif() string(REPLACE " " ";" DIRECTORIES_LIST "${DIRECTORIES}") string(REPLACE " " ";" FILES_PATTERNS_LIST "${FILES_PATTERNS}") # Create the list of expressions for the files set(glob_expressions) foreach(dir ${DIRECTORIES_LIST}) foreach(exp ${FILES_PATTERNS_LIST}) list(APPEND glob_expressions "${dir}/${exp}" ) endforeach() endforeach() # Create the list of files file(GLOB files ${glob_expressions}) # Write to the output file(WRITE ${OUTPUT_PATH} "${files}") ================================================ FILE: src/libssh/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake ================================================ # - MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # MACRO_ENSURE_OUT_OF_SOURCE_BUILD() # Copyright (c) 2006, Alexander Neundorf, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage) string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource) if (_insource) message(SEND_ERROR "${_errorMessage}") message(FATAL_ERROR "Remove the file CMakeCache.txt in ${CMAKE_SOURCE_DIR} first.") endif (_insource) endmacro (MACRO_ENSURE_OUT_OF_SOURCE_BUILD) ================================================ FILE: src/libssh/cmake/Toolchain-cross-m32.cmake ================================================ set(CMAKE_C_FLAGS "-m32" CACHE STRING "C compiler flags" FORCE) set(CMAKE_CXX_FLAGS "-m32" CACHE STRING "C++ compiler flags" FORCE) set(LIB32 /usr/lib) # Fedora if(EXISTS /usr/lib32) set(LIB32 /usr/lib32) # Arch, Solus endif() set(CMAKE_SYSTEM_LIBRARY_PATH ${LIB32} CACHE STRING "system library search path" FORCE) set(CMAKE_LIBRARY_PATH ${LIB32} CACHE STRING "library search path" FORCE) # this is probably unlikely to be needed, but just in case set(CMAKE_EXE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "executable linker flags" FORCE) set(CMAKE_SHARED_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "shared library linker flags" FORCE) set(CMAKE_MODULE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "module linker flags" FORCE) # on Fedora and Arch and similar, point pkgconfig at 32 bit .pc files. We have # to include the regular system .pc files as well (at the end), because some # are not always present in the 32 bit directory if(EXISTS ${LIB32}/pkgconfig) set(ENV{PKG_CONFIG_LIBDIR} ${LIB32}/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgconfig:/usr/lib64/pkgconfig) endiF() ================================================ FILE: src/libssh/config.h.cmake ================================================ /* Name of package */ #cmakedefine PACKAGE "${PROJECT_NAME}" /* Version number of package */ #cmakedefine VERSION "${PROJECT_VERSION}" #cmakedefine SYSCONFDIR "${SYSCONFDIR}" #cmakedefine BINARYDIR "${BINARYDIR}" #cmakedefine SOURCEDIR "${SOURCEDIR}" /* Global bind configuration file path */ #cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}" /* Global client configuration file path */ #cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}" /************************** HEADER FILES *************************/ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ARGP_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ARPA_INET_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_GLOB_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_VALGRIND_VALGRIND_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTY_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTMP_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UTIL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LIBUTIL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UTIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_IO_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_AES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_WSPIAPI_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_BLOWFISH_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_DES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_ECDH_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_EC_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_OPENSSL_ECDSA_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_H 1 /* Define to 1 if you have eliptic curve cryptography in openssl */ #cmakedefine HAVE_OPENSSL_ECC 1 /* Define to 1 if you have eliptic curve cryptography in gcrypt */ #cmakedefine HAVE_GCRYPT_ECC 1 /* Define to 1 if you have eliptic curve cryptography */ #cmakedefine HAVE_ECC 1 /* Define to 1 if you have DSA */ #cmakedefine HAVE_DSA 1 /* Define to 1 if you have gl_flags as a glob_t sturct member */ #cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1 /* Define to 1 if you have OpenSSL with Ed25519 support */ #cmakedefine HAVE_OPENSSL_ED25519 1 /* Define to 1 if you have OpenSSL with X25519 support */ #cmakedefine HAVE_OPENSSL_X25519 1 /*************************** FUNCTIONS ***************************/ /* Define to 1 if you have the `EVP_aes128_ctr' function. */ #cmakedefine HAVE_OPENSSL_EVP_AES_CTR 1 /* Define to 1 if you have the `EVP_aes128_cbc' function. */ #cmakedefine HAVE_OPENSSL_EVP_AES_CBC 1 /* Define to 1 if you have the `EVP_aes128_gcm' function. */ #cmakedefine HAVE_OPENSSL_EVP_AES_GCM 1 /* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */ #cmakedefine HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK 1 /* Define to 1 if you have the `CRYPTO_ctr128_encrypt' function. */ #cmakedefine HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ #cmakedefine HAVE_OPENSSL_EVP_CIPHER_CTX_NEW 1 /* Define to 1 if you have the `EVP_KDF_CTX_new_id' function. */ #cmakedefine HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID 1 /* Define to 1 if you have the `FIPS_mode' function. */ #cmakedefine HAVE_OPENSSL_FIPS_MODE 1 /* Define to 1 if you have the `EVP_DigestSign' function. */ #cmakedefine HAVE_OPENSSL_EVP_DIGESTSIGN 1 /* Define to 1 if you have the `EVP_DigestVerify' function. */ #cmakedefine HAVE_OPENSSL_EVP_DIGESTVERIFY 1 /* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */ #cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1 /* Define to 1 if you have the `snprintf' function. */ #cmakedefine HAVE_SNPRINTF 1 /* Define to 1 if you have the `_snprintf' function. */ #cmakedefine HAVE__SNPRINTF 1 /* Define to 1 if you have the `_snprintf_s' function. */ #cmakedefine HAVE__SNPRINTF_S 1 /* Define to 1 if you have the `vsnprintf' function. */ #cmakedefine HAVE_VSNPRINTF 1 /* Define to 1 if you have the `_vsnprintf' function. */ #cmakedefine HAVE__VSNPRINTF 1 /* Define to 1 if you have the `_vsnprintf_s' function. */ #cmakedefine HAVE__VSNPRINTF_S 1 /* Define to 1 if you have the `isblank' function. */ #cmakedefine HAVE_ISBLANK 1 /* Define to 1 if you have the `strncpy' function. */ #cmakedefine HAVE_STRNCPY 1 /* Define to 1 if you have the `strndup' function. */ #cmakedefine HAVE_STRNDUP 1 /* Define to 1 if you have the `cfmakeraw' function. */ #cmakedefine HAVE_CFMAKERAW 1 /* Define to 1 if you have the `getaddrinfo' function. */ #cmakedefine HAVE_GETADDRINFO 1 /* Define to 1 if you have the `poll' function. */ #cmakedefine HAVE_POLL 1 /* Define to 1 if you have the `select' function. */ #cmakedefine HAVE_SELECT 1 /* Define to 1 if you have the `clock_gettime' function. */ #cmakedefine HAVE_CLOCK_GETTIME 1 /* Define to 1 if you have the `ntohll' function. */ #cmakedefine HAVE_NTOHLL 1 /* Define to 1 if you have the `htonll' function. */ #cmakedefine HAVE_HTONLL 1 /* Define to 1 if you have the `strtoull' function. */ #cmakedefine HAVE_STRTOULL 1 /* Define to 1 if you have the `__strtoull' function. */ #cmakedefine HAVE___STRTOULL 1 /* Define to 1 if you have the `_strtoui64' function. */ #cmakedefine HAVE__STRTOUI64 1 /* Define to 1 if you have the `glob' function. */ #cmakedefine HAVE_GLOB 1 /* Define to 1 if you have the `explicit_bzero' function. */ #cmakedefine HAVE_EXPLICIT_BZERO 1 /* Define to 1 if you have the `memset_s' function. */ #cmakedefine HAVE_MEMSET_S 1 /* Define to 1 if you have the `SecureZeroMemory' function. */ #cmakedefine HAVE_SECURE_ZERO_MEMORY 1 /* Define to 1 if you have the `cmocka_set_test_filter' function. */ #cmakedefine HAVE_CMOCKA_SET_TEST_FILTER 1 /*************************** LIBRARIES ***************************/ /* Define to 1 if you have the `crypto' library (-lcrypto). */ #cmakedefine HAVE_LIBCRYPTO 1 /* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ #cmakedefine HAVE_LIBGCRYPT 1 /* Define to 1 if you have the 'mbedTLS' library (-lmbedtls). */ #cmakedefine HAVE_LIBMBEDCRYPTO 1 /* Define to 1 if you have the `pthread' library (-lpthread). */ #cmakedefine HAVE_PTHREAD 1 /* Define to 1 if you have the `cmocka' library (-lcmocka). */ #cmakedefine HAVE_CMOCKA 1 /**************************** OPTIONS ****************************/ #cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 #cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1 #cmakedefine HAVE_FALLTHROUGH_ATTRIBUTE 1 #cmakedefine HAVE_UNUSED_ATTRIBUTE 1 #cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1 #cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1 #cmakedefine HAVE_COMPILER__FUNC__ 1 #cmakedefine HAVE_COMPILER__FUNCTION__ 1 #cmakedefine HAVE_GCC_BOUNDED_ATTRIBUTE 1 /* Define to 1 if you want to enable GSSAPI */ #cmakedefine WITH_GSSAPI 1 /* Define to 1 if you want to enable ZLIB */ #cmakedefine WITH_ZLIB 1 /* Define to 1 if you want to enable SFTP */ #cmakedefine WITH_SFTP 1 /* Define to 1 if you want to enable server support */ #cmakedefine WITH_SERVER 1 /* Define to 1 if you want to enable DH group exchange algorithms */ #cmakedefine WITH_GEX 1 /* Define to 1 if you want to enable blowfish cipher support */ #cmakedefine WITH_BLOWFISH_CIPHER 1 /* Define to 1 if you want to enable debug output for crypto functions */ #cmakedefine DEBUG_CRYPTO 1 /* Define to 1 if you want to enable debug output for packet functions */ #cmakedefine DEBUG_PACKET 1 /* Define to 1 if you want to enable pcap output support (experimental) */ #cmakedefine WITH_PCAP 1 /* Define to 1 if you want to enable calltrace debug output */ #cmakedefine DEBUG_CALLTRACE 1 /* Define to 1 if you want to enable NaCl support */ #cmakedefine WITH_NACL 1 /*************************** ENDIAN *****************************/ /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #cmakedefine WORDS_BIGENDIAN 1 ================================================ FILE: src/libssh/doc/CMakeLists.txt ================================================ # # Build the documentation # if (${CMAKE_VERSION} VERSION_GREATER "3.8.99") find_package(Doxygen) if (DOXYGEN_FOUND) set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME}) set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION}) set(DOXYGEN_PROJECT_BRIEF "The SSH library") set(DOXYGEN_TAB_SIZE 4) set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES) set(DOXYGEN_MARKDOWN_SUPPORT YES) set(DOXYGEN_FULL_PATH_NAMES NO) set(DOXYGEN_PREDEFINED DOXYGEN WITH_SERVER WITH_SFTP PRINTF_ATTRIBUTE(x,y)) set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style) set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html) set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/that_style/that_style.css) set(DOXYGEN_HTML_EXTRA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_left.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_right.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_inter.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_off.png ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_on.png ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/splitbar_handle.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/doc.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/mag_glass.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg ${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js) # This updates the Doxyfile if we do changes here set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in") set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.docs") configure_file("${_doxyfile_template}" "${_target_doxyfile}") doxygen_add_docs(docs ${CMAKE_SOURCE_DIR}/include/libssh ${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}) endif() # DOXYGEN_FOUND endif() # CMAKE_VERSION ================================================ FILE: src/libssh/doc/authentication.dox ================================================ /** @page libssh_tutor_authentication Chapter 2: A deeper insight on authentication @section authentication_details A deeper insight on authentication In our guided tour, we merely mentioned that the user needed to authenticate. We didn't explain much in detail how that was supposed to happen. This chapter explains better the four authentication methods: with public keys, with a password, with challenges and responses (keyboard-interactive), and with no authentication at all. If your software is supposed to connect to an arbitrary server, then you might need to support all authentication methods. If your software will connect only to a given server, then it might be enough for your software to support only the authentication methods used by that server. If you are the administrator of the server, it might be your call to choose those authentication methods. It is not the purpose of this document to review in detail the advantages and drawbacks of each authentication method. You are therefore invited to read the abundant documentation on this topic to fully understand the advantages and security risks linked to each method. @subsection pubkeys Authenticating with public keys libssh is fully compatible with the openssh public and private keys. You can either use the automatic public key authentication method provided by libssh, or roll your own using the public key functions. The process of authenticating by public key to a server is the following: - you scan a list of files that contain public keys. each key is sent to the SSH server, until the server acknowledges a key (a key it knows can be used to authenticate the user). - then, you retrieve the private key for this key and send a message proving that you know that private key. The function ssh_userauth_autopubkey() does this using the available keys in "~/.ssh/". The return values are the following: - SSH_AUTH_ERROR: some serious error happened during authentication - SSH_AUTH_DENIED: no key matched - SSH_AUTH_SUCCESS: you are now authenticated - SSH_AUTH_PARTIAL: some key matched but you still have to provide an other mean of authentication (like a password). The ssh_userauth_publickey_auto() function also tries to authenticate using the SSH agent, if you have one running, or the "none" method otherwise. If you wish to authenticate with public key by your own, follow these steps: - Retrieve the public key with ssh_pki_import_pubkey_file(). - Offer the public key to the SSH server using ssh_userauth_try_publickey(). If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to authenticate using the public key and you can go to the next step. - Retrieve the private key, using the ssh_pki_import_privkey_file() function. If a passphrase is needed, either the passphrase specified as argument or a callback will be used. - Authenticate using ssh_userauth_publickey() with your private key. - Do not forget cleaning up memory using ssh_key_free(). Here is a minimalistic example of public key authentication: @code int authenticate_pubkey(ssh_session session) { int rc; rc = ssh_userauth_publickey_auto(session, NULL, NULL); if (rc == SSH_AUTH_ERROR) { fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session)); return SSH_AUTH_ERROR; } return rc; } @endcode @see ssh_userauth_publickey_auto() @see ssh_userauth_try_publickey() @see ssh_userauth_publickey() @see ssh_pki_import_pubkey_file() @see ssh_pki_import_privkey_file() @see ssh_key_free() @subsection password Authenticating with a password The function ssh_userauth_password() serves the purpose of authenticating using a password. It will return SSH_AUTH_SUCCESS if the password worked, or one of other constants otherwise. It's your work to ask the password and to deallocate it in a secure manner. If your server complains that the password is wrong, but you can still authenticate using openssh's client (issuing password), it's probably because openssh only accept keyboard-interactive. Switch to keyboard-interactive authentication, or try to configure plain text passwords on the SSH server. Here is a small example of password authentication: @code int authenticate_password(ssh_session session) { char *password; int rc; password = getpass("Enter your password: "); rc = ssh_userauth_password(session, NULL, password); if (rc == SSH_AUTH_ERROR) { fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session)); return SSH_AUTH_ERROR; } return rc; } @endcode @see ssh_userauth_password @subsection keyb_int The keyboard-interactive authentication method The keyboard-interactive method is, as its name tells, interactive. The server will issue one or more challenges that the user has to answer, until the server takes an authentication decision. ssh_userauth_kbdint() is the the main keyboard-interactive function. It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request. The keyboard-interactive authentication method of SSH2 is a feature that permits the server to ask a certain number of questions in an interactive manner to the client, until it decides to accept or deny the login. To begin, you call ssh_userauth_kbdint() (just set user and submethods to NULL) and store the answer. If the answer is SSH_AUTH_INFO, it means that the server has sent a few questions that you should ask the user. You can retrieve these questions with the following functions: ssh_userauth_kbdint_getnprompts(), ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and ssh_userauth_kbdint_getprompt(). Set the answer for each question in the challenge using ssh_userauth_kbdint_setanswer(). Then, call again ssh_userauth_kbdint() and start the process again until these functions returns something else than SSH_AUTH_INFO. Here are a few remarks: - Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS. - The server can send an empty question set (this is the default behavior on my system) after you have sent the answers to the first questions. You must still parse the answer, it might contain some message from the server saying hello or such things. Just call ssh_userauth_kbdint() until needed. - The meaning of "name", "prompt", "instruction" may be a little confusing. An explanation is given in the RFC section that follows. Here is a little note about how to use the information from keyboard-interactive authentication, coming from the RFC itself (rfc4256): @verbatim 3.3 User Interface Upon receiving a request message, the client SHOULD prompt the user as follows: A command line interface (CLI) client SHOULD print the name and instruction (if non-empty), adding newlines. Then for each prompt in turn, the client SHOULD display the prompt and read the user input. A graphical user interface (GUI) client has many choices on how to prompt the user. One possibility is to use the name field (possibly prefixed with the application's name) as the title of a dialog window in which the prompt(s) are presented. In that dialog window, the instruction field would be a text message, and the prompts would be labels for text entry fields. All fields SHOULD be presented to the user, for example an implementation SHOULD NOT discard the name field because its windows lack titles; it SHOULD instead find another way to display this information. If prompts are presented in a dialog window, then the client SHOULD NOT present each prompt in a separate window. All clients MUST properly handle an instruction field with embedded newlines. They SHOULD also be able to display at least 30 characters for the name and prompts. If the server presents names or prompts longer than 30 characters, the client MAY truncate these fields to the length it can display. If the client does truncate any fields, there MUST be an obvious indication that such truncation has occurred. The instruction field SHOULD NOT be truncated. Clients SHOULD use control character filtering as discussed in [SSH-ARCH] to avoid attacks by including terminal control characters in the fields to be displayed. For each prompt, the corresponding echo field indicates whether or not the user input should be echoed as characters are typed. Clients SHOULD correctly echo/mask user input for each prompt independently of other prompts in the request message. If a client does not honor the echo field for whatever reason, then the client MUST err on the side of masking input. A GUI client might like to have a checkbox toggling echo/mask. Clients SHOULD NOT add any additional characters to the prompt such as ": " (colon-space); the server is responsible for supplying all text to be displayed to the user. Clients MUST also accept empty responses from the user and pass them on as empty strings. @endverbatim The following example shows how to perform keyboard-interactive authentication: @code int authenticate_kbdint(ssh_session session) { int rc; rc = ssh_userauth_kbdint(session, NULL, NULL); while (rc == SSH_AUTH_INFO) { const char *name, *instruction; int nprompts, iprompt; name = ssh_userauth_kbdint_getname(session); instruction = ssh_userauth_kbdint_getinstruction(session); nprompts = ssh_userauth_kbdint_getnprompts(session); if (strlen(name) > 0) printf("%s\n", name); if (strlen(instruction) > 0) printf("%s\n", instruction); for (iprompt = 0; iprompt < nprompts; iprompt++) { const char *prompt; char echo; prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo); if (echo) { char buffer[128], *ptr; printf("%s", prompt); if (fgets(buffer, sizeof(buffer), stdin) == NULL) return SSH_AUTH_ERROR; buffer[sizeof(buffer) - 1] = '\0'; if ((ptr = strchr(buffer, '\n')) != NULL) *ptr = '\0'; if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0) return SSH_AUTH_ERROR; memset(buffer, 0, strlen(buffer)); } else { char *ptr; ptr = getpass(prompt); if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0) return SSH_AUTH_ERROR; } } rc = ssh_userauth_kbdint(session, NULL, NULL); } return rc; } @endcode @see ssh_userauth_kbdint() @see ssh_userauth_kbdint_getnprompts() @see ssh_userauth_kbdint_getname() @see ssh_userauth_kbdint_getinstruction() @see ssh_userauth_kbdint_getprompt() @see ssh_userauth_kbdint_setanswer() @subsection none Authenticating with "none" method The primary purpose of the "none" method is to get authenticated **without** any credential. Don't do that, use one of the other authentication methods, unless you really want to grant anonymous access. If the account has no password, and if the server is configured to let you pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS. The following example shows how to perform "none" authentication: @code int authenticate_none(ssh_session session) { int rc; rc = ssh_userauth_none(session, NULL); return rc; } @endcode @subsection auth_list Getting the list of supported authentications You are not meant to choose a given authentication method, you can let the server tell you which methods are available. Once you know them, you try them one after the other. The following example shows how to get the list of available authentication methods with ssh_userauth_list() and how to use the result: @code int test_several_auth_methods(ssh_session session) { int method, rc; rc = ssh_userauth_none(session, NULL); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_ERROR) { return rc; } method = ssh_userauth_list(session, NULL); if (method & SSH_AUTH_METHOD_NONE) { // For the source code of function authenticate_none(), // refer to the corresponding example rc = authenticate_none(session); if (rc == SSH_AUTH_SUCCESS) return rc; } if (method & SSH_AUTH_METHOD_PUBLICKEY) { // For the source code of function authenticate_pubkey(), // refer to the corresponding example rc = authenticate_pubkey(session); if (rc == SSH_AUTH_SUCCESS) return rc; } if (method & SSH_AUTH_METHOD_INTERACTIVE) { // For the source code of function authenticate_kbdint(), // refer to the corresponding example rc = authenticate_kbdint(session); if (rc == SSH_AUTH_SUCCESS) return rc; } if (method & SSH_AUTH_METHOD_PASSWORD) { // For the source code of function authenticate_password(), // refer to the corresponding example rc = authenticate_password(session); if (rc == SSH_AUTH_SUCCESS) return rc; } return SSH_AUTH_ERROR; } @endcode @subsection banner Getting the banner The SSH server might send a banner, which you can retrieve with ssh_get_issue_banner(), then display to the user. The following example shows how to retrieve and dispose the issue banner: @code int display_banner(ssh_session session) { int rc; char *banner; /* *** Does not work without calling ssh_userauth_none() first *** *** That will be fixed *** */ rc = ssh_userauth_none(session, NULL); if (rc == SSH_AUTH_ERROR) return rc; banner = ssh_get_issue_banner(session); if (banner) { printf("%s\n", banner); free(banner); } return rc; } @endcode */ ================================================ FILE: src/libssh/doc/command.dox ================================================ /** @page libssh_tutor_command Chapter 4: Passing a remote command @section remote_command Passing a remote command Previous chapter has shown how to open a full shell session, with an attached terminal or not. If you only need to execute a command on the remote end, you don't need all that complexity. The method described here is suited for executing only one remote command. If you need to issue several commands in a row, you should consider using a non-interactive remote shell, as explained in previous chapter. @see shell @subsection exec_remote Executing a remote command The first steps for executing a remote command are identical to those for opening remote shells. You first need a SSH channel, and then a SSH session that uses this channel: @code int show_remote_files(ssh_session session) { ssh_channel channel; int rc; channel = ssh_channel_new(session); if (channel == NULL) return SSH_ERROR; rc = ssh_channel_open_session(channel); if (rc != SSH_OK) { ssh_channel_free(channel); return rc; } @endcode Once a session is open, you can start the remote command with ssh_channel_request_exec(): @code rc = ssh_channel_request_exec(channel, "ls -l"); if (rc != SSH_OK) { ssh_channel_close(channel); ssh_channel_free(channel); return rc; } @endcode If the remote command displays data, you get them with ssh_channel_read(). This function returns the number of bytes read. If there is no more data to read on the channel, this function returns 0, and you can go to next step. If an error has been encountered, it returns a negative value: @code char buffer[256]; int nbytes; nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); while (nbytes > 0) { if (fwrite(buffer, 1, nbytes, stdout) != nbytes) { ssh_channel_close(channel); ssh_channel_free(channel); return SSH_ERROR; } nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); } if (nbytes < 0) { ssh_channel_close(channel); ssh_channel_free(channel); return SSH_ERROR; } @endcode Once you read the result of the remote command, you send an end-of-file to the channel, close it, and free the memory that it used: @code ssh_channel_send_eof(channel); ssh_channel_close(channel); ssh_channel_free(channel); return SSH_OK; } @endcode */ ================================================ FILE: src/libssh/doc/curve25519-sha256@libssh.org.txt ================================================ curve25519-sha256@libssh.org.txt Aris Adamantiadis 21/9/2013 1. Introduction This document describes the key exchange methode curve25519-sha256@libssh.org for SSH version 2 protocol. It is provided as an alternative to the existing key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie- Hellman [RFC5656]. The reason is the following : During summer of 2013, revelations from ex- consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors into softwares, hardware components and published standards. While it is still believed that the mathematics behind ECC cryptography are still sound and solid, some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence in NIST-published curves such as nistp256, nistp384, nistp521, for which constant parameters (including the generator point) are defined without explanation. It is also believed that NSA had a word to say in their definition. These curves are not the most secure or fastest possible for their key sizes [DJB], and researchers think it is possible that NSA have ways of cracking NIST curves. It is also interesting to note that SSH belongs to the list of protocols the NSA claims to be able to eavesdrop. Having a secure replacement would make passive attacks much harder if such a backdoor exists. However an alternative exists in the form of Curve25519. This algorithm has been proposed in 2006 by DJB [Curve25519]. Its main strengths are its speed, its constant-time run time (and resistance against side-channel attacks), and its lack of nebulous hard-coded constants. The reference version being used in this document is the one described in [Curve25519] as implemented in the library NaCl [NaCl]. This document does not attempt to provide alternatives to the ecdsa-sha1-* authentication keys. 2. Key exchange The key exchange procedure is very similar to the one described chapter 4 of [RFC5656]. Public ephemeral keys are transmitted over SSH encapsulated into standard SSH strings. The following is an overview of the key exchange process: Client Server ------ ------ Generate ephemeral key pair. SSH_MSG_KEX_ECDH_INIT --------> Verify that client public key length is 32 bytes. Generate ephemeral key pair. Compute shared secret. Generate and sign exchange hash. <-------- SSH_MSG_KEX_ECDH_REPLY Verify that server public key length is 32 bytes. * Verify host keys belong to server. Compute shared secret. Generate exchange hash. Verify server's signature. * Optional but strongly recommanded as this protects against MITM attacks. This is implemented using the same messages as described in RFC5656 chapter 4 3. Method Name The name of this key exchange method is "curve25519-sha256@libssh.org". 4. Implementation considerations The whole method is based on the curve25519 scalar multiplication. In this method, a private key is a scalar of 256 bits, and a public key is a point of 256 bits. 4.1. Private key generation A 32 bytes private key should be generated for each new connection, using a secure PRNG. The following actions must be done on the private key: mysecret[0] &= 248; mysecret[31] &= 127; mysecret[31] |= 64; In order to keep the key valid. However, many cryptographic libraries will do this automatically. It should be noted that, in opposition to NIST curves, no special validation should be done to ensure the result is a valid and secure private key. 4.2 Public key generation The 32 bytes public key of either a client or a server must be generated using the 32 bytes private key and a common generator base. This base is defined as 9 followed by all zeroes: const unsigned char basepoint[32] = {9}; The public key is calculated using the cryptographic scalar multiplication: const unsigned char privkey[32]; unsigned char pubkey[32]; crypto_scalarmult (pubkey, privkey, basepoint); However some cryptographic libraries may provide a combined function: crypto_scalarmult_base (pubkey, privkey); It should be noted that, in opposition to NIST curves, no special validation should be done to ensure the received public keys are valid curves point. The Curve25519 algorithm ensure that every possible public key maps to a valid ECC Point. 4.3 Shared secret generation The shared secret, k, is defined in SSH specifications to be a big integer. This number is calculated using the following procedure: X is the 32 bytes point obtained by the scalar multiplication of the other side's public key and the local private key scalar. The whole 32 bytes of the number X are then converted into a big integer k. This conversion follows the network byte order. This step differs from RFC5656. [RFC5656] https://tools.ietf.org/html/rfc5656 [SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929 [DJB] https://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf [Curve25519] "Curve25519: new Diffie-Hellman speed records." https://cr.yp.to/ecdh/curve25519-20060209.pdf ================================================ FILE: src/libssh/doc/forwarding.dox ================================================ /** @page libssh_tutor_forwarding Chapter 7: Forwarding connections (tunnel) @section forwarding_connections Forwarding connections Port forwarding comes in SSH protocol in two different flavours: direct or reverse port forwarding. Direct port forwarding is also named local port forwarding, and reverse port forwarding is also called remote port forwarding. SSH also allows X11 tunnels. @subsection forwarding_direct Direct port forwarding Direct port forwarding is from client to server. The client opens a tunnel, and forwards whatever data to the server. Then, the server connects to an end point. The end point can reside on another machine or on the SSH server itself. Example of use of direct port forwarding: @verbatim Mail client application Google Mail | ^ 5555 (arbitrary) | | 143 (IMAP2) V | SSH client =====> SSH server Legend: --P-->: port connections through port P =====>: SSH tunnel @endverbatim A mail client connects to port 5555 of a client. An encrypted tunnel is established to the server. The server connects to port 143 of Google Mail (the end point). Now the local mail client can retrieve mail. @subsection forwarding_reverse Reverse port forwarding The reverse forwarding is slightly different. It goes from server to client, even though the client has the initiative of establishing the tunnel. Once the tunnel is established, the server will listen on a port. Whenever a connection to this port is made, the server forwards the data to the client. Example of use of reverse port forwarding: @verbatim Local mail server Mail client application ^ | | 5555 (arbitrary) 143 (IMAP2) | | V SSH client <===== SSH server Legend: --P-->: port connections through port P =====>: SSH tunnel @endverbatim In this example, the SSH client establishes the tunnel, but it is used to forward the connections established at the server to the client. @subsection forwarding_x11 X11 tunnels X11 tunnels allow a remote application to display locally. Example of use of X11 tunnels: @verbatim Local display Graphical application (X11 server) (X11 client) ^ | | V SSH client <===== SSH server Legend: ----->: X11 connection through X11 display number =====>: SSH tunnel @endverbatim The SSH tunnel is established by the client. How to establish X11 tunnels with libssh has already been described in this tutorial. @see x11 @subsection libssh_direct Doing direct port forwarding with libssh To do direct port forwarding, call function ssh_channel_open_forward(): - you need a separate channel for the tunnel as first parameter; - second and third parameters are the remote endpoint; - fourth and fifth parameters are sent to the remote server so that they can be logged on that server. If you don't plan to forward the data you will receive to any local port, just put fake values like "localhost" and 5555 as your local host and port. The example below shows how to open a direct channel that would be used to retrieve google's home page from the remote SSH server. @code int direct_forwarding(ssh_session session) { ssh_channel forwarding_channel; int rc; char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n"; int nbytes, nwritten; forwarding_channel = ssh_channel_new(session); if (forwarding_channel == NULL) { return rc; } rc = ssh_channel_open_forward(forwarding_channel, "www.google.com", 80, "localhost", 5555); if (rc != SSH_OK) { ssh_channel_free(forwarding_channel); return rc; } nbytes = strlen(http_get); nwritten = ssh_channel_write(forwarding_channel, http_get, nbytes); if (nbytes != nwritten) { ssh_channel_free(forwarding_channel); return SSH_ERROR; } ... ssh_channel_free(forwarding_channel); return SSH_OK; } @endcode The data sent by Google can be retrieved for example with ssh_select() and ssh_channel_read(). Goggle's home page can then be displayed on the local SSH client, saved into a local file, made available on a local port, or whatever use you have for it. @subsection libssh_reverse Doing reverse port forwarding with libssh To do reverse port forwarding, call ssh_channel_listen_forward(), then ssh_channel_accept_forward(). When you call ssh_channel_listen_forward(), you can let the remote server chose the non-privileged port it should listen to. Otherwise, you can chose your own privileged or non-privileged port. Beware that you should have administrative privileges on the remote server to open a privileged port (port number < 1024). Below is an example of a very rough web server waiting for connections on port 8080 of remote SSH server. The incoming connections are passed to the local libssh application, which handles them: @code int web_server(ssh_session session) { int rc; ssh_channel channel; char buffer[256]; int nbytes, nwritten; int port = 0; char *helloworld = "" "HTTP/1.1 200 OK\n" "Content-Type: text/html\n" "Content-Length: 113\n" "\n" "\n" " \n" " Hello, World!\n" " \n" " \n" "

Hello, World!

\n" " \n" "\n"; rc = ssh_channel_listen_forward(session, NULL, 8080, NULL); if (rc != SSH_OK) { fprintf(stderr, "Error opening remote port: %s\n", ssh_get_error(session)); return rc; } channel = ssh_channel_accept_forward(session, 60000, &port); if (channel == NULL) { fprintf(stderr, "Error waiting for incoming connection: %s\n", ssh_get_error(session)); return SSH_ERROR; } while (1) { nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); if (nbytes < 0) { fprintf(stderr, "Error reading incoming data: %s\n", ssh_get_error(session)); ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_ERROR; } if (strncmp(buffer, "GET /", 5)) continue; nbytes = strlen(helloworld); nwritten = ssh_channel_write(channel, helloworld, nbytes); if (nwritten != nbytes) { fprintf(stderr, "Error sending answer: %s\n", ssh_get_error(session)); ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_ERROR; } printf("Sent answer\n"); } ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_OK; } @endcode */ ================================================ FILE: src/libssh/doc/guided_tour.dox ================================================ /** @page libssh_tutor_guided_tour Chapter 1: A typical SSH session @section ssh_session A typical SSH session A SSH session goes through the following steps: - Before connecting to the server, you can set up if you wish one or other server public key authentication, i.e. DSA or RSA. You can choose cryptographic algorithms you trust and compression algorithms if any. You must of course set up the hostname. - The connection is established. A secure handshake is made, and resulting from it, a public key from the server is gained. You MUST verify that the public key is legitimate, using for instance the MD5 fingerprint or the known hosts file. - The client must authenticate: the classical ways are password, or public keys (from dsa and rsa key-pairs generated by openssh). If a SSH agent is running, it is possible to use it. - Now that the user has been authenticated, you must open one or several channels. Channels are different subways for information into a single ssh connection. Each channel has a standard stream (stdout) and an error stream (stderr). You can theoretically open an infinity of channels. - With the channel you opened, you can do several things: - Execute a single command. - Open a shell. You may want to request a pseudo-terminal before. - Invoke the sftp subsystem to transfer files. - Invoke the scp subsystem to transfer files. - Invoke your own subsystem. This is outside the scope of this document, but can be done. - When everything is finished, just close the channels, and then the connection. The sftp and scp subsystems use channels, but libssh hides them to the programmer. If you want to use those subsystems, instead of a channel, you'll usually open a "sftp session" or a "scp session". @subsection setup Creating the session and setting options The most important object in a SSH connection is the SSH session. In order to allocate a new SSH session, you use ssh_new(). Don't forget to always verify that the allocation succeeded. @code #include #include int main() { ssh_session my_ssh_session = ssh_new(); if (my_ssh_session == NULL) exit(-1); ... ssh_free(my_ssh_session); } @endcode libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new() does the allocation and ssh_free() does the contrary. The ssh_options_set() function sets the options of the session. The most important options are: - SSH_OPTIONS_HOST: the name of the host you want to connect to - SSH_OPTIONS_PORT: the used port (default is port 22) - SSH_OPTIONS_USER: the system user under which you want to connect - SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed The complete list of options can be found in the documentation of ssh_options_set(). The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER, the local username of your account will be used. Here is a small example of how to use it: @code #include #include int main() { ssh_session my_ssh_session; int verbosity = SSH_LOG_PROTOCOL; int port = 22; my_ssh_session = ssh_new(); if (my_ssh_session == NULL) exit(-1); ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port); ... ssh_free(my_ssh_session); } @endcode Please notice that all parameters are passed to ssh_options_set() as pointers, even if you need to set an integer value. @see ssh_new @see ssh_free @see ssh_options_set @see ssh_options_parse_config @see ssh_options_copy @see ssh_options_getopt @subsection connect Connecting to the server Once all settings have been made, you can connect using ssh_connect(). That function will return SSH_OK if the connection worked, SSH_ERROR otherwise. You can get the English error string with ssh_get_error() in order to show the user what went wrong. Then, use ssh_disconnect() when you want to stop the session. Here's an example: @code #include #include #include int main() { ssh_session my_ssh_session; int rc; my_ssh_session = ssh_new(); if (my_ssh_session == NULL) exit(-1); ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); rc = ssh_connect(my_ssh_session); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to localhost: %s\n", ssh_get_error(my_ssh_session)); exit(-1); } ... ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); } @endcode @subsection serverauth Authenticating the server Once you're connected, the following step is mandatory: you must check that the server you just connected to is known and safe to use (remember, SSH is about security and authentication). There are two ways of doing this: - The first way (recommended) is to use the ssh_session_is_known_server() function. This function will look into the known host file (~/.ssh/known_hosts on UNIX), look for the server hostname's pattern, and determine whether this host is present or not in the list. - The second way is to use ssh_get_pubkey_hash() to get a binary version of the public key hash value. You can then use your own database to check if this public key is known and secure. You can also use the ssh_get_pubkey_hash() to show the public key hash value to the user, in case he knows what the public key hash value is (some paranoid people write their public key hash values on paper before going abroad, just in case ...). If the remote host is being used to for the first time, you can ask the user whether he/she trusts it. Once he/she concluded that the host is valid and worth being added in the known hosts file, you use ssh_write_knownhost() to register it in the known hosts file, or any other way if you use your own database. The following example is part of the examples suite available in the examples/ directory: @code #include #include int verify_knownhost(ssh_session session) { enum ssh_known_hosts_e state; unsigned char *hash = NULL; ssh_key srv_pubkey = NULL; size_t hlen; char buf[10]; char *hexa; char *p; int cmp; int rc; rc = ssh_get_server_publickey(session, &srv_pubkey); if (rc < 0) { return -1; } rc = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen); ssh_key_free(srv_pubkey); if (rc < 0) { return -1; } state = ssh_session_is_known_server(session); switch (state) { case SSH_KNOWN_HOSTS_OK: /* OK */ break; case SSH_KNOWN_HOSTS_CHANGED: fprintf(stderr, "Host key for server changed: it is now:\n"); ssh_print_hexa("Public key hash", hash, hlen); fprintf(stderr, "For security reasons, connection will be stopped\n"); ssh_clean_pubkey_hash(&hash); return -1; case SSH_KNOWN_HOSTS_OTHER: fprintf(stderr, "The host key for this server was not found but an other" "type of key exists.\n"); fprintf(stderr, "An attacker might change the default server key to" "confuse your client into thinking the key does not exist\n"); ssh_clean_pubkey_hash(&hash); return -1; case SSH_KNOWN_HOSTS_NOT_FOUND: fprintf(stderr, "Could not find known host file.\n"); fprintf(stderr, "If you accept the host key here, the file will be" "automatically created.\n"); /* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */ case SSH_KNOWN_HOSTS_UNKNOWN: hexa = ssh_get_hexa(hash, hlen); fprintf(stderr,"The server is unknown. Do you trust the host key?\n"); fprintf(stderr, "Public key hash: %s\n", hexa); ssh_string_free_char(hexa); ssh_clean_pubkey_hash(&hash); p = fgets(buf, sizeof(buf), stdin); if (p == NULL) { return -1; } cmp = strncasecmp(buf, "yes", 3); if (cmp != 0) { return -1; } rc = ssh_session_update_known_hosts(session); if (rc < 0) { fprintf(stderr, "Error %s\n", strerror(errno)); return -1; } break; case SSH_KNOWN_HOSTS_ERROR: fprintf(stderr, "Error %s", ssh_get_error(session)); ssh_clean_pubkey_hash(&hash); return -1; } ssh_clean_pubkey_hash(&hash); return 0; } @endcode @see ssh_connect @see ssh_disconnect @see ssh_get_error @see ssh_get_error_code @see ssh_get_server_publickey @see ssh_get_publickey_hash @see ssh_session_is_known_server @see ssh_session_update_known_hosts @subsection auth Authenticating the user The authentication process is the way a service provider can identify a user and verify his/her identity. The authorization process is about enabling the authenticated user the access to resources. In SSH, the two concepts are linked. After authentication, the server can grant the user access to several resources such as port forwarding, shell, sftp subsystem, and so on. libssh supports several methods of authentication: - "none" method. This method allows to get the available authentications methods. It also gives the server a chance to authenticate the user with just his/her login. Some very old hardware uses this feature to fallback the user on a "telnet over SSH" style of login. - password method. A password is sent to the server, which accepts it or not. - keyboard-interactive method. The server sends several challenges to the user, who must answer correctly. This makes possible the authentication via a codebook for instance ("give code at 23:R on page 3"). - public key method. The host knows the public key of the user, and the user must prove he knows the associated private key. This can be done manually, or delegated to the SSH agent as we'll see later. All these methods can be combined. You can for instance force the user to authenticate with at least two of the authentication methods. In that case, one speaks of "Partial authentication". A partial authentication is a response from authentication functions stating that your credential was accepted, but yet another one is required to get in. The example below shows an authentication with password: @code #include #include #include int main() { ssh_session my_ssh_session; int rc; char *password; // Open session and set options my_ssh_session = ssh_new(); if (my_ssh_session == NULL) exit(-1); ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost"); // Connect to server rc = ssh_connect(my_ssh_session); if (rc != SSH_OK) { fprintf(stderr, "Error connecting to localhost: %s\n", ssh_get_error(my_ssh_session)); ssh_free(my_ssh_session); exit(-1); } // Verify the server's identity // For the source code of verify_knownhost(), check previous example if (verify_knownhost(my_ssh_session) < 0) { ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); exit(-1); } // Authenticate ourselves password = getpass("Password: "); rc = ssh_userauth_password(my_ssh_session, NULL, password); if (rc != SSH_AUTH_SUCCESS) { fprintf(stderr, "Error authenticating with password: %s\n", ssh_get_error(my_ssh_session)); ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); exit(-1); } ... ssh_disconnect(my_ssh_session); ssh_free(my_ssh_session); } @endcode @see @ref authentication_details @subsection using_ssh Doing something At this point, the authenticity of both server and client is established. Time has come to take advantage of the many possibilities offered by the SSH protocol: execute a remote command, open remote shells, transfer files, forward ports, etc. The example below shows how to execute a remote command: @code int show_remote_processes(ssh_session session) { ssh_channel channel; int rc; char buffer[256]; int nbytes; channel = ssh_channel_new(session); if (channel == NULL) return SSH_ERROR; rc = ssh_channel_open_session(channel); if (rc != SSH_OK) { ssh_channel_free(channel); return rc; } rc = ssh_channel_request_exec(channel, "ps aux"); if (rc != SSH_OK) { ssh_channel_close(channel); ssh_channel_free(channel); return rc; } nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); while (nbytes > 0) { if (write(1, buffer, nbytes) != (unsigned int) nbytes) { ssh_channel_close(channel); ssh_channel_free(channel); return SSH_ERROR; } nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); } if (nbytes < 0) { ssh_channel_close(channel); ssh_channel_free(channel); return SSH_ERROR; } ssh_channel_send_eof(channel); ssh_channel_close(channel); ssh_channel_free(channel); return SSH_OK; } @endcode Each ssh_channel_request_exec() needs to be run on freshly created and connected (with ssh_channel_open_session()) channel. @see @ref opening_shell @see @ref remote_command @see @ref sftp_subsystem @see @ref scp_subsystem @subsection errors Handling the errors All the libssh functions which return an error value also set an English error message describing the problem. Error values are typically SSH_ERROR for integer values, or NULL for pointers. The function ssh_get_error() returns a pointer to the static error message. ssh_error_code() returns the error code number : SSH_NO_ERROR, SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL, or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your request, but the situation is recoverable. The others mean something happened to the connection (some encryption problems, server problems, ...). SSH_INVALID_REQUEST means the library got some garbage from server, but might be recoverable. SSH_FATAL means the connection has an important problem and isn't probably recoverable. Most of time, the error returned are SSH_FATAL, but some functions (generally the ssh_request_xxx ones) may fail because of server denying request. In these cases, SSH_REQUEST_DENIED is returned. For thread safety, errors are bound to ssh_session objects. As long as your ssh_session object is not NULL, you can retrieve the last error message and error code from the ssh_session using ssh_get_error() and ssh_get_error_code() respectively. The SFTP subsystem has its own error codes, in addition to libssh ones. */ ================================================ FILE: src/libssh/doc/introduction.dox ================================================ /** @page libssh_tutorial The Tutorial @section introduction Introduction libssh is a C library that enables you to write a program that uses the SSH protocol. With it, you can remotely execute programs, transfer files, or use a secure and transparent tunnel for your remote programs. The SSH protocol is encrypted, ensures data integrity, and provides strong means of authenticating both the server of the client. The library hides a lot of technical details from the SSH protocol, but this does not mean that you should not try to know about and understand these details. libssh is a Free Software / Open Source project. The libssh library is distributed under LGPL license. The libssh project has nothing to do with "libssh2", which is a completely different and independent project. libssh can run on top of either libgcrypt or libcrypto, two general-purpose cryptographic libraries. This tutorial concentrates for its main part on the "client" side of libssh. To learn how to accept incoming SSH connections (how to write a SSH server), you'll have to jump to the end of this document. This tutorial describes libssh version 0.5.0. This version is a little different from the 0.4.X series. However, the examples should work with little changes on versions like 0.4.2 and later. Table of contents: @subpage libssh_tutor_guided_tour @subpage libssh_tutor_authentication @subpage libssh_tutor_shell @subpage libssh_tutor_command @subpage libssh_tutor_sftp @subpage libssh_tutor_scp @subpage libssh_tutor_forwarding @subpage libssh_tutor_threads @subpage libssh_tutor_todo */ ================================================ FILE: src/libssh/doc/linking.dox ================================================ /** @page libssh_linking The Linking HowTo @section dynamic Dynamic Linking On UNIX and Windows systems its the same, you need at least the libssh.h header file and the libssh shared library. @section static Static Linking @warning The libssh library is licensed under the LGPL! Make sure you understand what this means to your codebase if you want to distribute binaries and link statically against LGPL code! On UNIX systems linking against the static version of the library is the same as linking against the shared library. Both have the same name. Some build system require to use the full path to the static library. To be able to compile the application you're developing you need to either pass LIBSSH_STATIC as a define in the compiler command line or define it before you include libssh.h. This is required cause the dynamic library needs to specify the dllimport attribute. @code #define LIBSSH_STATIC 1 #include @endcode If you're are statically linking with OpenSSL, read the "Linking your application" section in the NOTES.[OS] in the OpenSSL source tree! */ ================================================ FILE: src/libssh/doc/mainpage.dox ================================================ /** @mainpage This is the online reference for developing with the libssh library. It documents the libssh C API and the C++ wrapper. @section main-linking Linking We created a small howto how to link libssh against your application, read @subpage libssh_linking. @section main-tutorial Tutorial You should start by reading @subpage libssh_tutorial, then reading the documentation of the interesting functions as you go. @section main-features Features The libssh library provides: - Key Exchange Methods: curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1 - Public Key Algorithms: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss - Ciphers: aes256-ctr, aes192-ctr, aes128-ctr, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, none - Compression Schemes: zlib, zlib@openssh.com, none - MAC hashes: hmac-sha1, hmac-sha2-256, hmac-sha2-512, hmac-md5, none - Authentication: none, password, public-key, keyboard-interactive, gssapi-with-mic - Channels: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, auth-agent-req@openssh.com - Global Requests: tcpip-forward, forwarded-tcpip - Channel Requests: x11, pty, exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com - Subsystems: sftp(version 3), OpenSSH Extensions - SFTP: statvfs@openssh.com, fstatvfs@openssh.com - Thread-safe: Just don't share sessions - Non-blocking: it can be used both blocking and non-blocking - Your sockets: the app hands over the socket, or uses libssh sockets - OpenSSL or gcrypt: builds with either @section main-additional-features Additional Features - Client and server support - SSHv2 and SSHv1 protocol support - Supports Linux, UNIX, BSD, Solaris, OS/2 and Windows - Automated test cases with nightly tests - Event model based on poll(2), or a poll(2)-emulation. @section main-copyright Copyright Policy libssh is a project with distributed copyright ownership, which means we prefer the copyright on parts of libssh to be held by individuals rather than corporations if possible. There are historical legal reasons for this, but one of the best ways to explain it is that it’s much easier to work with individuals who have ownership than corporate legal departments if we ever need to make reasonable compromises with people using and working with libssh. We track the ownership of every part of libssh via git, our source code control system, so we know the provenance of every piece of code that is committed to libssh. So if possible, if you’re doing libssh changes on behalf of a company who normally owns all the work you do please get them to assign personal copyright ownership of your changes to you as an individual, that makes things very easy for us to work with and avoids bringing corporate legal departments into the picture. If you can’t do this we can still accept patches from you owned by your employer under a standard employment contract with corporate copyright ownership. It just requires a simple set-up process first. We use a process very similar to the way things are done in the Linux Kernel community, so it should be very easy to get a sign off from your corporate legal department. The only changes we’ve made are to accommodate the license we use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2. The process is called signing. How to sign your work ---------------------- Once you have permission to contribute to libssh from your employer, simply email a copy of the following text from your corporate email address to: contributing@libssh.org @verbatim libssh Developer's Certificate of Origin. Version 1.0 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the appropriate version of the GNU General Public License; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the GNU General Public License, in the appropriate version; or (c) The contribution was provided directly to me by some other person who certified (a) or (b) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all metadata and personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with the libssh Team's policies and the requirements of the GNU GPL where they are relevant. (e) I am granting this work to this project under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at the option of the project) any later version. https://www.gnu.org/licenses/lgpl-2.1.html @endverbatim We will maintain a copy of that email as a record that you have the rights to contribute code to libssh under the required licenses whilst working for the company where the email came from. Then when sending in a patch via the normal mechanisms described above, add a line that states: @verbatim Signed-off-by: Random J Developer @endverbatim using your real name and the email address you sent the original email you used to send the libssh Developer’s Certificate of Origin to us (sorry, no pseudonyms or anonymous contributions.) That’s it! Such code can then quite happily contain changes that have copyright messages such as: @verbatim (c) Example Corporation. @endverbatim and can be merged into the libssh codebase in the same way as patches from any other individual. You don’t need to send in a copy of the libssh Developer’s Certificate of Origin for each patch, or inside each patch. Just the sign-off message is all that is required once we’ve received the initial email. Have fun and happy libssh hacking! The libssh Team @section main-rfc Internet standard @subsection main-rfc-secsh Secure Shell (SSH) The following RFC documents described SSH-2 protcol as an Internet standard. - RFC 4250, The Secure Shell (SSH) Protocol Assigned Numbers - RFC 4251, The Secure Shell (SSH) Protocol Architecture - RFC 4252, The Secure Shell (SSH) Authentication Protocol - RFC 4253, The Secure Shell (SSH) Transport Layer Protocol - RFC 4254, The Secure Shell (SSH) Connection Protocol - RFC 4255, Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints (not implemented in libssh) - RFC 4256, Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) - RFC 4335, The Secure Shell (SSH) Session Channel Break Extension - RFC 4344, The Secure Shell (SSH) Transport Layer Encryption Modes - RFC 4345, Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol It was later modified and expanded by the following RFCs. - RFC 4419, Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol - RFC 4432, RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol (not implemented in libssh) - RFC 4462, Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol (only the authentication implemented in libssh) - RFC 4716, The Secure Shell (SSH) Public Key File Format (not implemented in libssh) - RFC 5647, AES Galois Counter Mode for the Secure Shell Transport Layer Protocol (the algorithm negotiation implemented according to openssh.com) - RFC 5656, Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer - RFC 6594, Use of the SHA-256 Algorithm with RSA, DSA, and ECDSA in SSHFP Resource Records (not implemented in libssh) - RFC 6668, SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol - RFC 7479, Using Ed25519 in SSHFP Resource Records (not implemented in libssh) - RFC 8160, IUTF8 Terminal Mode in Secure Shell (SSH) (not handled in libssh) - RFC 8270, Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits - RFC 8308, Extension Negotiation in the Secure Shell (SSH) Protocol (only the "server-sig-algs" extension implemented) - RFC 8332, Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol There are also drafts that are being currently developed and followed. - draft-ietf-curdle-ssh-kex-sha2-10 Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH) - draft-miller-ssh-agent-03 SSH Agent Protocol - draft-ietf-curdle-ssh-curves-12 Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448 Interesting cryptography documents: - PKCS #11, PKCS #11 reference documents, describing interface with smartcards. @subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP) The protocol is not an Internet standard but it is still widely implemented. OpenSSH and most other implementation implement Version 3 of the protocol. We do the same in libssh. - draft-ietf-secsh-filexfer-02.txt, SSH File Transfer Protocol @subsection main-rfc-extensions Secure Shell Extensions The OpenSSH project has defined some extensions to the protocol. We support some of them like the statvfs calls in SFTP or the ssh-agent. - OpenSSH's deviations and extensions - OpenSSH's pubkey certificate authentication - chacha20-poly1305@openssh.com authenticated encryption mode - OpenSSH private key format (openssh-key-v1) */ ================================================ FILE: src/libssh/doc/scp.dox ================================================ /** @page libssh_tutor_scp Chapter 6: The SCP subsystem @section scp_subsystem The SCP subsystem The SCP subsystem has far less functionality than the SFTP subsystem. However, if you only need to copy files from and to the remote system, it does its job. @subsection scp_session Opening and closing a SCP session Like in the SFTP subsystem, you don't handle the SSH channels directly. Instead, you open a "SCP session". When you open your SCP session, you have to choose between read or write mode. You can't do both in the same session. So you specify either SSH_SCP_READ or SSH_SCP_WRITE as the second parameter of function ssh_scp_new(). Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE. When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate the behaviour of "scp -r" command in your program, no matter it is for reading or for writing. Once your session is created, you initialize it with ssh_scp_init(). When you have finished transferring files, you terminate the SCP connection with ssh_scp_close(). Finally, you can dispose the SCP connection with ssh_scp_free(). The example below does the maintenance work to open a SCP connection for writing in recursive mode: @code int scp_write(ssh_session session) { ssh_scp scp; int rc; scp = ssh_scp_new (session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, "."); if (scp == NULL) { fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session)); return SSH_ERROR; } rc = ssh_scp_init(scp); if (rc != SSH_OK) { fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session)); ssh_scp_free(scp); return rc; } ... ssh_scp_close(scp); ssh_scp_free(scp); return SSH_OK; } @endcode The example below shows how to open a connection to read a single file: @code int scp_read(ssh_session session) { ssh_scp scp; int rc; scp = ssh_scp_new (session, SSH_SCP_READ, "helloworld/helloworld.txt"); if (scp == NULL) { fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session)); return SSH_ERROR; } rc = ssh_scp_init(scp); if (rc != SSH_OK) { fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session)); ssh_scp_free(scp); return rc; } ... ssh_scp_close(scp); ssh_scp_free(scp); return SSH_OK; } @endcode @subsection scp_write Creating files and directories You create directories with ssh_scp_push_directory(). In recursive mode, you are placed in this directory once it is created. If the directory already exists and if you are in recursive mode, you simply enter that directory. Creating files is done in two steps. First, you prepare the writing with ssh_scp_push_file(). Then, you write the data with ssh_scp_write(). The length of the data to write must be identical between both function calls. There's no need to "open" nor "close" the file, this is done automatically on the remote end. If the file already exists, it is overwritten and truncated. The following example creates a new directory named "helloworld/", then creates a file named "helloworld.txt" in that directory: @code int scp_helloworld(ssh_session session, ssh_scp scp) { int rc; const char *helloworld = "Hello, world!\n"; int length = strlen(helloworld); rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU); if (rc != SSH_OK) { fprintf(stderr, "Can't create remote directory: %s\n", ssh_get_error(session)); return rc; } rc = ssh_scp_push_file (scp, "helloworld.txt", length, S_IRUSR | S_IWUSR); if (rc != SSH_OK) { fprintf(stderr, "Can't open remote file: %s\n", ssh_get_error(session)); return rc; } rc = ssh_scp_write(scp, helloworld, length); if (rc != SSH_OK) { fprintf(stderr, "Can't write to remote file: %s\n", ssh_get_error(session)); return rc; } return SSH_OK; } @endcode @subsection scp_recursive_write Copying full directory trees to the remote server Let's say you want to copy the following tree of files to the remote site: @verbatim +-- file1 +-- B --+ | +-- file2 -- A --+ | +-- file3 +-- C --+ +-- file4 @endverbatim You would do it that way: - open the session in recursive mode - enter directory A - enter its subdirectory B - create file1 in B - create file2 in B - leave directory B - enter subdirectory C - create file3 in C - create file4 in C - leave directory C - leave directory A To leave a directory, call ssh_scp_leave_directory(). @subsection scp_read Reading files and directories To receive files, you pull requests from the other side with ssh_scp_pull_request(). If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for the reception. You can get the size of the data to receive with ssh_scp_request_get_size() and allocate a buffer accordingly. When you are ready, you accept the request with ssh_scp_accept_request(), then read the data with ssh_scp_read(). The following example receives a single file. The name of the file to receive has been given earlier, when the scp session was opened: @code int scp_receive(ssh_session session, ssh_scp scp) { int rc; int size, mode; char *filename, *buffer; rc = ssh_scp_pull_request(scp); if (rc != SSH_SCP_REQUEST_NEWFILE) { fprintf(stderr, "Error receiving information about file: %s\n", ssh_get_error(session)); return SSH_ERROR; } size = ssh_scp_request_get_size(scp); filename = strdup(ssh_scp_request_get_filename(scp)); mode = ssh_scp_request_get_permissions(scp); printf("Receiving file %s, size %d, permissions 0%o\n", filename, size, mode); free(filename); buffer = malloc(size); if (buffer == NULL) { fprintf(stderr, "Memory allocation error\n"); return SSH_ERROR; } ssh_scp_accept_request(scp); rc = ssh_scp_read(scp, buffer, size); if (rc == SSH_ERROR) { fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session)); free(buffer); return rc; } printf("Done\n"); write(1, buffer, size); free(buffer); rc = ssh_scp_pull_request(scp); if (rc != SSH_SCP_REQUEST_EOF) { fprintf(stderr, "Unexpected request: %s\n", ssh_get_error(session)); return SSH_ERROR; } return SSH_OK; } @endcode In this example, since we just requested a single file, we expect ssh_scp_request() to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a naive approach; for example, the remote server might send a warning as well (return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive reception program would receive the requests in a loop and analyze them carefully until SSH_SCP_REQUEST_EOF has been received. @subsection scp_recursive_read Receiving full directory trees from the remote server If you opened the SCP session in recursive mode, the remote end will be telling you when to change directory. In that case, when ssh_scp_pull_request() answers SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if it does not exist yet) and enter it. When ssh_scp_pull_request() answers SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory. */ ================================================ FILE: src/libssh/doc/sftp.dox ================================================ /** @page libssh_tutor_sftp Chapter 5: The SFTP subsystem @section sftp_subsystem The SFTP subsystem SFTP stands for "Secure File Transfer Protocol". It enables you to safely transfer files between the local and the remote computer. It reminds a lot of the old FTP protocol. SFTP is a rich protocol. It lets you do over the network almost everything that you can do with local files: - send files - modify only a portion of a file - receive files - receive only a portion of a file - get file owner and group - get file permissions - set file owner and group - set file permissions - remove files - rename files - create a directory - remove a directory - retrieve the list of files in a directory - get the target of a symbolic link - create symbolic links - get information about mounted filesystems. The current implemented version of the SFTP protocol is version 3. All functions aren't implemented yet, but the most important are. @subsection sftp_session Opening and closing a SFTP session Unlike with remote shells and remote commands, when you use the SFTP subsystem, you don't handle directly the SSH channels. Instead, you open a "SFTP session". The function sftp_new() creates a new SFTP session. The function sftp_init() initializes it. The function sftp_free() deletes it. As you see, all the SFTP-related functions start with the "sftp_" prefix instead of the usual "ssh_" prefix. The example below shows how to use these functions: @code #include int sftp_helloworld(ssh_session session) { sftp_session sftp; int rc; sftp = sftp_new(session); if (sftp == NULL) { fprintf(stderr, "Error allocating SFTP session: %s\n", ssh_get_error(session)); return SSH_ERROR; } rc = sftp_init(sftp); if (rc != SSH_OK) { fprintf(stderr, "Error initializing SFTP session: code %d.\n", sftp_get_error(sftp)); sftp_free(sftp); return rc; } ... sftp_free(sftp); return SSH_OK; } @endcode @subsection sftp_errors Analyzing SFTP errors In case of a problem, the function sftp_get_error() returns a SFTP-specific error number, in addition to the regular SSH error number returned by ssh_get_error_number(). Possible errors are: - SSH_FX_OK: no error - SSH_FX_EOF: end-of-file encountered - SSH_FX_NO_SUCH_FILE: file does not exist - SSH_FX_PERMISSION_DENIED: permission denied - SSH_FX_FAILURE: generic failure - SSH_FX_BAD_MESSAGE: garbage received from server - SSH_FX_NO_CONNECTION: no connection has been set up - SSH_FX_CONNECTION_LOST: there was a connection, but we lost it - SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet - SSH_FX_INVALID_HANDLE: invalid file handle - SSH_FX_NO_SUCH_PATH: no such file or directory path exists - SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made - SSH_FX_WRITE_PROTECT: write-protected filesystem - SSH_FX_NO_MEDIA: no media was in remote drive @subsection sftp_mkdir Creating a directory The function sftp_mkdir() takes the "SFTP session" we just created as its first argument. It also needs the name of the file to create, and the desired permissions. The permissions are the same as for the usual mkdir() function. To get a comprehensive list of the available permissions, use the "man 2 stat" command. The desired permissions are combined with the remote user's mask to determine the effective permissions. The code below creates a directory named "helloworld" in the current directory that can be read and written only by its owner: @code #include #include int sftp_helloworld(ssh_session session, sftp_session sftp) { int rc; rc = sftp_mkdir(sftp, "helloworld", S_IRWXU); if (rc != SSH_OK) { if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS) { fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session)); return rc; } } ... return SSH_OK; } @endcode Unlike its equivalent in the SCP subsystem, this function does NOT change the current directory to the newly created subdirectory. @subsection sftp_write Copying a file to the remote computer You handle the contents of a remote file just like you would do with a local file: you open the file in a given mode, move the file pointer in it, read or write data, and close the file. The sftp_open() function is very similar to the regular open() function, excepted that it returns a file handle of type sftp_file. This file handle is then used by the other file manipulation functions and remains valid until you close the remote file with sftp_close(). The example below creates a new file named "helloworld.txt" in the newly created "helloworld" directory. If the file already exists, it will be truncated. It then writes the famous "Hello, World!" sentence to the file, followed by a new line character. Finally, the file is closed: @code #include #include #include int sftp_helloworld(ssh_session session, sftp_session sftp) { int access_type = O_WRONLY | O_CREAT | O_TRUNC; sftp_file file; const char *helloworld = "Hello, World!\n"; int length = strlen(helloworld); int rc, nwritten; ... file = sftp_open(sftp, "helloworld/helloworld.txt", access_type, S_IRWXU); if (file == NULL) { fprintf(stderr, "Can't open file for writing: %s\n", ssh_get_error(session)); return SSH_ERROR; } nwritten = sftp_write(file, helloworld, length); if (nwritten != length) { fprintf(stderr, "Can't write data to file: %s\n", ssh_get_error(session)); sftp_close(file); return SSH_ERROR; } rc = sftp_close(file); if (rc != SSH_OK) { fprintf(stderr, "Can't close the written file: %s\n", ssh_get_error(session)); return rc; } return SSH_OK; } @endcode @subsection sftp_read Reading a file from the remote computer The nice thing with reading a file over the network through SFTP is that it can be done both in a synchronous way or an asynchronous way. If you read the file asynchronously, your program can do something else while it waits for the results to come. Synchronous read is done with sftp_read(). Files are normally transferred in chunks. A good chunk size is 16 KB. The following example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we request, sftp_read blocks till the data has been received: @code // Good chunk size #define MAX_XFER_BUF_SIZE 16384 int sftp_read_sync(ssh_session session, sftp_session sftp) { int access_type; sftp_file file; char buffer[MAX_XFER_BUF_SIZE]; int nbytes, nwritten, rc; int fd; access_type = O_RDONLY; file = sftp_open(sftp, "/etc/profile", access_type, 0); if (file == NULL) { fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session)); return SSH_ERROR; } fd = open("/path/to/profile", O_CREAT); if (fd < 0) { fprintf(stderr, "Can't open file for writing: %s\n", strerror(errno)); return SSH_ERROR; } for (;;) { nbytes = sftp_read(file, buffer, sizeof(buffer)); if (nbytes == 0) { break; // EOF } else if (nbytes < 0) { fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session)); sftp_close(file); return SSH_ERROR; } nwritten = write(fd, buffer, nbytes); if (nwritten != nbytes) { fprintf(stderr, "Error writing: %s\n", strerror(errno)); sftp_close(file); return SSH_ERROR; } } rc = sftp_close(file); if (rc != SSH_OK) { fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session)); return rc; } return SSH_OK; } @endcode Asynchronous read is done in two steps, first sftp_async_read_begin(), which returns a "request handle", and then sftp_async_read(), which uses that request handle. If the file has been opened in nonblocking mode, then sftp_async_read() might return SSH_AGAIN, which means that the request hasn't completed yet and that the function should be called again later on. Otherwise, sftp_async_read() waits for the data to come. To open a file in nonblocking mode, call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode. The example below reads a very big file in asynchronous, nonblocking, mode. Each time the data is not ready yet, a counter is incremented. @code // Good chunk size #define MAX_XFER_BUF_SIZE 16384 int sftp_read_async(ssh_session session, sftp_session sftp) { int access_type; sftp_file file; char buffer[MAX_XFER_BUF_SIZE]; int async_request; int nbytes; long counter; int rc; access_type = O_RDONLY; file = sftp_open(sftp, "some_very_big_file", access_type, 0); if (file == NULL) { fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session)); return SSH_ERROR; } sftp_file_set_nonblocking(file); async_request = sftp_async_read_begin(file, sizeof(buffer)); counter = 0L; usleep(10000); if (async_request >= 0) { nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request); } else { nbytes = -1; } while (nbytes > 0 || nbytes == SSH_AGAIN) { if (nbytes > 0) { write(1, buffer, nbytes); async_request = sftp_async_read_begin(file, sizeof(buffer)); } else { counter++; } usleep(10000); if (async_request >= 0) { nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request); } else { nbytes = -1; } } if (nbytes < 0) { fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session)); sftp_close(file); return SSH_ERROR; } printf("The counter has reached value: %ld\n", counter); rc = sftp_close(file); if (rc != SSH_OK) { fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session)); return rc; } return SSH_OK; } @endcode @subsection sftp_ls Listing the contents of a directory The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(), and sftp_closedir() enable to list the contents of a directory. They use a new handle_type, "sftp_dir", which gives access to the directory being read. In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer to a structure with information about a directory entry: - name: the name of the file or directory - size: its size in bytes - etc. sftp_readdir() might return NULL under two conditions: - when the end of the directory has been met - when an error occurred To tell the difference, call sftp_dir_eof(). The attributes must be freed with sftp_attributes_free() when no longer needed. The following example reads the contents of some remote directory: @code int sftp_list_dir(ssh_session session, sftp_session sftp) { sftp_dir dir; sftp_attributes attributes; int rc; dir = sftp_opendir(sftp, "/var/log"); if (!dir) { fprintf(stderr, "Directory not opened: %s\n", ssh_get_error(session)); return SSH_ERROR; } printf("Name Size Perms Owner\tGroup\n"); while ((attributes = sftp_readdir(sftp, dir)) != NULL) { printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n", attributes->name, (long long unsigned int) attributes->size, attributes->permissions, attributes->owner, attributes->uid, attributes->group, attributes->gid); sftp_attributes_free(attributes); } if (!sftp_dir_eof(dir)) { fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(session)); sftp_closedir(dir); return SSH_ERROR; } rc = sftp_closedir(dir); if (rc != SSH_OK) { fprintf(stderr, "Can't close directory: %s\n", ssh_get_error(session)); return rc; } } @endcode */ ================================================ FILE: src/libssh/doc/shell.dox ================================================ /** @page libssh_tutor_shell Chapter 3: Opening a remote shell @section opening_shell Opening a remote shell We already mentioned that a single SSH connection can be shared between several "channels". Channels can be used for different purposes. This chapter shows how to open one of these channels, and how to use it to start a command interpreter on a remote computer. @subsection open_channel Opening and closing a channel The ssh_channel_new() function creates a channel. It returns the channel as a variable of type ssh_channel. Once you have this channel, you open a SSH session that uses it with ssh_channel_open_session(). Once you don't need the channel anymore, you can send an end-of-file to it with ssh_channel_close(). At this point, you can destroy the channel with ssh_channel_free(). The code sample below achieves these tasks: @code int shell_session(ssh_session session) { ssh_channel channel; int rc; channel = ssh_channel_new(session); if (channel == NULL) return SSH_ERROR; rc = ssh_channel_open_session(channel); if (rc != SSH_OK) { ssh_channel_free(channel); return rc; } ... ssh_channel_close(channel); ssh_channel_send_eof(channel); ssh_channel_free(channel); return SSH_OK; } @endcode @subsection interactive Interactive and non-interactive sessions A "shell" is a command interpreter. It is said to be "interactive" if there is a human user typing the commands, one after the other. The contrary, a non-interactive shell, is similar to the execution of commands in the background: there is no attached terminal. If you plan using an interactive shell, you need to create a pseud-terminal on the remote side. A remote terminal is usually referred to as a "pty", for "pseudo-teletype". The remote processes won't see the difference with a real text-oriented terminal. If needed, you request the pty with the function ssh_channel_request_pty(). Then you define its dimensions (number of rows and columns) with ssh_channel_change_pty_size(). Be your session interactive or not, the next step is to request a shell with ssh_channel_request_shell(). @code int interactive_shell_session(ssh_channel channel) { int rc; rc = ssh_channel_request_pty(channel); if (rc != SSH_OK) return rc; rc = ssh_channel_change_pty_size(channel, 80, 24); if (rc != SSH_OK) return rc; rc = ssh_channel_request_shell(channel); if (rc != SSH_OK) return rc; ... return rc; } @endcode @subsection read_data Displaying the data sent by the remote computer In your program, you will usually need to receive all the data "displayed" into the remote pty. You will usually analyse, log, or display this data. ssh_channel_read() and ssh_channel_read_nonblocking() are the simplest way to read data from a channel. If you only need to read from a single channel, they should be enough. The example below shows how to wait for remote data using ssh_channel_read(): @code int interactive_shell_session(ssh_channel channel) { int rc; char buffer[256]; int nbytes; rc = ssh_channel_request_pty(channel); if (rc != SSH_OK) return rc; rc = ssh_channel_change_pty_size(channel, 80, 24); if (rc != SSH_OK) return rc; rc = ssh_channel_request_shell(channel); if (rc != SSH_OK) return rc; while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) { nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); if (nbytes < 0) return SSH_ERROR; if (nbytes > 0) write(1, buffer, nbytes); } return rc; } @endcode Unlike ssh_channel_read(), ssh_channel_read_nonblocking() never waits for remote data to be ready. It returns immediately. If you plan to use ssh_channel_read_nonblocking() repeatedly in a loop, you should use a "passive wait" function like usleep(3) in the same loop. Otherwise, your program will consume all the CPU time, and your computer might become unresponsive. @subsection write_data Sending user input to the remote computer User's input is sent to the remote site with ssh_channel_write(). The following example shows how to combine a nonblocking read from a SSH channel with a nonblocking read from the keyboard. The local input is then sent to the remote computer: @code /* Under Linux, this function determines whether a key has been pressed. Under Windows, it is a standard function, so you need not redefine it. */ int kbhit() { struct timeval tv = { 0L, 0L }; fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); return select(1, &fds, NULL, NULL, &tv); } /* A very simple terminal emulator: - print data received from the remote computer - send keyboard input to the remote computer */ int interactive_shell_session(ssh_channel channel) { /* Session and terminal initialization skipped */ ... char buffer[256]; int nbytes, nwritten; while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) { nbytes = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0); if (nbytes < 0) return SSH_ERROR; if (nbytes > 0) { nwritten = write(1, buffer, nbytes); if (nwritten != nbytes) return SSH_ERROR; if (!kbhit()) { usleep(50000L); // 0.05 second continue; } nbytes = read(0, buffer, sizeof(buffer)); if (nbytes < 0) return SSH_ERROR; if (nbytes > 0) { nwritten = ssh_channel_write(channel, buffer, nbytes); if (nwritten != nbytes) return SSH_ERROR; } } return rc; } @endcode Of course, this is a poor terminal emulator, since the echo from the keys pressed should not be done locally, but should be done by the remote side. Also, user's input should not be sent once "Enter" key is pressed, but immediately after each key is pressed. This can be accomplished by setting the local terminal to "raw" mode with the cfmakeraw(3) function. cfmakeraw() is a standard function under Linux, on other systems you can recode it with: @code static void cfmakeraw(struct termios *termios_p) { termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); termios_p->c_cflag &= ~(CSIZE|PARENB); termios_p->c_cflag |= CS8; } @endcode If you are not using a local terminal, but some kind of graphical environment, the solution to this kind of "echo" problems will be different. @subsection select_loop A more elaborate way to get the remote data *** Warning: ssh_select() and ssh_channel_select() are not relevant anymore, since libssh is about to provide an easier system for asynchronous communications. This subsection should be removed then. *** ssh_channel_read() and ssh_channel_read_nonblocking() functions are simple, but they are not adapted when you expect data from more than one SSH channel, or from other file descriptors. Last example showed how getting data from the standard input (the keyboard) at the same time as data from the SSH channel was complicated. The functions ssh_select() and ssh_channel_select() provide a more elegant way to wait for data coming from many sources. The functions ssh_select() and ssh_channel_select() remind of the standard UNIX select(2) function. The idea is to wait for "something" to happen: incoming data to be read, outgoing data to block, or an exception to occur. Both these functions do a "passive wait", i.e. you can safely use them repeatedly in a loop, it will not consume exaggerate processor time and make your computer unresponsive. It is quite common to use these functions in your application's main loop. The difference between ssh_select() and ssh_channel_select() is that ssh_channel_select() is simpler, but allows you only to watch SSH channels. ssh_select() is more complete and enables watching regular file descriptors as well, in the same function call. Below is an example of a function that waits both for remote SSH data to come, as well as standard input from the keyboard: @code int interactive_shell_session(ssh_session session, ssh_channel channel) { /* Session and terminal initialization skipped */ ... char buffer[256]; int nbytes, nwritten; while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) { struct timeval timeout; ssh_channel in_channels[2], out_channels[2]; fd_set fds; int maxfd; timeout.tv_sec = 30; timeout.tv_usec = 0; in_channels[0] = channel; in_channels[1] = NULL; FD_ZERO(&fds); FD_SET(0, &fds); FD_SET(ssh_get_fd(session), &fds); maxfd = ssh_get_fd(session) + 1; ssh_select(in_channels, out_channels, maxfd, &fds, &timeout); if (out_channels[0] != NULL) { nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); if (nbytes < 0) return SSH_ERROR; if (nbytes > 0) { nwritten = write(1, buffer, nbytes); if (nwritten != nbytes) return SSH_ERROR; } } if (FD_ISSET(0, &fds)) { nbytes = read(0, buffer, sizeof(buffer)); if (nbytes < 0) return SSH_ERROR; if (nbytes > 0) { nwritten = ssh_channel_write(channel, buffer, nbytes); if (nbytes != nwritten) return SSH_ERROR; } } } return rc; } @endcode @subsection x11 Using graphical applications on the remote side If your remote application is graphical, you can forward the X11 protocol to your local computer. To do that, you first declare that you accept X11 connections with ssh_channel_accept_x11(). Then you create the forwarding tunnel for the X11 protocol with ssh_channel_request_x11(). The following code performs channel initialization and shell session opening, and handles a parallel X11 connection: @code int interactive_shell_session(ssh_channel channel) { int rc; ssh_channel x11channel; rc = ssh_channel_request_pty(channel); if (rc != SSH_OK) return rc; rc = ssh_channel_change_pty_size(channel, 80, 24); if (rc != SSH_OK) return rc; rc = ssh_channel_request_x11(channel, 0, NULL, NULL, 0); if (rc != SSH_OK) return rc; rc = ssh_channel_request_shell(channel); if (rc != SSH_OK) return rc; /* Read the data sent by the remote computer here */ ... } @endcode Don't forget to set the $DISPLAY environment variable on the remote side, or the remote applications won't try using the X11 tunnel: @code $ export DISPLAY=:0 $ xclock & @endcode */ ================================================ FILE: src/libssh/doc/tbd.dox ================================================ /** @page libssh_tutor_todo To be done *** To be written *** @section sshd Writing a libssh-based server *** To be written *** @section cpp The libssh C++ wrapper *** To be written *** */ ================================================ FILE: src/libssh/doc/that_style/LICENSE ================================================ MIT License Copyright (c) 2017 Jan-Lukas Wynen 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. ================================================ FILE: src/libssh/doc/that_style/README.md ================================================ # that style A plain, more modern HTML style for Doxygen ## Requirements - Doxygen (tested with version 1.8.13) - *optional*: a sass/scss compiler if you want to modify the style ## Simple usage Tell Doxygen about the files for that style as shown in [doxyfile.conf](doxyfile.conf). You might need to adjust the paths depending on where you installed that style. When you run Doxygen, all files are copied into to generated HTML folder. So you don't need to keep the originals around unless you want to re-generate the documentation. ## Advanced that style uses a custom javascript to hack some nice stripes into some tables. It has to be loaded from HTML. Hence you need to use the provided custom header. Since its default content may change when Doxygen is updated, there might be syntax error in the generated HTML. If this is the case, you can remove the custom header (adjust your doxyfile.conf). This has no disadvantages other than removing the stripes. [that_style.css](that_style.css) was generated from the scss files in the folder [sass](sass). If you want to change the style, use those files in order to have better control. For instance, you can easily change most colors by modifying the variables in the beginning of [that_style.scss](sass/that_style.scss). ================================================ FILE: src/libssh/doc/that_style/header.html ================================================ $projectname: $title $title $treeview $search $mathjax $extrastylesheet
$projectname  $projectnumber
$projectbrief
$projectbrief
$searchbox
================================================ FILE: src/libssh/doc/that_style/js/striped_bg.js ================================================ // Adds extra CSS classes "even" and "odd" to .memberdecls to allow // striped backgrounds. function MemberDeclsStriper () { var counter = 0; this.stripe = function() { $(".memberdecls tbody").children().each(function(i) { // reset counter at every heading -> always start with even if ($(this).is(".heading")) { counter = 0; } // add extra classes if (counter % 2 == 1) { $(this).addClass("odd"); } else { $(this).addClass("even"); } // advance counter at every separator // this is the only way to reliably detect which table rows belong together if ($(this).is('[class^="separator"]')) { counter++; } }); } } // execute the function $(document).ready(new MemberDeclsStriper().stripe); ================================================ FILE: src/libssh/doc/that_style/that_style.css ================================================ @charset "UTF-8"; /* * My own little style */ body, table, div, p, dl { font: 400 14px/22px Roboto,sans-serif; } h1.groupheader { font-size: 150%; } .title { font: 400 14px/28px Roboto,sans-serif; font-size: 150%; font-weight: bold; margin: 10px 2px; } h2.groupheader { border-bottom: 1px solid #555555; color: black; font-size: 200%; font-weight: bold; margin-top: 1.75em; padding-top: 1em; padding-bottom: 4px; width: 100%; } tr.heading h2 { border-bottom: 1px solid #a5a5a5; font-size: 150%; margin-top: 6px; margin-bottom: 6px; padding-top: 3px; padding-bottom: 7px; } h2.groupheader a { margin-left: 1%; } h3.groupheader { font-size: 100%; } h1, h2, h3, h4, h5, h6 { -webkit-transition: none; -moz-transition: none; -o-transition: none; transition: none; margin-right: 15px; } h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { text-shadow: none; color: #5f082b; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd { margin-top: 2px; } p.starttd { margin-top: 0px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } #top { border: none; position: relative; z-index: 100; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 0 8px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 0 8px rgba(0, 0, 0, 0.3); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 0 8px rgba(0, 0, 0, 0.3); box-shadow: 0 0 4px rgba(0, 0, 0, 0.4), 0 0 8px rgba(0, 0, 0, 0.3); } caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab { background-color: #ffffff; border: none; text-align: center; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } a, a:visited { color: #00549f; font-weight: normal; text-decoration: none; } .contents a:visited { color: #4665A2; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; text-transform: uppercase; } a.qindexHL { font-weight: bold; background-color: #9CAFD4; color: #ffffff; border: 1px double #869DCA; } .contents a.qindexHL:visited { color: #ffffff; } a.el, a.el:visited { font-weight: normal; color: #00549f; } a.elRef, a.elRef:visited { font-family: monospace; color: #006bc8; } /* * The main menu at the top */ #main-menu { background-image: none; background: #414141; padding: 0; } .sm-dox > li:not(:last-child) > a { background-image: none; text-shadow: none; color: white; font-weight: normal; letter-spacing: 1px; font-size: 11pt; text-transform: uppercase; } .sm-dox > li:not(:last-child) > a:hover, .sm-dox > li:not(:last-child) > a.highlighted { background-color: #5f082b; } .sm-dox a span.sub-arrow { border-color: white transparent transparent; } .sm-dox ul { border: none; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; padding: 0; background: #414141; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } .sm-dox ul a { background: inherit; color: white; font-weight: normal; letter-spacing: 1px; font-size: 11pt; } .sm-dox ul a:hover { background: #5f082b; color: white; font-weight: normal; letter-spacing: 1px; font-size: 11pt; } .sm-dox ul a.highlighted { background: #5f082b; color: white; font-weight: normal; letter-spacing: 1px; font-size: 11pt; } .sm-dox ul a span.sub-arrow { /* this sets the color of the arrow */ border-color: white transparent transparent; } dl.el { margin-left: -1cm; } div.ah, span.ah { background: none; color: black; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; border: none; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; font: 14pt monospace; font-weight: bold; text-transform: uppercase; } div.classindex ul { list-style: none; padding-left: 0; } div.classindex span.ai { display: inline-block; } div.groupHeader { margin-left: 16px; margin-top: 12px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background-color: #ffffff; color: black; margin: 0; } #doc-content { background-color: #111; color: #ffffff; } div.contents { color: black; background-color: #ffffff; padding: 0; margin: 5pt; } div.contents hr { display: none; visibility: hidden; } div.header + div.contents { padding: 1ex; margin: 0 5pt 5pt 5pt; } div.textblock { padding: 1ex 1ex 0 1ex; } div.textblock + ul { padding-bottom: 1%; } img.footer { border: 0px; vertical-align: middle; } /* Basic styling for fragments shared by all themes. */ div.fragment { padding: 4px; margin: 4px 8px 4px 2px; color: #bebebe; background-color: #323232; border: 3px solid #e8e8e8; border-radius: 2px; overflow-y: hidden; overflow-x: auto; position: relative; } div.line { font-family: monospace, fixed; font-size: 13px; min-height: 13px; line-height: 1.0; text-indent: -53px; margin: 0px; padding: 1px 0 1px 53px; white-space: pre; -webkit-transition: background-color; -moz-transition: background-color; -o-transition: background-color; transition: background-color; -webkit-duration: 0s; -moz-duration: 0s; -o-duration: 0s; duration: 0s; } div.line:hover { background-color: #1a1a1a; } div.line::after { content: "\000A"; white-space: pre; } span.lineno { padding-right: 4px; text-align: right; color: black; height: 100px; white-space: pre; border-right: 3px solid #1d7567; background-color: #323232; } span.lineno a, span.lineno a:visited { background-color: inherit; color: #1e595a; } span.lineno a:hover { background-color: #C8C8C8; text-decoration: none; } .lineno { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } div.fragment { color: #bebebe; background-color: #323232; } div.fragment::before { background-color: #1a1a1a; border-right: 1px solid #3e3e3e; } div.line:hover { background-color: #1a1a1a; } span.lineno { color: #969696; background-color: #323232; border-right: 1px solid #3e3e3e; } span.lineno a, span.lineno a:visited { background-color: inherit; color: #dcdcdc; } span.lineno a:hover { background-color: #323232; } a.code, a.code:visited { color: #6cc7eb; } a.codeRef, a.codeRef:visited { color: #3d95e6; } span.keyword { color: #98f77a; font-weight: bold; } span.keywordtype { color: #ffa0a0; } span.keywordflow { color: #98f77a; font-weight: bold; } span.comment { color: #999; font-style: oblique; } span.preprocessor { color: #cd5c57; } span.stringliteral { color: #64b041; } span.charliteral { color: #64b041; } blockquote { background-color: #F7F8FB; border-left: 2px solid #9CAFD4; margin: 0 24px 0 4px; padding: 0 12px 0 16px; } /* * The search box */ .sm-dox > li:last-child { margin-right: 10pt; } #MSearchBox { border: 2px inset black; display: table; width: 350px; height: 26px; background: white; margin-top: 5px; } #MSearchBox .left { background-image: none; display: table-cell; width: 100%; height: inherit; left: 0; } #MSearchBox .right { background-image: none; width: 0; display: none; visibility: hidden; } nav > #MSearchBox { border: 2px solid #666666; margin: 5px 10pt 0 0; height: 22px; } #MSearchSelect, .left #MSearchSelect { left: 0; background-image: url("mag_glass.svg"); width: 22px; height: 22px; padding: 22px 22px 0 0; margin: 0 4px 0 4px; box-sizing: border-box; } #MSearchField { background-image: none; display: table-cell; margin: 0; margin-left: 30px; width: calc(100% - 34px); height: 22px; font: 11pt sans-serif; } #MSearchSelectWindow { background-color: #414141; padding: 0; border: solid 1px black; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } a.SelectItem { color: white; padding: 3px 4px; font: 10pt sans-serif; letter-spacing: 1px; } a.SelectItem:hover { background-color: #5f082b; color: white; } a.SelectItem:focus, a.SelectItem:active { color: white; } #MSearchResultsWindow { background-color: white; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } table.memberdecls { width: 100%; border-spacing: 0px; padding: 0px; margin-top: 7px; background-color: #ffffff; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } .memberdecls tbody { background-color: #ffffff; } .memberdecls .odd { background: #f6f6f6; } /* all but last separator show a line */ .memberdecls tr[class^="separator"]:not(:last-child) .memSeparator { border-bottom: 1px solid #c5c5c5; line-height: 1px; margin: 0; padding: 0; } .memberdecls tr[class^="separator"]:last-child .memSeparator { border-bottom: none; line-height: 0; margin: 0; padding: 0; } table.fieldtable { -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; } .memberdecls td, .fieldtable tr { background-color: inherit; } .fieldtable th { display: none; height: 0; visibility: hidden; } td.fieldname { color: #820a32; font-family: monospace; font-weight: bold; } th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { background-color: #414141; color: white; } .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { font-family: monospace; background-color: #ffffff; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { background-color: #ffffff; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memItemRight { width: 100%; } .memTemplParams { color: black; white-space: nowrap; font-size: 100%; } /* Styles for detailed member documentation */ .memtitle { padding: 8px; border: none; margin-bottom: -1px; background-image: none; background-color: #f6f6f6; line-height: 1.25; font-weight: bold; color: black; float: left; z-index: 0; position: relative; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } .permalink { font-size: 100%; display: inline-block; vertical-align: middle; } /* replace content of permalinks */ .permalink a { visibility: hidden; } .permalink a:after { content: "§"; visibility: visible; display: block; position: absolute; color: black; top: 20%; } .permalink a:visited { color: black; } .memtemplate { font-size: 100%; color: black; font-family: monospace; font-weight: normal; margin-left: 9px; } .memnav { background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .mempage { width: 100%; } .memitem { font-family: monospace; padding: 0; margin-bottom: 10px; margin-right: 5px; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; display: table !important; width: 100%; background-color: #f6f6f6; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } .memitem.glow { -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; } .memname { font-family: monospace; font-weight: 400; margin-left: 6px; } .memname td { vertical-align: bottom; } .memproto, dl.reflist dt { border: none; padding: 6px 0px 6px 0px; color: black; font-weight: bold; text-shadow: none; background-color: #f6f6f6; position: relative; z-index: 1; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; } .overload { font-family: "courier new",courier,monospace; font-size: 65%; } .memdoc, dl.reflist dd { border: none; border-left: 4px solid #5f082b; border-bottom-left-radius: 0px; border-bottom-right-radius: 0px; -webkit-border-bottom-left-radius: 0px; -webkit-border-bottom-right-radius: 0px; -moz-border-bottom-left-radius: 0px; -moz-border-bottom-right-radius: 0px; padding: 2px 1% 2px 1%; margin: 1%; background-color: #ffffff; background-image: none; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; /* allow movement of elements inside */ display: flex; flex-direction: column; } /* overrides for docs on individual pages */ .memtitle:nth-child(2) { width: 0; height: 0; display: none; visibility: hidden; } .memitem:nth-child(3) { margin: 0; margin-top: 0.5%; background-color: #ffffff; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; } .memitem:nth-child(3) .memproto { padding: 10px; background-color: #ffffff; margin-bottom: 10px; } .memitem:nth-child(3) .memproto::after { content: ""; width: 99%; height: 1px; position: absolute; bottom: -10px; left: 0.5%; background: #666; } .memitem:nth-child(3) .memdoc { border: none; padding: 0; } .memitem:nth-child(3) table.memname { background-color: #f6f6f6; border-collapse: collapse; border-spacing: initial; border: 1px solid #aaa; } .memitem:nth-child(3) table.memname tr:not(:last-child) { border-bottom: 1px dashed #aaa; } dl.reflist dt { padding: 5px; z-index: 0; /* cover the top shadow of dd */ position: relative; -moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px rgba(0, 0, 0, 0.35), 0 0 8px rgba(0, 0, 0, 0.2); } /* cover up the shadow at the bottom */ dl.reflist dt::after { content: " "; width: 100%; display: block; height: 8px; position: absolute; background-color: #f6f6f6; left: 0; bottom: -8px; } dl.reflist dd { border-left: 4px solid #5f082b; padding: 2px 1% 2px 1%; margin: 8px 8px 24px 8px; outline: 8px solid #f6f6f6; -moz-box-shadow: 0 0 4px 8px rgba(0, 0, 0, 0.35), 0 0 8px 8px rgba(0, 0, 0, 0.2); -webkit-box-shadow: 0 0 4px 8px rgba(0, 0, 0, 0.35), 0 0 8px 8px rgba(0, 0, 0, 0.2); -o-box-shadow: 0 0 4px 8px rgba(0, 0, 0, 0.35), 0 0 8px 8px rgba(0, 0, 0, 0.2); box-shadow: 0 0 4px 8px rgba(0, 0, 0, 0.35), 0 0 8px 8px rgba(0, 0, 0, 0.2); } dl.reflist dd p::before { font-size: 85%; content: "\25B6\00A0\00A0"; display: inline-block; width: 12pt; } dl.reflist dd p { margin-top: 4px; margin-bottom: 4px; } .paramkey { text-align: right; } .paramtype { font-family: monospace; white-space: nowrap; color: #002546; } .paramname { color: black; font-family: monospace; white-space: nowrap; } .paramname em { color: #820a32; font-style: normal; } .paramname code { color: #404040; line-height: 14px; } .params, .retval, .exception, .tparams { margin-left: 0; padding-left: 0; margin-bottom: -0.25em; } .params dt, .tparams dt { margin-bottom: 0.5em; } .params .paramname, .tparams .paramname, .retval .paramname, .exception .paramname { color: #820a32; font-family: monospace; font-weight: bold; vertical-align: top; } .params .paramtype, .tparams .paramtype { font-family: monospace; font-style: italic; vertical-align: top; } .params .paramdir, .tparams .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } /* line over parameters docs */ .params, .tparams { border-collapse: collapse; } .params tr, .tparams tr { -moz-box-shadow: 0 -2px 0 -1px #606060; -webkit-box-shadow: 0 -2px 0 -1px #606060; -o-box-shadow: 0 -2px 0 -1px #606060; box-shadow: 0 -2px 0 -1px #606060; } .params .paramname, .tparams .paramname { border-top: 2px solid #5f082b; padding-right: 5pt; } .params td, .tparams td { padding-bottom: 1em; } table.mlabels { border-spacing: 0px; } td.mlabels-left { width: 100%; padding: 0px; } td.mlabels-right { vertical-align: bottom; padding: 0px; white-space: nowrap; } span.mlabels { margin-left: 8px; } span.mlabel { background-color: #444444; border: none; border-radius: 3px; text-shadow: none; color: white; margin-right: 4px; padding: 3px 5px; font-size: 8pt; white-space: nowrap; vertical-align: middle; } .memdoc .definition { position: relative; padding-top: 0.5em; /* move definition line to bottom of memdoc */ order: 3; } .memdoc .definition::before { content: ""; width: 33%; height: 1px; border-top: 1px solid black; position: absolute; top: 0; } table.directory { border-top: 1px solid #c5c5c5; border-bottom: 1px solid #c5c5c5; border-collapse: collapse; width: 100%; font: 400 14px Roboto,sans-serif; } table.directory tr { background-color: white !important; } table.directory tr.even { background-color: #f6f6f6 !important; } table.directory tr:hover { background-color: #e6e6e6 !important; } table.directory td.entry { padding: 1.5pt 3pt 1.5pt 3pt; white-space: normal; } div.directory { border: none; } div.directory table.directory tr { line-height: 17pt; } div.directory table.directory td { margin: 0; padding: 0.5pt 6pt 0.5pt 0; vertical-align: middle; } div.directory table.directory td.entry { white-space: nowrap; } div.directory table.directory td.desc { width: 100%; padding-left: 6pt; border-left: 1px solid rgba(0, 0, 0, 0.05); } .directory .levels { white-space: nowrap; width: 100%; text-align: right; font-size: 9pt; } .directory .levels span { cursor: pointer; padding-left: 2px; padding-right: 2px; color: #00549f; } .directory .levels span:hover { text-decoration: underline; } /* * The tree view on the left */ .arrow { color: black; cursor: pointer; font-size: 80%; display: inline-block; width: 16px; height: 22px; margin-left: 4px; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .arrow:hover { color: black; } #selected .arrow { color: white; } #selected .arrow:hover { color: #d2d2d2; } #nav-tree { background-image: none; background-color: white; } #nav-tree .item { margin: 0; } #nav-tree .item:hover { background-color: #d2d2d2; } #nav-tree .selected { background-image: none; background-color: #5f082b; color: white; text-shadow: none; } #nav-tree .selected:hover { background-image: none; background-color: #5f082b; color: white; text-shadow: none; } #nav-tree a { color: black; } .ui-resizable-e { background: #808080 url("splitbar_handle.svg") no-repeat center; border-right: solid 1px #c0c0c0; border-left: solid 1px black; } .ui-resizable-e:hover { background-color: #606060; } .icon { font-family: monospace; font-weight: bold; font-size: 12px; height: 15px; width: 15px; display: inline-block; background-color: #444444; color: white; text-align: center; border-radius: 3px; margin: 0; padding-top: 1px; text-indent: -1px; } .icona { width: 0; height: 0; display: none; visibility: hidden; } .iconfopen { width: 24px; height: 18px; margin-bottom: 4px; background-image: url("folderopen.svg"); background-position: 0; background-repeat: no-repeat; vertical-align: top; display: inline-block; } .iconfclosed { width: 24px; height: 18px; margin-bottom: 4px; background-image: url("folderclosed.svg"); background-position: 0; background-repeat: no-repeat; vertical-align: top; display: inline-block; } .icondoc { width: 24px; height: 18px; margin-bottom: 4px; background-image: url("doc.svg"); background-position: 0; background-repeat: no-repeat; vertical-align: top; display: inline-block; } div.dynheader { margin-top: 8px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } address { font-style: normal; color: #2A3D61; } table.doxtable caption { caption-side: top; } table.doxtable { border-collapse: collapse; margin-top: 4px; margin-bottom: 4px; } table.doxtable td, table.doxtable th { border: 1px solid #444444; padding: 3px 7px 2px; } table.doxtable th { background-color: #444444; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; } /* * The line at the bottom */ .navpath { /* intermediate navelems */ /* first navelem */ /* last navelem */ } .navpath ul { font-size: 11px; background-image: none; height: 30px; line-height: 30px; color: black; border: none; border-top: 1px solid #808080; overflow: hidden; margin: 0px; padding: 0px; } .navpath li:not(:first-child) { list-style-type: none; float: left; padding-left: 18px; padding-right: 10px; color: black; background-color: white; background-image: url("nav_edge_inter.svg"); background-repeat: no-repeat; background-position: left -1px; background-size: auto 100%; } .navpath li:first-child { list-style-type: none; float: left; padding-left: 15px; padding-right: 10px; color: black; background-color: white; background-image: none; } .navpath li:nth-last-child(2) { list-style-type: none; float: left; padding-left: 10px; padding-right: 15px; color: white; background-color: #5f082b; background-image: url("nav_edge_right.svg"); background-repeat: no-repeat; background-position: right -1px; background-size: auto 100%; } .navpath li:nth-last-child(2):not(:first-child) { list-style-type: none; float: left; padding-left: 15px; padding-right: 15px; color: white; background-color: #5f082b; background-image: url("nav_edge_left.svg"), url("nav_edge_right.svg"); background-repeat: no-repeat; background-position: -1px -1px, right -1px; background-size: auto 100%; } .navpath li.navelem a, .navpath .navpath li.navelem b { height: 32px; display: block; text-decoration: none; outline: none; color: inherit; font-family: Roboto,sans-serif; text-shadow: none; text-decoration: none; font-weight: normal; } .navpath li.navelem a:hover { color: inherit; text-decoration: underline; } .navpath li.footer { list-style-type: none; float: right; padding-left: 0; padding-right: 10px; background-color: #d5d5d5; background-image: none; color: black; font-size: 8pt; } .navpath li.footer:before { content: ""; width: 13px; height: 30px; display: inline-block; float: left; background-image: url("nav_edge_right.svg"); background-repeat: no-repeat; background-position: right 0; background-size: auto 100%; /* flip the element horizontally */ -moz-transform: scaleX(-1); -o-transform: scaleX(-1); -webkit-transform: scaleX(-1); transform: scaleX(-1); filter: FlipH; -ms-filter: "FlipH"; } div.summary { -webkit-order: 2; order: 2; float: right; font-size: 8pt; padding-right: 5px; width: 50%; text-align: right; margin-right: 0.5%; } div.summary a { white-space: nowrap; } table.classindex { margin: 10px; white-space: nowrap; margin-left: 1%; margin-right: 1%; width: 98%; border: none; border-top: 1px solid black; border-bottom: 1px solid black; border-spacing: 0.5em; padding: 0; } div.ingroups { font-size: 8pt; width: 50%; text-align: left; } div.ingroups a { white-space: nowrap; } div.header { display: -webkit-flex; display: flex; justify-content: space-between; background-image: none; background-color: #ffffff; color: black; margin: 5pt 5pt 0 5pt; padding: 0 1ex 0 1ex; align-items: center; justify-content: center; border-bottom: none; position: relative; } div.header::after { content: ""; height: 2px; width: 99%; position: absolute; bottom: -5px; left: 0.5%; background: #666; } div.headertitle { -webkit-order: 1; order: 1; margin-right: auto; text-align: center; } dl { padding: 0; } dl.section { margin-left: 0px; padding-left: 0px; } dl.section > dt { font-weight: bold; font-family: sans-serif; } dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug { margin-left: -7px; padding-left: 3px; } dl.note { padding-left: 7px; border: none; } dl.warning { background-color: #ffe6ea; border: 1px solid #ff0728; border-left: 4px solid #ff0728; padding-top: 4px; padding-bottom: 3px; } dl.attention { border-left: 4px solid #ff0728; } dl.pre, dl.post, dl.invariant { background-color: #f0ffe6; border: 1px solid #5eb82a; border-left: 4px solid #5eb82a; } dl.deprecated { background-color: #f6f6f6; border: 1px solid black; } dl.todo { border-left: 4px solid #e8d500; } dl.test { border-left: 4px solid #00549f; } dl.bug { background-color: #f6f6f6; border: 1px solid #cc071e; border-left: 4px solid #cc071e; } dl.section dd { margin-bottom: 6px; } .memdoc dl dt a.el { font-weight: bold; color: black; } #projectlogo { text-align: center; vertical-align: bottom; border-collapse: separate; } #projectlogo img { border: 0px none; } #projectalign { vertical-align: middle; } #projectname { font: 300% Tahoma, Arial,sans-serif; margin: 0px; padding: 2px 0px; } #projectbrief { font: 120% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #projectnumber { font: 50% Roboto,sans-serif; margin: 0px; padding: 0px; } #titlearea { padding: 0px; margin: 0px; width: 100%; border-bottom: none; } #titlearea:nth-last-child(2) { border-bottom: 2px solid #444444; } .image { text-align: center; } .dotgraph, .mscgraph, .diagraph { text-align: center; } .caption { font-weight: bold; } div.zoom { border: 1px solid #90A5CE; } dl.citelist { margin-bottom: 5ex; } dl.citelist dt { color: black; float: left; font-weight: bold; padding: 5px 0; margin: 2px 10pt 2px 0; } dl.citelist dd { margin: 2px 0; padding: 5px 0; } dl.citelist .startdd { margin-top: 0; } div.toc { background-color: transparent; border: 1px solid #414141; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; float: right; height: auto; margin: 0 8px 10px 10px; padding: 10px 15px 5px 25px; width: auto; } div.toc li { background: transparent; font: 10pt Roboto,DejaVu Sans,sans-serif; padding-left: 0; padding-top: 0.5ex; } div.toc li .level1 { margin-left: 10pt; } div.toc li .level2 { margin-left: 10pt; } div.toc li .level3 { margin-left: 10pt; } div.toc li .level4 { margin-left: 10pt; } div.toc h3 { font: bold 12px/1.2 Roboto,DejaVu Sans,sans-serif; color: black; border-bottom: none; margin: 0; letter-spacing: 1px; } div.toc ul { list-style: disc; border: none; padding: 0; } .inherit_header { font-weight: bold; color: gray; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .inherit_header td { padding: 6px 0px 2px 5px; } .inherit { display: none; } /* tooltip related style info */ .ttc { position: absolute; display: none; } #powerTip { cursor: default; white-space: nowrap; background-color: #ffffff; border: 1px solid #323232; border-radius: 0; -moz-box-shadow: none; -webkit-box-shadow: none; -o-box-shadow: none; box-shadow: none; display: none; font-size: smaller; max-width: 80%; opacity: 0.9; padding: 1ex 1em 1em 1em; position: absolute; z-index: 2147483647; } #powerTip div.ttdoc { color: grey; font-style: italic; } #powerTip div.ttname a { font-weight: bold; } #powerTip div.ttname { font-weight: bold; } #powerTip div.ttdeci { color: #006318; } #powerTip div { margin: 0px; padding: 0px; font: 12px/16px Roboto,sans-serif; } #powerTip:before, #powerTip:after { content: ""; position: absolute; margin: 0px; } @media print { #top { display: none; } #side-nav { display: none; } #nav-path { display: none; } body { overflow: visible; } h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } .summary { display: none; } .memitem { page-break-inside: avoid; } #doc-content { margin-left: 0 !important; height: auto !important; width: auto !important; overflow: inherit; display: inline; background-color: white; } } ================================================ FILE: src/libssh/doc/threading.dox ================================================ /** @page libssh_tutor_threads Chapter 8: Threads with libssh @section threads_with_libssh How to use libssh with threads libssh may be used in multithreaded applications, but under several conditions : - Your system must support libpthread or, in Windows environment, CriticalSection based mutex control. - Since version 0.8.0, threads initialization is called automatically in the library constructor if libssh is dynamically linked. This means it is no longer necessary to call ssh_init()/ssh_finalize(). - If libssh is statically linked, threading must be initialized by calling ssh_init() before using any of libssh provided functions. This initialization must be done outside of any threading context. Don't forget to call ssh_finalize() to avoid memory leak - At all times, you may use different sessions inside threads, make parallel connections, read/write on different sessions and so on. You *cannot* use a single session (or channels for a single session) in several threads at the same time. This will most likely lead to internal state corruption. This limitation is being worked out and will maybe disappear later. @subsection threads_init Initialization of threads Since version 0.8.0, it is no longer necessary to call ssh_init()/ssh_finalize() if libssh is dynamically linked. If libssh is statically linked, call ssh_init() before using any of libssh provided functions. @subsection threads_pthread Using libpthread with libssh Since version 0.8.0, libpthread is the default threads library used by libssh. To use libpthread, simply link it to you application. If you are using libssh statically linked, don't forget to call ssh_init() before using any of libssh provided functions (and ssh_finalize() in the end). @subsection threads_other Using another threading library Since version 0.8.0, libssh does not support custom threading libraries. The change makes sense since the newer versions for libcrypto (OpenSSL) and libgcrypt don't support custom threading libraries. The default used threading library is libpthread. Alternatively, in Windows environment, CriticalSection based mutex control can be used. If your system does not support libpthread nor CriticalSection based mutex control, unfortunately, you cannot use libssh in multithreaded scenarios. Good luck ! */ ================================================ FILE: src/libssh/examples/CMakeLists.txt ================================================ project(libssh-examples C CXX) set(examples_SRCS authentication.c knownhosts.c connect_ssh.c ) include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR}) if (ARGP_INCLUDE_DIR) include_directories(${ARGP_INCLUDE_DIR}) endif() if (UNIX AND NOT WIN32) add_executable(libssh_scp libssh_scp.c ${examples_SRCS}) target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(libssh_scp ssh::ssh) add_executable(scp_download scp_download.c ${examples_SRCS}) target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(scp_download ssh::ssh) add_executable(sshnetcat sshnetcat.c ${examples_SRCS}) target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(sshnetcat ssh::ssh) if (WITH_SFTP) add_executable(samplesftp samplesftp.c ${examples_SRCS}) target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesftp ssh::ssh) endif (WITH_SFTP) add_executable(ssh-client ssh_client.c ${examples_SRCS}) target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(ssh-client ssh::ssh) if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H)) if (HAVE_LIBUTIL) add_executable(ssh_server_fork ssh_server_fork.c) target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util) endif (HAVE_LIBUTIL) if (WITH_GSSAPI AND GSSAPI_FOUND) add_executable(samplesshd-cb samplesshd-cb.c) target_compile_options(samplesshd-cb PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesshd-cb ssh::ssh ${ARGP_LIBRARY}) add_executable(proxy proxy.c) target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARY}) add_executable(sshd_direct-tcpip sshd_direct-tcpip.c) target_compile_options(sshd_direct-tcpip PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARY}) endif (WITH_GSSAPI AND GSSAPI_FOUND) add_executable(samplesshd-kbdint samplesshd-kbdint.c) target_compile_options(samplesshd-kbdint PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARY}) endif() endif (UNIX AND NOT WIN32) add_executable(exec exec.c ${examples_SRCS}) target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(exec ssh::ssh) add_executable(senddata senddata.c ${examples_SRCS}) target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(senddata ssh::ssh) add_executable(keygen keygen.c) target_compile_options(keygen PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(keygen ssh::ssh) add_executable(libsshpp libsshpp.cpp) target_link_libraries(libsshpp ssh::ssh) add_executable(libsshpp_noexcept libsshpp_noexcept.cpp) target_link_libraries(libsshpp_noexcept ssh::ssh) ================================================ FILE: src/libssh/examples/authentication.c ================================================ /* * authentication.c * This file contains an example of how to do an authentication to a * SSH server using libssh */ /* Copyright 2003-2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include #include #include #include #include "examples_common.h" int authenticate_kbdint(ssh_session session, const char *password) { int err; err = ssh_userauth_kbdint(session, NULL, NULL); while (err == SSH_AUTH_INFO) { const char *instruction; const char *name; char buffer[128]; int i, n; name = ssh_userauth_kbdint_getname(session); instruction = ssh_userauth_kbdint_getinstruction(session); n = ssh_userauth_kbdint_getnprompts(session); if (name && strlen(name) > 0) { printf("%s\n", name); } if (instruction && strlen(instruction) > 0) { printf("%s\n", instruction); } for (i = 0; i < n; i++) { const char *answer; const char *prompt; char echo; prompt = ssh_userauth_kbdint_getprompt(session, i, &echo); if (prompt == NULL) { break; } if (echo) { char *p; printf("%s", prompt); if (fgets(buffer, sizeof(buffer), stdin) == NULL) { return SSH_AUTH_ERROR; } buffer[sizeof(buffer) - 1] = '\0'; if ((p = strchr(buffer, '\n'))) { *p = '\0'; } if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) { return SSH_AUTH_ERROR; } memset(buffer, 0, strlen(buffer)); } else { if (password && strstr(prompt, "Password:")) { answer = password; } else { buffer[0] = '\0'; if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) { return SSH_AUTH_ERROR; } answer = buffer; } err = ssh_userauth_kbdint_setanswer(session, i, answer); memset(buffer, 0, sizeof(buffer)); if (err < 0) { return SSH_AUTH_ERROR; } } } err=ssh_userauth_kbdint(session,NULL,NULL); } return err; } static int auth_keyfile(ssh_session session, char* keyfile) { ssh_key key = NULL; char pubkey[132] = {0}; // +".pub" int rc; snprintf(pubkey, sizeof(pubkey), "%s.pub", keyfile); rc = ssh_pki_import_pubkey_file( pubkey, &key); if (rc != SSH_OK) return SSH_AUTH_DENIED; rc = ssh_userauth_try_publickey(session, NULL, key); ssh_key_free(key); if (rc!=SSH_AUTH_SUCCESS) return SSH_AUTH_DENIED; rc = ssh_pki_import_privkey_file(keyfile, NULL, NULL, NULL, &key); if (rc != SSH_OK) return SSH_AUTH_DENIED; rc = ssh_userauth_publickey(session, NULL, key); ssh_key_free(key); return rc; } static void error(ssh_session session) { fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session)); } int authenticate_console(ssh_session session) { int rc; int method; char password[128] = {0}; char *banner; // Try to authenticate rc = ssh_userauth_none(session, NULL); if (rc == SSH_AUTH_ERROR) { error(session); return rc; } method = ssh_userauth_list(session, NULL); while (rc != SSH_AUTH_SUCCESS) { if (method & SSH_AUTH_METHOD_GSSAPI_MIC){ rc = ssh_userauth_gssapi(session); if(rc == SSH_AUTH_ERROR) { error(session); return rc; } else if (rc == SSH_AUTH_SUCCESS) { break; } } // Try to authenticate with public key first if (method & SSH_AUTH_METHOD_PUBLICKEY) { rc = ssh_userauth_publickey_auto(session, NULL, NULL); if (rc == SSH_AUTH_ERROR) { error(session); return rc; } else if (rc == SSH_AUTH_SUCCESS) { break; } } { char buffer[128] = {0}; char *p = NULL; printf("Automatic pubkey failed. " "Do you want to try a specific key? (y/n)\n"); if (fgets(buffer, sizeof(buffer), stdin) == NULL) { break; } if ((buffer[0]=='Y') || (buffer[0]=='y')) { printf("private key filename: "); if (fgets(buffer, sizeof(buffer), stdin) == NULL) { return SSH_AUTH_ERROR; } buffer[sizeof(buffer) - 1] = '\0'; if ((p = strchr(buffer, '\n'))) { *p = '\0'; } rc = auth_keyfile(session, buffer); if(rc == SSH_AUTH_SUCCESS) { break; } fprintf(stderr, "failed with key\n"); } } // Try to authenticate with keyboard interactive"; if (method & SSH_AUTH_METHOD_INTERACTIVE) { rc = authenticate_kbdint(session, NULL); if (rc == SSH_AUTH_ERROR) { error(session); return rc; } else if (rc == SSH_AUTH_SUCCESS) { break; } } if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) { return SSH_AUTH_ERROR; } // Try to authenticate with password if (method & SSH_AUTH_METHOD_PASSWORD) { rc = ssh_userauth_password(session, NULL, password); if (rc == SSH_AUTH_ERROR) { error(session); return rc; } else if (rc == SSH_AUTH_SUCCESS) { break; } } memset(password, 0, sizeof(password)); } banner = ssh_get_issue_banner(session); if (banner) { printf("%s\n",banner); SSH_STRING_FREE_CHAR(banner); } return rc; } ================================================ FILE: src/libssh/examples/connect_ssh.c ================================================ /* * connect_ssh.c * This file contains an example of how to connect to a * SSH server using libssh */ /* Copyright 2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include #include "examples_common.h" #include ssh_session connect_ssh(const char *host, const char *user,int verbosity){ ssh_session session; int auth=0; session=ssh_new(); if (session == NULL) { return NULL; } if(user != NULL){ if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { ssh_free(session); return NULL; } } if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) { ssh_free(session); return NULL; } ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); if(ssh_connect(session)){ fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); ssh_disconnect(session); ssh_free(session); return NULL; } if(verify_knownhost(session)<0){ ssh_disconnect(session); ssh_free(session); return NULL; } auth=authenticate_console(session); if(auth==SSH_AUTH_SUCCESS){ return session; } else if(auth==SSH_AUTH_DENIED){ fprintf(stderr,"Authentication failed\n"); } else { fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session)); } ssh_disconnect(session); ssh_free(session); return NULL; } ================================================ FILE: src/libssh/examples/examples_common.h ================================================ /* Copyright 2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #ifndef EXAMPLES_COMMON_H_ #define EXAMPLES_COMMON_H_ #include /** Zero a structure */ #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) int authenticate_console(ssh_session session); int authenticate_kbdint(ssh_session session, const char *password); int verify_knownhost(ssh_session session); ssh_session connect_ssh(const char *hostname, const char *user, int verbosity); #endif /* EXAMPLES_COMMON_H_ */ ================================================ FILE: src/libssh/examples/exec.c ================================================ /* simple exec example */ #include #include #include "examples_common.h" int main(void) { ssh_session session; ssh_channel channel; char buffer[256]; int rbytes, wbytes, total = 0; int rc; session = connect_ssh("localhost", NULL, 0); if (session == NULL) { ssh_finalize(); return 1; } channel = ssh_channel_new(session);; if (channel == NULL) { ssh_disconnect(session); ssh_free(session); ssh_finalize(); return 1; } rc = ssh_channel_open_session(channel); if (rc < 0) { goto failed; } rc = ssh_channel_request_exec(channel, "lsof"); if (rc < 0) { goto failed; } rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); if (rbytes <= 0) { goto failed; } do { wbytes = fwrite(buffer + total, 1, rbytes, stdout); if (wbytes <= 0) { goto failed; } total += wbytes; /* When it was not possible to write the whole buffer to stdout */ if (wbytes < rbytes) { rbytes -= wbytes; continue; } rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); total = 0; } while (rbytes > 0); if (rbytes < 0) { goto failed; } ssh_channel_send_eof(channel); ssh_channel_close(channel); ssh_channel_free(channel); ssh_disconnect(session); ssh_free(session); ssh_finalize(); return 0; failed: ssh_channel_close(channel); ssh_channel_free(channel); ssh_disconnect(session); ssh_free(session); ssh_finalize(); return 1; } ================================================ FILE: src/libssh/examples/keygen.c ================================================ /* keygen.c * Sample implementation of ssh-keygen using libssh */ /* Copyright 2019 Red Hat, Inc. Author: Jakub Jelen This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. */ #include #include int main(void) { ssh_key key = NULL; int rv; /* Generate a new ED25519 private key file */ rv = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &key); if (rv != SSH_OK) { fprintf(stderr, "Failed to generate private key"); return -1; } /* Write it to a file testkey in the current dirrectory */ rv = ssh_pki_export_privkey_file(key, NULL, NULL, NULL, "testkey"); if (rv != SSH_OK) { fprintf(stderr, "Failed to write private key file"); return -1; } return 0; } ================================================ FILE: src/libssh/examples/knownhosts.c ================================================ /* * knownhosts.c * This file contains an example of how verify the identity of a * SSH server using libssh */ /* Copyright 2003-2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #include #include #include "libssh/priv.h" #include #include "examples_common.h" #ifdef _WIN32 #define strncasecmp _strnicmp #endif int verify_knownhost(ssh_session session) { enum ssh_known_hosts_e state; char buf[10]; unsigned char *hash = NULL; size_t hlen; ssh_key srv_pubkey; int rc; rc = ssh_get_server_publickey(session, &srv_pubkey); if (rc < 0) { return -1; } rc = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen); ssh_key_free(srv_pubkey); if (rc < 0) { return -1; } state = ssh_session_is_known_server(session); switch(state) { case SSH_KNOWN_HOSTS_CHANGED: fprintf(stderr,"Host key for server changed : server's one is now :\n"); ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen); ssh_clean_pubkey_hash(&hash); fprintf(stderr,"For security reason, connection will be stopped\n"); return -1; case SSH_KNOWN_HOSTS_OTHER: fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n"); fprintf(stderr,"An attacker might change the default server key to confuse your client" "into thinking the key does not exist\n" "We advise you to rerun the client with -d or -r for more safety.\n"); return -1; case SSH_KNOWN_HOSTS_NOT_FOUND: fprintf(stderr,"Could not find known host file. If you accept the host key here,\n"); fprintf(stderr,"the file will be automatically created.\n"); /* fallback to SSH_SERVER_NOT_KNOWN behavior */ FALL_THROUGH; case SSH_SERVER_NOT_KNOWN: fprintf(stderr, "The server is unknown. Do you trust the host key (yes/no)?\n"); ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen); if (fgets(buf, sizeof(buf), stdin) == NULL) { ssh_clean_pubkey_hash(&hash); return -1; } if(strncasecmp(buf,"yes",3)!=0){ ssh_clean_pubkey_hash(&hash); return -1; } fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n"); if (fgets(buf, sizeof(buf), stdin) == NULL) { ssh_clean_pubkey_hash(&hash); return -1; } if(strncasecmp(buf,"yes",3)==0){ rc = ssh_session_update_known_hosts(session); if (rc != SSH_OK) { ssh_clean_pubkey_hash(&hash); fprintf(stderr, "error %s\n", strerror(errno)); return -1; } } break; case SSH_KNOWN_HOSTS_ERROR: ssh_clean_pubkey_hash(&hash); fprintf(stderr,"%s",ssh_get_error(session)); return -1; case SSH_KNOWN_HOSTS_OK: break; /* ok */ } ssh_clean_pubkey_hash(&hash); return 0; } ================================================ FILE: src/libssh/examples/libssh_scp.c ================================================ /* libssh_scp.c * Sample implementation of a SCP client */ /* Copyright 2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. */ #include #include #include #include #include #include #include "examples_common.h" static char **sources; static int nsources; static char *destination; static int verbosity = 0; struct location { int is_ssh; char *user; char *host; char *path; ssh_session session; ssh_scp scp; FILE *file; }; enum { READ, WRITE }; static void usage(const char *argv0) { fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n" " [[user@]host2:]destination\n" "sample scp client - libssh-%s\n", // "Options :\n", // " -r : use RSA to verify host public key\n", argv0, ssh_version(0)); exit(0); } static int opts(int argc, char **argv) { int i; while((i = getopt(argc, argv, "v")) != -1) { switch(i) { case 'v': verbosity++; break; default: fprintf(stderr, "unknown option %c\n", optopt); usage(argv[0]); return -1; } } nsources = argc - optind - 1; if (nsources < 1) { usage(argv[0]); return -1; } sources = malloc((nsources + 1) * sizeof(char *)); if (sources == NULL) { return -1; } for(i = 0; i < nsources; ++i) { sources[i] = argv[optind]; optind++; } sources[i] = NULL; destination = argv[optind]; return 0; } static void location_free(struct location *loc) { if (loc) { if (loc->path) { free(loc->path); } loc->path = NULL; if (loc->is_ssh) { if (loc->host) { free(loc->host); } loc->host = NULL; if (loc->user) { free(loc->user); } loc->user = NULL; if (loc->host) { free(loc->host); } loc->host = NULL; } free(loc); } } static struct location *parse_location(char *loc) { struct location *location; char *ptr; location = malloc(sizeof(struct location)); if (location == NULL) { return NULL; } memset(location, 0, sizeof(struct location)); location->host = location->user = NULL; ptr = strchr(loc, ':'); if (ptr != NULL) { location->is_ssh = 1; location->path = strdup(ptr+1); *ptr = '\0'; ptr = strchr(loc, '@'); if (ptr != NULL) { location->host = strdup(ptr+1); *ptr = '\0'; location->user = strdup(loc); } else { location->host = strdup(loc); } } else { location->is_ssh = 0; location->path = strdup(loc); } return location; } static void close_location(struct location *loc) { int rc; if (loc) { if (loc->is_ssh) { if (loc->scp) { rc = ssh_scp_close(loc->scp); if (rc == SSH_ERROR) { fprintf(stderr, "Error closing scp: %s\n", ssh_get_error(loc->session)); } ssh_scp_free(loc->scp); loc->scp = NULL; } if (loc->session) { ssh_disconnect(loc->session); ssh_free(loc->session); loc->session = NULL; } } else { if (loc->file) { fclose(loc->file); loc->file = NULL; } } } } static int open_location(struct location *loc, int flag) { if (loc->is_ssh && flag == WRITE) { loc->session = connect_ssh(loc->host, loc->user, verbosity); if (!loc->session) { fprintf(stderr, "Couldn't connect to %s\n", loc->host); return -1; } loc->scp = ssh_scp_new(loc->session, SSH_SCP_WRITE, loc->path); if (!loc->scp) { fprintf(stderr, "error : %s\n", ssh_get_error(loc->session)); ssh_disconnect(loc->session); ssh_free(loc->session); loc->session = NULL; return -1; } if (ssh_scp_init(loc->scp) == SSH_ERROR) { fprintf(stderr, "error : %s\n", ssh_get_error(loc->session)); ssh_scp_free(loc->scp); loc->scp = NULL; ssh_disconnect(loc->session); ssh_free(loc->session); loc->session = NULL; return -1; } return 0; } else if (loc->is_ssh && flag == READ) { loc->session = connect_ssh(loc->host, loc->user, verbosity); if (!loc->session) { fprintf(stderr, "Couldn't connect to %s\n", loc->host); return -1; } loc->scp = ssh_scp_new(loc->session, SSH_SCP_READ, loc->path); if (!loc->scp) { fprintf(stderr, "error : %s\n", ssh_get_error(loc->session)); ssh_disconnect(loc->session); ssh_free(loc->session); loc->session = NULL; return -1; } if (ssh_scp_init(loc->scp) == SSH_ERROR) { fprintf(stderr, "error : %s\n", ssh_get_error(loc->session)); ssh_scp_free(loc->scp); loc->scp = NULL; ssh_disconnect(loc->session); ssh_free(loc->session); loc->session = NULL; return -1; } return 0; } else { loc->file = fopen(loc->path, flag == READ ? "r":"w"); if (!loc->file) { if (errno == EISDIR) { if (chdir(loc->path)) { fprintf(stderr, "Error changing directory to %s: %s\n", loc->path, strerror(errno)); return -1; } return 0; } fprintf(stderr, "Error opening %s: %s\n", loc->path, strerror(errno)); return -1; } return 0; } return -1; } /** @brief copies files from source location to destination * @param src source location * @param dest destination location * @param recursive Copy also directories */ static int do_copy(struct location *src, struct location *dest, int recursive) { size_t size; socket_t fd; struct stat s; int w, r; char buffer[16384]; size_t total = 0; mode_t mode; char *filename = NULL; /* recursive mode doesn't work yet */ (void)recursive; /* Get the file name and size*/ if (!src->is_ssh) { fd = fileno(src->file); if (fd < 0) { fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno)); return -1; } r = fstat(fd, &s); if (r < 0) { return -1; } size = s.st_size; mode = s.st_mode & ~S_IFMT; filename = ssh_basename(src->path); } else { size = 0; do { r = ssh_scp_pull_request(src->scp); if (r == SSH_SCP_REQUEST_NEWDIR) { ssh_scp_deny_request(src->scp, "Not in recursive mode"); continue; } if (r == SSH_SCP_REQUEST_NEWFILE) { size = ssh_scp_request_get_size(src->scp); filename = strdup(ssh_scp_request_get_filename(src->scp)); mode = ssh_scp_request_get_permissions(src->scp); //ssh_scp_accept_request(src->scp); break; } if (r == SSH_ERROR) { fprintf(stderr, "Error: %s\n", ssh_get_error(src->session)); SSH_STRING_FREE_CHAR(filename); return -1; } } while(r != SSH_SCP_REQUEST_NEWFILE); } if (dest->is_ssh) { r = ssh_scp_push_file(dest->scp, src->path, size, mode); // snprintf(buffer, sizeof(buffer), "C0644 %d %s\n", size, src->path); if (r == SSH_ERROR) { fprintf(stderr, "error: %s\n", ssh_get_error(dest->session)); SSH_STRING_FREE_CHAR(filename); ssh_scp_free(dest->scp); dest->scp = NULL; return -1; } } else { if (!dest->file) { dest->file = fopen(filename, "w"); if (!dest->file) { fprintf(stderr, "Cannot open %s for writing: %s\n", filename, strerror(errno)); if (src->is_ssh) { ssh_scp_deny_request(src->scp, "Cannot open local file"); } SSH_STRING_FREE_CHAR(filename); return -1; } } if (src->is_ssh) { ssh_scp_accept_request(src->scp); } } do { if (src->is_ssh) { r = ssh_scp_read(src->scp, buffer, sizeof(buffer)); if (r == SSH_ERROR) { fprintf(stderr, "Error reading scp: %s\n", ssh_get_error(src->session)); SSH_STRING_FREE_CHAR(filename); return -1; } if (r == 0) { break; } } else { r = fread(buffer, 1, sizeof(buffer), src->file); if (r == 0) { break; } if (r < 0) { fprintf(stderr, "Error reading file: %s\n", strerror(errno)); SSH_STRING_FREE_CHAR(filename); return -1; } } if (dest->is_ssh) { w = ssh_scp_write(dest->scp, buffer, r); if (w == SSH_ERROR) { fprintf(stderr, "Error writing in scp: %s\n", ssh_get_error(dest->session)); ssh_scp_free(dest->scp); dest->scp = NULL; SSH_STRING_FREE_CHAR(filename); return -1; } } else { w = fwrite(buffer, r, 1, dest->file); if (w <= 0) { fprintf(stderr, "Error writing in local file: %s\n", strerror(errno)); SSH_STRING_FREE_CHAR(filename); return -1; } } total += r; } while(total < size); SSH_STRING_FREE_CHAR(filename); printf("wrote %zu bytes\n", total); return 0; } int main(int argc, char **argv) { struct location *dest, *src; int i; int r; if (opts(argc, argv) < 0) { r = EXIT_FAILURE; goto end; } dest = parse_location(destination); if (dest == NULL) { r = EXIT_FAILURE; goto end; } if (open_location(dest, WRITE) < 0) { location_free(dest); r = EXIT_FAILURE; goto end; } for (i = 0; i < nsources; ++i) { src = parse_location(sources[i]); if (src == NULL) { r = EXIT_FAILURE; goto close_dest; } if (open_location(src, READ) < 0) { location_free(src); r = EXIT_FAILURE; goto close_dest; } if (do_copy(src, dest, 0) < 0) { close_location(src); location_free(src); break; } close_location(src); location_free(src); } r = 0; close_dest: close_location(dest); location_free(dest); end: return r; } ================================================ FILE: src/libssh/examples/libsshpp.cpp ================================================ /* Copyright 2010 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. */ /* This file demonstrates the use of the C++ wrapper to libssh */ #include #include #include int main(int argc, const char **argv){ ssh::Session session; try { if(argc>1) session.setOption(SSH_OPTIONS_HOST,argv[1]); else session.setOption(SSH_OPTIONS_HOST,"localhost"); session.connect(); session.userauthPublickeyAuto(); session.disconnect(); } catch (ssh::SshException e){ std::cout << "Error during connection : "; std::cout << e.getError() << std::endl; } return 0; } ================================================ FILE: src/libssh/examples/libsshpp_noexcept.cpp ================================================ /* Copyright 2010 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. */ /* This file demonstrates the use of the C++ wrapper to libssh * specifically, without C++ exceptions */ #include #define SSH_NO_CPP_EXCEPTIONS #include int main(int argc, const char **argv){ ssh::Session session,s2; int err; if(argc>1) err=session.setOption(SSH_OPTIONS_HOST,argv[1]); else err=session.setOption(SSH_OPTIONS_HOST,"localhost"); if(err==SSH_ERROR) goto error; err=session.connect(); if(err==SSH_ERROR) goto error; err=session.userauthPublickeyAuto(); if(err==SSH_ERROR) goto error; return 0; error: std::cout << "Error during connection : "; std::cout << session.getError() << std::endl; return 1; } ================================================ FILE: src/libssh/examples/proxy.c ================================================ /* This is a sample implementation of a libssh based SSH proxy */ /* Copyright 2003-2013 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #include #ifdef HAVE_ARGP_H #include #endif #include #include #include #define USER "myuser" #define PASSWORD "mypassword" static int authenticated=0; static int tries = 0; static int error = 0; static ssh_channel chan=NULL; static char *username; static ssh_gssapi_creds client_creds = NULL; static int auth_password(ssh_session session, const char *user, const char *password, void *userdata){ (void)userdata; printf("Authenticating user %s pwd %s\n",user, password); if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){ authenticated = 1; printf("Authenticated\n"); return SSH_AUTH_SUCCESS; } if (tries >= 3){ printf("Too many authentication tries\n"); ssh_disconnect(session); error = 1; return SSH_AUTH_DENIED; } tries++; return SSH_AUTH_DENIED; } static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){ (void)userdata; client_creds = ssh_gssapi_get_creds(session); printf("Authenticating user %s with gssapi principal %s\n",user, principal); if (client_creds != NULL) printf("Received some gssapi credentials\n"); else printf("Not received any forwardable creds\n"); printf("authenticated\n"); authenticated = 1; username = strdup(principal); return SSH_AUTH_SUCCESS; } static int pty_request(ssh_session session, ssh_channel channel, const char *term, int x,int y, int px, int py, void *userdata){ (void) session; (void) channel; (void) term; (void) x; (void) y; (void) px; (void) py; (void) userdata; printf("Allocated terminal\n"); return 0; } static int shell_request(ssh_session session, ssh_channel channel, void *userdata){ (void)session; (void)channel; (void)userdata; printf("Allocated shell\n"); return 0; } struct ssh_channel_callbacks_struct channel_cb = { .channel_pty_request_function = pty_request, .channel_shell_request_function = shell_request }; static ssh_channel new_session_channel(ssh_session session, void *userdata){ (void) session; (void) userdata; if(chan != NULL) return NULL; printf("Allocated session channel\n"); chan = ssh_channel_new(session); ssh_callbacks_init(&channel_cb); ssh_set_channel_callbacks(chan, &channel_cb); return chan; } #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh proxy example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; switch (key) { case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_event mainloop; ssh_session client_session; struct ssh_server_callbacks_struct cb = { .userdata = NULL, .auth_password_function = auth_password, .auth_gssapi_mic_function = auth_gssapi_mic, .channel_open_request_session_function = new_session_channel }; char buf[2048]; char host[128]=""; char *ptr; int i,r, rc; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "sshd_rsa"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); return 1; } r=ssh_bind_accept(sshbind,session); if(r==SSH_ERROR){ printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); return 1; } ssh_callbacks_init(&cb); ssh_set_server_callbacks(session, &cb); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); mainloop = ssh_event_new(); ssh_event_add_session(mainloop, session); while (!(authenticated && chan != NULL)){ if(error) break; r = ssh_event_dopoll(mainloop, -1); if (r == SSH_ERROR){ printf("Error : %s\n",ssh_get_error(session)); ssh_disconnect(session); return 1; } } if(error){ printf("Error, exiting loop\n"); return 1; } else printf("Authenticated and got a channel\n"); if (!client_creds){ snprintf(buf,sizeof(buf), "Sorry, but you do not have forwardable tickets. Try again with -K\r\n"); ssh_channel_write(chan,buf,strlen(buf)); printf("%s",buf); ssh_disconnect(session); return 1; } snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username); ssh_channel_write(chan, buf, strlen(buf)); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { ssh_channel_write(chan, buf, i); if(strlen(host) + i < sizeof(host)){ strncat(host, buf, i); } if (strchr(host, '\x0d')) { *strchr(host, '\x0d')='\0'; ssh_channel_write(chan, "\n", 1); break; } } else { printf ("Error: %s\n", ssh_get_error(session) ); return 1; } } while (i>0); snprintf(buf,sizeof(buf),"Trying to connect to \"%s\"\r\n", host); ssh_channel_write(chan, buf, strlen(buf)); printf("%s",buf); client_session = ssh_new(); /* ssh servers expect username without realm */ ptr = strchr(username,'@'); if(ptr) *ptr= '\0'; ssh_options_set(client_session, SSH_OPTIONS_HOST, host); ssh_options_set(client_session, SSH_OPTIONS_USER, username); ssh_gssapi_set_creds(client_session, client_creds); rc = ssh_connect(client_session); if (rc != SSH_OK){ printf("Error connecting to %s: %s", host, ssh_get_error(client_session)); return 1; } rc = ssh_userauth_none(client_session, NULL); if(rc == SSH_AUTH_SUCCESS){ printf("Authenticated using method none\n"); } else { rc = ssh_userauth_gssapi(client_session); if(rc != SSH_AUTH_SUCCESS){ printf("GSSAPI Authentication failed: %s\n",ssh_get_error(client_session)); return 1; } } snprintf(buf,sizeof(buf), "Authentication success\r\n"); printf("%s",buf); ssh_channel_write(chan,buf,strlen(buf)); ssh_disconnect(client_session); ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/samplesftp.c ================================================ /* Copyright 2003-2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include "examples_common.h" #ifdef WITH_SFTP static int verbosity; static char *destination; #define DATALEN 65536 static void do_sftp(ssh_session session) { sftp_session sftp = sftp_new(session); sftp_dir dir; sftp_attributes file; sftp_statvfs_t sftpstatvfs; struct statvfs sysstatvfs; sftp_file fichier; sftp_file to; int len = 1; unsigned int i; char data[DATALEN] = {0}; char *lnk; unsigned int count; if (!sftp) { fprintf(stderr, "sftp error initialising channel: %s\n", ssh_get_error(session)); goto end; } if (sftp_init(sftp)) { fprintf(stderr, "error initialising sftp: %s\n", ssh_get_error(session)); goto end; } printf("Additional SFTP extensions provided by the server:\n"); count = sftp_extensions_get_count(sftp); for (i = 0; i < count; i++) { printf("\t%s, version: %s\n", sftp_extensions_get_name(sftp, i), sftp_extensions_get_data(sftp, i)); } /* test symlink and readlink */ if (sftp_symlink(sftp, "/tmp/this_is_the_link", "/tmp/sftp_symlink_test") < 0) { fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session)); goto end; } lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test"); if (lnk == NULL) { fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session)); goto end; } printf("readlink /tmp/sftp_symlink_test: %s\n", lnk); sftp_unlink(sftp, "/tmp/sftp_symlink_test"); if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) { sftpstatvfs = sftp_statvfs(sftp, "/tmp"); if (sftpstatvfs == NULL) { fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session)); goto end; } printf("sftp statvfs:\n" "\tfile system block size: %llu\n" "\tfundamental fs block size: %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n" "\tfree blocks in file system: %llu\n" "\tfree blocks for non-root: %llu\n" "\ttotal file inodes: %llu\n" "\tfree file inodes: %llu\n" "\tfree file inodes for to non-root: %llu\n" "\tfile system id: %llu\n" "\tbit mask of f_flag values: %llu\n" "\tmaximum filename length: %llu\n", (unsigned long long) sftpstatvfs->f_bsize, (unsigned long long) sftpstatvfs->f_frsize, (unsigned long long) sftpstatvfs->f_blocks, (unsigned long long) sftpstatvfs->f_bfree, (unsigned long long) sftpstatvfs->f_bavail, (unsigned long long) sftpstatvfs->f_files, (unsigned long long) sftpstatvfs->f_ffree, (unsigned long long) sftpstatvfs->f_favail, (unsigned long long) sftpstatvfs->f_fsid, (unsigned long long) sftpstatvfs->f_flag, (unsigned long long) sftpstatvfs->f_namemax); sftp_statvfs_free(sftpstatvfs); if (statvfs("/tmp", &sysstatvfs) < 0) { fprintf(stderr, "statvfs failed (%s)\n", strerror(errno)); goto end; } printf("sys statvfs:\n" "\tfile system block size: %llu\n" "\tfundamental fs block size: %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n" "\tfree blocks in file system: %llu\n" "\tfree blocks for non-root: %llu\n" "\ttotal file inodes: %llu\n" "\tfree file inodes: %llu\n" "\tfree file inodes for to non-root: %llu\n" "\tfile system id: %llu\n" "\tbit mask of f_flag values: %llu\n" "\tmaximum filename length: %llu\n", (unsigned long long) sysstatvfs.f_bsize, (unsigned long long) sysstatvfs.f_frsize, (unsigned long long) sysstatvfs.f_blocks, (unsigned long long) sysstatvfs.f_bfree, (unsigned long long) sysstatvfs.f_bavail, (unsigned long long) sysstatvfs.f_files, (unsigned long long) sysstatvfs.f_ffree, (unsigned long long) sysstatvfs.f_favail, (unsigned long long) sysstatvfs.f_fsid, (unsigned long long) sysstatvfs.f_flag, (unsigned long long) sysstatvfs.f_namemax); } /* the connection is made */ /* opening a directory */ dir = sftp_opendir(sftp, "./"); if (!dir) { fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session)); goto end; } /* reading the whole directory, file by file */ while ((file = sftp_readdir(sftp, dir))) { fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n", file->name, file->permissions, file->owner, file->uid, file->group, file->gid, (long long unsigned int) file->size); sftp_attributes_free(file); } /* when file = NULL, an error has occured OR the directory listing is end of * file */ if (!sftp_dir_eof(dir)) { fprintf(stderr, "Error: %s\n", ssh_get_error(session)); goto end; } if (sftp_closedir(dir)) { fprintf(stderr, "Error: %s\n", ssh_get_error(session)); goto end; } /* this will open a file and copy it into your /home directory */ /* the small buffer size was intended to stress the library. of course, you * can use a buffer till 20kbytes without problem */ fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0); if (!fichier) { fprintf(stderr, "Error opening /usr/bin/ssh: %s\n", ssh_get_error(session)); goto end; } /* open a file for writing... */ to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700); if (!to) { fprintf(stderr, "Error opening ssh-copy for writing: %s\n", ssh_get_error(session)); sftp_close(fichier); goto end; } while ((len = sftp_read(fichier, data, 4096)) > 0) { if (sftp_write(to, data, len) != len) { fprintf(stderr, "Error writing %d bytes: %s\n", len, ssh_get_error(session)); sftp_close(to); sftp_close(fichier); goto end; } } printf("finished\n"); if (len < 0) { fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session)); } sftp_close(fichier); sftp_close(to); printf("fichiers ferm\n"); to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644); for (i = 0; i < 1000; ++i) { len = sftp_write(to, data, DATALEN); printf("wrote %d bytes\n", len); if (len != DATALEN) { printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session)); } } sftp_close(to); end: /* close the sftp session */ sftp_free(sftp); printf("sftp session terminated\n"); } static void usage(const char *argv0) { fprintf(stderr, "Usage : %s [-v] remotehost\n" "sample sftp test client - libssh-%s\n" "Options :\n" " -v : increase log verbosity\n", argv0, ssh_version(0)); exit(0); } static int opts(int argc, char **argv) { int i; while ((i = getopt(argc, argv, "v")) != -1) { switch(i) { case 'v': verbosity++; break; default: fprintf(stderr, "unknown option %c\n", optopt); usage(argv[0]); return -1; } } destination = argv[optind]; if (destination == NULL) { usage(argv[0]); return -1; } return 0; } int main(int argc, char **argv) { ssh_session session; if (opts(argc, argv) < 0) { return EXIT_FAILURE; } session = connect_ssh(destination, NULL, verbosity); if (session == NULL) { return EXIT_FAILURE; } do_sftp(session); ssh_disconnect(session); ssh_free(session); return 0; } #endif ================================================ FILE: src/libssh/examples/samplesshd-cb.c ================================================ /* This is a sample implementation of a libssh based SSH server */ /* Copyright 2003-2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #include #ifdef HAVE_ARGP_H #include #endif #include #include #include #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif #define USER "myuser" #define PASSWORD "mypassword" static int authenticated=0; static int tries = 0; static int error = 0; static ssh_channel chan=NULL; static int auth_password(ssh_session session, const char *user, const char *password, void *userdata){ (void)userdata; printf("Authenticating user %s pwd %s\n",user, password); if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){ authenticated = 1; printf("Authenticated\n"); return SSH_AUTH_SUCCESS; } if (tries >= 3){ printf("Too many authentication tries\n"); ssh_disconnect(session); error = 1; return SSH_AUTH_DENIED; } tries++; return SSH_AUTH_DENIED; } static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){ ssh_gssapi_creds creds = ssh_gssapi_get_creds(session); (void)userdata; printf("Authenticating user %s with gssapi principal %s\n",user, principal); if (creds != NULL) printf("Received some gssapi credentials\n"); else printf("Not received any forwardable creds\n"); printf("authenticated\n"); authenticated = 1; return SSH_AUTH_SUCCESS; } static int pty_request(ssh_session session, ssh_channel channel, const char *term, int x,int y, int px, int py, void *userdata){ (void) session; (void) channel; (void) term; (void) x; (void) y; (void) px; (void) py; (void) userdata; printf("Allocated terminal\n"); return 0; } static int shell_request(ssh_session session, ssh_channel channel, void *userdata){ (void)session; (void)channel; (void)userdata; printf("Allocated shell\n"); return 0; } struct ssh_channel_callbacks_struct channel_cb = { .channel_pty_request_function = pty_request, .channel_shell_request_function = shell_request }; static ssh_channel new_session_channel(ssh_session session, void *userdata){ (void) session; (void) userdata; if(chan != NULL) return NULL; printf("Allocated session channel\n"); chan = ssh_channel_new(session); ssh_callbacks_init(&channel_cb); ssh_set_channel_callbacks(chan, &channel_cb); return chan; } #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh server example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; switch (key) { case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_event mainloop; struct ssh_server_callbacks_struct cb = { .userdata = NULL, .auth_password_function = auth_password, .auth_gssapi_mic_function = auth_gssapi_mic, .channel_open_request_session_function = new_session_channel }; char buf[2048]; int i; int r; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); return 1; } r=ssh_bind_accept(sshbind,session); if(r==SSH_ERROR){ printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); return 1; } ssh_callbacks_init(&cb); ssh_set_server_callbacks(session, &cb); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); mainloop = ssh_event_new(); ssh_event_add_session(mainloop, session); while (!(authenticated && chan != NULL)){ if(error) break; r = ssh_event_dopoll(mainloop, -1); if (r == SSH_ERROR){ printf("Error : %s\n",ssh_get_error(session)); ssh_disconnect(session); return 1; } } if(error){ printf("Error, exiting loop\n"); } else printf("Authenticated and got a channel\n"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } if (buf[0] == '\x0d') { if (write(1, "\n", 1) < 0) { printf("error writing to buffer\n"); return 1; } ssh_channel_write(chan, "\n", 1); } } } while (i>0); ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/samplesshd-kbdint.c ================================================ /* This is a sample implementation of a libssh based SSH server */ /* Copyright 2003-2011 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #ifdef HAVE_ARGP_H #include #endif #include #include #include #include #define SSHD_USER "libssh" #define SSHD_PASSWORD "libssh" #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif static int port = 22; static bool authenticated = false; #ifdef WITH_PCAP static const char *pcap_file = "debug.server.pcap"; static ssh_pcap_file pcap; static void set_pcap(ssh_session session){ if(!pcap_file) return; pcap=ssh_pcap_file_new(); if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){ printf("Error opening pcap file\n"); ssh_pcap_file_free(pcap); pcap=NULL; return; } ssh_set_pcap_file(session,pcap); } static void cleanup_pcap(void) { ssh_pcap_file_free(pcap); pcap=NULL; } #endif static int auth_password(const char *user, const char *password) { int cmp; cmp = strcmp(user, SSHD_USER); if (cmp != 0) { return 0; } cmp = strcmp(password, SSHD_PASSWORD); if (cmp != 0) { return 0; } authenticated = true; return 1; // authenticated } #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh server example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, 0, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; switch (key) { case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); port = atoi(arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ static const char *name; static const char *instruction; static const char *prompts[2]; static char echo[] = { 1, 0 }; static int kbdint_check_response(ssh_session session) { int count; count = ssh_userauth_kbdint_getnanswers(session); if(count != 2) { instruction = "Something weird happened :("; return 0; } if(strcasecmp("Arthur Dent", ssh_userauth_kbdint_getanswer(session, 0)) != 0) { instruction = "OK, this is not YOUR name, " "but it's a reference to the HGTG..."; prompts[0] = "The main character's full name: "; return 0; } if(strcmp("42", ssh_userauth_kbdint_getanswer(session, 1)) != 0) { instruction = "Make an effort !!! What is the Answer to the Ultimate " "Question of Life, the Universe, and Everything ?"; prompts[1] = "Answer to the Ultimate Question of Life, the Universe, " "and Everything: "; return 0; } authenticated = true; return 1; } static int authenticate(ssh_session session) { ssh_message message; name = "\n\nKeyboard-Interactive Fancy Authentication\n"; instruction = "Please enter your real name and your password"; prompts[0] = "Real name: "; prompts[1] = "Password: "; do { message=ssh_message_get(session); if(!message) break; switch(ssh_message_type(message)){ case SSH_REQUEST_AUTH: switch(ssh_message_subtype(message)){ case SSH_AUTH_METHOD_PASSWORD: printf("User %s wants to auth with pass %s\n", ssh_message_auth_user(message), ssh_message_auth_password(message)); if(auth_password(ssh_message_auth_user(message), ssh_message_auth_password(message))){ ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); // not authenticated, send default message ssh_message_reply_default(message); break; case SSH_AUTH_METHOD_INTERACTIVE: if(!ssh_message_auth_kbdint_is_response(message)) { printf("User %s wants to auth with kbdint\n", ssh_message_auth_user(message)); ssh_message_auth_interactive_request(message, name, instruction, 2, prompts, echo); } else { if(kbdint_check_response(session)) { ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } break; case SSH_AUTH_METHOD_NONE: default: printf("User %s wants to auth with unknown auth %d\n", ssh_message_auth_user(message), ssh_message_subtype(message)); ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); break; } break; default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } ssh_message_free(message); } while (1); return 0; } int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; char buf[2048]; int auth=0; int shell=0; int i; int r; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif #ifdef WITH_PCAP set_pcap(session); #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } printf("Started sample libssh sshd on port %d\n", port); printf("You can login as the user %s with the password %s\n", SSHD_USER, SSHD_PASSWORD); r = ssh_bind_accept(sshbind, session); if(r==SSH_ERROR){ printf("Error accepting a connection: %s\n", ssh_get_error(sshbind)); return 1; } if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } /* proceed to authentication */ auth = authenticate(session); if (!auth || !authenticated) { printf("Authentication error: %s\n", ssh_get_error(session)); ssh_disconnect(session); return 1; } /* wait for a channel session */ do { message = ssh_message_get(session); if(message){ if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN && ssh_message_subtype(message) == SSH_CHANNEL_SESSION) { chan = ssh_message_channel_request_open_reply_accept(message); ssh_message_free(message); break; } else { ssh_message_reply_default(message); ssh_message_free(message); } } else { break; } } while(!chan); if(!chan) { printf("Error: cleint did not ask for a channel session (%s)\n", ssh_get_error(session)); ssh_finalize(); return 1; } /* wait for a shell */ do { message = ssh_message_get(session); if(message != NULL) { if(ssh_message_type(message) == SSH_REQUEST_CHANNEL && ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) { shell = 1; ssh_message_channel_request_reply_success(message); ssh_message_free(message); break; } ssh_message_reply_default(message); ssh_message_free(message); } else { break; } } while(!shell); if(!shell) { printf("Error: No shell requested (%s)\n", ssh_get_error(session)); return 1; } printf("it works !\n"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { if(*buf == '' || *buf == '') break; if(i == 1 && *buf == '\r') ssh_channel_write(chan, "\r\n", 2); else ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } } } while (i>0); ssh_channel_close(chan); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/scp_download.c ================================================ /* scp_download.c * Sample implementation of a tiny SCP downloader client */ /* Copyright 2009 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. */ #include #include #include #include #include #include #include "examples_common.h" static int verbosity = 0; static const char *createcommand = "rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && " "cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d"; static char *host = NULL; static void usage(const char *argv0){ fprintf(stderr,"Usage : %s [options] host\n" "sample tiny scp downloader client - libssh-%s\n" "This program will create files in /tmp and try to fetch them\n", // "Options :\n", // " -r : use RSA to verify host public key\n", argv0, ssh_version(0)); exit(0); } static int opts(int argc, char **argv){ int i; while((i=getopt(argc,argv,"v"))!=-1){ switch(i){ case 'v': verbosity++; break; default: fprintf(stderr,"unknown option %c\n",optopt); usage(argv[0]); return -1; } } host = argv[optind]; if(host == NULL) usage(argv[0]); return 0; } static void create_files(ssh_session session){ ssh_channel channel=ssh_channel_new(session); char buffer[1]; int rc; if(channel == NULL){ fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session)); exit(EXIT_FAILURE); } if(ssh_channel_open_session(channel) != SSH_OK){ fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session)); ssh_channel_free(channel); exit(EXIT_FAILURE); } if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){ fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session)); ssh_channel_close(channel); ssh_channel_free(channel); exit(EXIT_FAILURE); } while(!ssh_channel_is_eof(channel)){ rc = ssh_channel_read(channel,buffer,1,1); if (rc != 1) { fprintf(stderr, "Error reading from channel\n"); ssh_channel_close(channel); ssh_channel_free(channel); return; } rc = write(1, buffer, 1); if (rc < 0) { fprintf(stderr, "Error writing to buffer\n"); ssh_channel_close(channel); ssh_channel_free(channel); return; } } ssh_channel_close(channel); ssh_channel_free(channel); } static int fetch_files(ssh_session session){ int size; char buffer[16384]; int mode; char *filename; int r; ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*"); if(ssh_scp_init(scp) != SSH_OK){ fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session)); ssh_scp_free(scp); return -1; } printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n"); do { r=ssh_scp_pull_request(scp); switch(r){ case SSH_SCP_REQUEST_NEWFILE: size=ssh_scp_request_get_size(scp); filename=strdup(ssh_scp_request_get_filename(scp)); mode=ssh_scp_request_get_permissions(scp); printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode); free(filename); ssh_scp_accept_request(scp); r=ssh_scp_read(scp,buffer,sizeof(buffer)); if(r==SSH_ERROR){ fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; } printf("done\n"); break; case SSH_ERROR: fprintf(stderr,"Error: %s\n",ssh_get_error(session)); ssh_scp_close(scp); ssh_scp_free(scp); return -1; case SSH_SCP_REQUEST_WARNING: fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp)); break; case SSH_SCP_REQUEST_NEWDIR: filename=strdup(ssh_scp_request_get_filename(scp)); mode=ssh_scp_request_get_permissions(scp); printf("downloading directory %s, perms 0%o\n",filename,mode); free(filename); ssh_scp_accept_request(scp); break; case SSH_SCP_REQUEST_ENDDIR: printf("End of directory\n"); break; case SSH_SCP_REQUEST_EOF: printf("End of requests\n"); goto end; } } while (1); end: ssh_scp_close(scp); ssh_scp_free(scp); return 0; } int main(int argc, char **argv){ ssh_session session; if(opts(argc,argv)<0) return EXIT_FAILURE; session=connect_ssh(host,NULL,verbosity); if(session == NULL) return EXIT_FAILURE; create_files(session); fetch_files(session); ssh_disconnect(session); ssh_free(session); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/senddata.c ================================================ #include #include #include "examples_common.h" #define LIMIT 0x100000000UL int main(void) { ssh_session session; ssh_channel channel; char buffer[1024*1024]; int rc; uint64_t total=0; uint64_t lastshown=4096; session = connect_ssh("localhost", NULL, 0); if (session == NULL) { return 1; } channel = ssh_channel_new(session);; if (channel == NULL) { ssh_disconnect(session); return 1; } rc = ssh_channel_open_session(channel); if (rc < 0) { ssh_channel_close(channel); ssh_disconnect(session); return 1; } rc = ssh_channel_request_exec(channel, "cat > /dev/null"); if (rc < 0) { ssh_channel_close(channel); ssh_disconnect(session); return 1; } while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) { total += rc; if(total/2 >= lastshown){ printf("written %llx\n", (long long unsigned int) total); lastshown=total; } if(total > LIMIT) break; } if (rc < 0) { printf("error : %s\n",ssh_get_error(session)); ssh_channel_close(channel); ssh_disconnect(session); return 1; } ssh_channel_send_eof(channel); ssh_channel_close(channel); ssh_disconnect(session); return 0; } ================================================ FILE: src/libssh/examples/ssh_client.c ================================================ /* ssh_client.c */ /* * Copyright 2003-2015 Aris Adamantiadis * * This file is part of the SSH Library * * You are free to copy this file, modify it in any way, consider it being public * domain. This does not apply to the rest of the library though, but it is * allowed to cut-and-paste working code from this file to any license of * program. * The goal is to show the API in action. It's not a reference on how terminal * clients must be made or how a client should react. */ #include "config.h" #include #include #include #include #include #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_PTY_H #include #endif #include #include #include #include #include #include #include #include "examples_common.h" #define MAXCMD 10 static char *host; static char *user; static char *cmds[MAXCMD]; static struct termios terminal; static char *pcap_file = NULL; static char *proxycommand; static int auth_callback(const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata) { (void) verify; (void) userdata; return ssh_getpass(prompt, buf, len, echo, verify); } struct ssh_callbacks_struct cb = { .auth_function = auth_callback, .userdata = NULL, }; static void add_cmd(char *cmd) { int n; for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++); if (n == MAXCMD) { return; } cmds[n] = strdup(cmd); } static void usage(void) { fprintf(stderr, "Usage : ssh [options] [login@]hostname\n" "sample client - libssh-%s\n" "Options :\n" " -l user : log in as user\n" " -p port : connect to port\n" " -d : use DSS to verify host public key\n" " -r : use RSA to verify host public key\n" #ifdef WITH_PCAP " -P file : create a pcap debugging file\n" #endif #ifndef _WIN32 " -T proxycommand : command to execute as a socket proxy\n" #endif "\n", ssh_version(0)); exit(0); } static int opts(int argc, char **argv) { int i; while((i = getopt(argc,argv,"T:P:")) != -1) { switch(i){ case 'P': pcap_file = optarg; break; #ifndef _WIN32 case 'T': proxycommand = optarg; break; #endif default: fprintf(stderr, "Unknown option %c\n", optopt); usage(); } } if (optind < argc) { host = argv[optind++]; } while(optind < argc) { add_cmd(argv[optind++]); } if (host == NULL) { usage(); } return 0; } #ifndef HAVE_CFMAKERAW static void cfmakeraw(struct termios *termios_p) { termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); termios_p->c_cflag &= ~(CSIZE|PARENB); termios_p->c_cflag |= CS8; } #endif static void do_cleanup(int i) { /* unused variable */ (void) i; tcsetattr(0, TCSANOW, &terminal); } static void do_exit(int i) { /* unused variable */ (void) i; do_cleanup(0); exit(0); } static ssh_channel chan; static int signal_delayed = 0; static void sigwindowchanged(int i) { (void) i; signal_delayed = 1; } static void setsignal(void) { signal(SIGWINCH, sigwindowchanged); signal_delayed = 0; } static void sizechanged(void) { struct winsize win = { .ws_row = 0, }; ioctl(1, TIOCGWINSZ, &win); ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row); setsignal(); } static void select_loop(ssh_session session,ssh_channel channel) { ssh_connector connector_in, connector_out, connector_err; int rc; ssh_event event = ssh_event_new(); /* stdin */ connector_in = ssh_connector_new(session); ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT); ssh_connector_set_in_fd(connector_in, 0); ssh_event_add_connector(event, connector_in); /* stdout */ connector_out = ssh_connector_new(session); ssh_connector_set_out_fd(connector_out, 1); ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT); ssh_event_add_connector(event, connector_out); /* stderr */ connector_err = ssh_connector_new(session); ssh_connector_set_out_fd(connector_err, 2); ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR); ssh_event_add_connector(event, connector_err); while (ssh_channel_is_open(channel)) { if (signal_delayed) { sizechanged(); } rc = ssh_event_dopoll(event, 60000); if (rc == SSH_ERROR) { fprintf(stderr, "Error in ssh_event_dopoll()\n"); break; } } ssh_event_remove_connector(event, connector_in); ssh_event_remove_connector(event, connector_out); ssh_event_remove_connector(event, connector_err); ssh_connector_free(connector_in); ssh_connector_free(connector_out); ssh_connector_free(connector_err); ssh_event_free(event); } static void shell(ssh_session session) { ssh_channel channel; struct termios terminal_local; int interactive=isatty(0); channel = ssh_channel_new(session); if (channel == NULL) { return; } if (interactive) { tcgetattr(0, &terminal_local); memcpy(&terminal, &terminal_local, sizeof(struct termios)); } if (ssh_channel_open_session(channel)) { printf("Error opening channel : %s\n", ssh_get_error(session)); ssh_channel_free(channel); return; } chan = channel; if (interactive) { ssh_channel_request_pty(channel); sizechanged(); } if (ssh_channel_request_shell(channel)) { printf("Requesting shell : %s\n", ssh_get_error(session)); ssh_channel_free(channel); return; } if (interactive) { cfmakeraw(&terminal_local); tcsetattr(0, TCSANOW, &terminal_local); setsignal(); } signal(SIGTERM, do_cleanup); select_loop(session, channel); if (interactive) { do_cleanup(0); } ssh_channel_free(channel); } static void batch_shell(ssh_session session) { ssh_channel channel; char buffer[1024]; size_t i; int s = 0; for (i = 0; i < MAXCMD && cmds[i]; ++i) { s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]); free(cmds[i]); cmds[i] = NULL; } channel = ssh_channel_new(session); if (channel == NULL) { return; } ssh_channel_open_session(channel); if (ssh_channel_request_exec(channel, buffer)) { printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session)); ssh_channel_free(channel); return; } select_loop(session, channel); ssh_channel_free(channel); } static int client(ssh_session session) { int auth = 0; char *banner; int state; if (user) { if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { return -1; } } if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) { return -1; } if (proxycommand != NULL) { if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) { return -1; } } ssh_options_parse_config(session, NULL); if (ssh_connect(session)) { fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session)); return -1; } state = verify_knownhost(session); if (state != 0) { return -1; } ssh_userauth_none(session, NULL); banner = ssh_get_issue_banner(session); if (banner) { printf("%s\n", banner); free(banner); } auth = authenticate_console(session); if (auth != SSH_AUTH_SUCCESS) { return -1; } if (cmds[0] == NULL) { shell(session); } else { batch_shell(session); } return 0; } static ssh_pcap_file pcap; static void set_pcap(ssh_session session) { if (pcap_file == NULL) { return; } pcap = ssh_pcap_file_new(); if (pcap == NULL) { return; } if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) { printf("Error opening pcap file\n"); ssh_pcap_file_free(pcap); pcap = NULL; return; } ssh_set_pcap_file(session, pcap); } static void cleanup_pcap(void) { if (pcap != NULL) { ssh_pcap_file_free(pcap); } pcap = NULL; } int main(int argc, char **argv) { ssh_session session; session = ssh_new(); ssh_callbacks_init(&cb); ssh_set_callbacks(session,&cb); if (ssh_options_getopt(session, &argc, argv)) { fprintf(stderr, "Error parsing command line: %s\n", ssh_get_error(session)); usage(); } opts(argc, argv); signal(SIGTERM, do_exit); set_pcap(session); client(session); ssh_disconnect(session); ssh_free(session); cleanup_pcap(); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/ssh_server_fork.c ================================================ /* This is a sample implementation of a libssh based SSH server */ /* Copyright 2014 Audrius Butkevicius This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. */ #include "config.h" #include #include #include #ifdef HAVE_ARGP_H #include #endif #include #ifdef HAVE_LIBUTIL_H #include #endif #ifdef HAVE_PTY_H #include #endif #include #include #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTIL_H #include #endif #include #include #include #include #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif #define USER "myuser" #define PASS "mypassword" #define BUF_SIZE 1048576 #define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR) #define SFTP_SERVER_PATH "/usr/lib/sftp-server" static void set_default_keys(ssh_bind sshbind, int rsa_already_set, int dsa_already_set, int ecdsa_already_set) { if (!rsa_already_set) { ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); } if (!dsa_already_set) { ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); } if (!ecdsa_already_set) { ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, KEYS_FOLDER "ssh_host_ecdsa_key"); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, KEYS_FOLDER "ssh_host_ed25519_key"); } #define DEF_STR_SIZE 1024 char authorizedkeys[DEF_STR_SIZE] = {0}; #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh server example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set a host key. Can be used multiple times. " "Implies no default keys.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "ecdsakey", .key = 'e', .arg = "FILE", .flags = 0, .doc = "Set the ecdsa key.", .group = 0 }, { .name = "authorizedkeys", .key = 'a', .arg = "FILE", .flags = 0, .doc = "Set the authorized keys file.", .group = 0 }, { .name = "no-default-keys", .key = 'n', .arg = NULL, .flags = 0, .doc = "Do not set default key locations.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; static int no_default_keys = 0; static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0; switch (key) { case 'n': no_default_keys = 1; break; case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); dsa_already_set = 1; break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); /* We can't track the types of keys being added with this option, so let's ensure we keep the keys we're adding by just not setting the default keys */ no_default_keys = 1; break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); rsa_already_set = 1; break; case 'e': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg); ecdsa_already_set = 1; break; case 'a': strncpy(authorizedkeys, arg, DEF_STR_SIZE-1); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } if (!no_default_keys) { set_default_keys(sshbind, rsa_already_set, dsa_already_set, ecdsa_already_set); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ /* A userdata struct for channel. */ struct channel_data_struct { /* pid of the child process the channel will spawn. */ pid_t pid; /* For PTY allocation */ socket_t pty_master; socket_t pty_slave; /* For communication with the child process. */ socket_t child_stdin; socket_t child_stdout; /* Only used for subsystem and exec requests. */ socket_t child_stderr; /* Event which is used to poll the above descriptors. */ ssh_event event; /* Terminal size struct. */ struct winsize *winsize; }; /* A userdata struct for session. */ struct session_data_struct { /* Pointer to the channel the session will allocate. */ ssh_channel channel; int auth_attempts; int authenticated; }; static int data_function(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata) { struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; (void) session; (void) channel; (void) is_stderr; if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) { return 0; } return write(cdata->child_stdin, (char *) data, len); } static int pty_request(ssh_session session, ssh_channel channel, const char *term, int cols, int rows, int py, int px, void *userdata) { struct channel_data_struct *cdata = (struct channel_data_struct *)userdata; (void) session; (void) channel; (void) term; cdata->winsize->ws_row = rows; cdata->winsize->ws_col = cols; cdata->winsize->ws_xpixel = px; cdata->winsize->ws_ypixel = py; if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL, cdata->winsize) != 0) { fprintf(stderr, "Failed to open pty\n"); return SSH_ERROR; } return SSH_OK; } static int pty_resize(ssh_session session, ssh_channel channel, int cols, int rows, int py, int px, void *userdata) { struct channel_data_struct *cdata = (struct channel_data_struct *)userdata; (void) session; (void) channel; cdata->winsize->ws_row = rows; cdata->winsize->ws_col = cols; cdata->winsize->ws_xpixel = px; cdata->winsize->ws_ypixel = py; if (cdata->pty_master != -1) { return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize); } return SSH_ERROR; } static int exec_pty(const char *mode, const char *command, struct channel_data_struct *cdata) { switch(cdata->pid = fork()) { case -1: close(cdata->pty_master); close(cdata->pty_slave); fprintf(stderr, "Failed to fork\n"); return SSH_ERROR; case 0: close(cdata->pty_master); if (login_tty(cdata->pty_slave) != 0) { exit(1); } execl("/bin/sh", "sh", mode, command, NULL); exit(0); default: close(cdata->pty_slave); /* pty fd is bi-directional */ cdata->child_stdout = cdata->child_stdin = cdata->pty_master; } return SSH_OK; } static int exec_nopty(const char *command, struct channel_data_struct *cdata) { int in[2], out[2], err[2]; /* Do the plumbing to be able to talk with the child process. */ if (pipe(in) != 0) { goto stdin_failed; } if (pipe(out) != 0) { goto stdout_failed; } if (pipe(err) != 0) { goto stderr_failed; } switch(cdata->pid = fork()) { case -1: goto fork_failed; case 0: /* Finish the plumbing in the child process. */ close(in[1]); close(out[0]); close(err[0]); dup2(in[0], STDIN_FILENO); dup2(out[1], STDOUT_FILENO); dup2(err[1], STDERR_FILENO); close(in[0]); close(out[1]); close(err[1]); /* exec the requested command. */ execl("/bin/sh", "sh", "-c", command, NULL); exit(0); } close(in[0]); close(out[1]); close(err[1]); cdata->child_stdin = in[1]; cdata->child_stdout = out[0]; cdata->child_stderr = err[0]; return SSH_OK; fork_failed: close(err[0]); close(err[1]); stderr_failed: close(out[0]); close(out[1]); stdout_failed: close(in[0]); close(in[1]); stdin_failed: return SSH_ERROR; } static int exec_request(ssh_session session, ssh_channel channel, const char *command, void *userdata) { struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; (void) session; (void) channel; if(cdata->pid > 0) { return SSH_ERROR; } if (cdata->pty_master != -1 && cdata->pty_slave != -1) { return exec_pty("-c", command, cdata); } return exec_nopty(command, cdata); } static int shell_request(ssh_session session, ssh_channel channel, void *userdata) { struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; (void) session; (void) channel; if(cdata->pid > 0) { return SSH_ERROR; } if (cdata->pty_master != -1 && cdata->pty_slave != -1) { return exec_pty("-l", NULL, cdata); } /* Client requested a shell without a pty, let's pretend we allow that */ return SSH_OK; } static int subsystem_request(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata) { /* subsystem requests behave simillarly to exec requests. */ if (strcmp(subsystem, "sftp") == 0) { return exec_request(session, channel, SFTP_SERVER_PATH, userdata); } return SSH_ERROR; } static int auth_password(ssh_session session, const char *user, const char *pass, void *userdata) { struct session_data_struct *sdata = (struct session_data_struct *) userdata; (void) session; if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) { sdata->authenticated = 1; return SSH_AUTH_SUCCESS; } sdata->auth_attempts++; return SSH_AUTH_DENIED; } static int auth_publickey(ssh_session session, const char *user, struct ssh_key_struct *pubkey, char signature_state, void *userdata) { struct session_data_struct *sdata = (struct session_data_struct *) userdata; (void) user; (void) session; if (signature_state == SSH_PUBLICKEY_STATE_NONE) { return SSH_AUTH_SUCCESS; } if (signature_state != SSH_PUBLICKEY_STATE_VALID) { return SSH_AUTH_DENIED; } // valid so far. Now look through authorized keys for a match if (authorizedkeys[0]) { ssh_key key = NULL; int result; struct stat buf; if (stat(authorizedkeys, &buf) == 0) { result = ssh_pki_import_pubkey_file( authorizedkeys, &key ); if ((result != SSH_OK) || (key==NULL)) { fprintf(stderr, "Unable to import public key file %s\n", authorizedkeys); } else { result = ssh_key_cmp( key, pubkey, SSH_KEY_CMP_PUBLIC ); ssh_key_free(key); if (result == 0) { sdata->authenticated = 1; return SSH_AUTH_SUCCESS; } } } } // no matches sdata->authenticated = 0; return SSH_AUTH_DENIED; } static ssh_channel channel_open(ssh_session session, void *userdata) { struct session_data_struct *sdata = (struct session_data_struct *) userdata; sdata->channel = ssh_channel_new(session); return sdata->channel; } static int process_stdout(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write(channel, buf, n); } } return n; } static int process_stderr(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write_stderr(channel, buf, n); } } return n; } static void handle_session(ssh_event event, ssh_session session) { int n; int rc = 0; /* Structure for storing the pty size. */ struct winsize wsize = { .ws_row = 0, .ws_col = 0, .ws_xpixel = 0, .ws_ypixel = 0 }; /* Our struct holding information about the channel. */ struct channel_data_struct cdata = { .pid = 0, .pty_master = -1, .pty_slave = -1, .child_stdin = -1, .child_stdout = -1, .child_stderr = -1, .event = NULL, .winsize = &wsize }; /* Our struct holding information about the session. */ struct session_data_struct sdata = { .channel = NULL, .auth_attempts = 0, .authenticated = 0 }; struct ssh_channel_callbacks_struct channel_cb = { .userdata = &cdata, .channel_pty_request_function = pty_request, .channel_pty_window_change_function = pty_resize, .channel_shell_request_function = shell_request, .channel_exec_request_function = exec_request, .channel_data_function = data_function, .channel_subsystem_request_function = subsystem_request }; struct ssh_server_callbacks_struct server_cb = { .userdata = &sdata, .auth_password_function = auth_password, .channel_open_request_session_function = channel_open, }; if (authorizedkeys[0]) { server_cb.auth_pubkey_function = auth_publickey; ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY); } else ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD); ssh_callbacks_init(&server_cb); ssh_callbacks_init(&channel_cb); ssh_set_server_callbacks(session, &server_cb); if (ssh_handle_key_exchange(session) != SSH_OK) { fprintf(stderr, "%s\n", ssh_get_error(session)); return; } ssh_event_add_session(event, session); n = 0; while (sdata.authenticated == 0 || sdata.channel == NULL) { /* If the user has used up all attempts, or if he hasn't been able to * authenticate in 10 seconds (n * 100ms), disconnect. */ if (sdata.auth_attempts >= 3 || n >= 100) { return; } if (ssh_event_dopoll(event, 100) == SSH_ERROR) { fprintf(stderr, "%s\n", ssh_get_error(session)); return; } n++; } ssh_set_channel_callbacks(sdata.channel, &channel_cb); do { /* Poll the main event which takes care of the session, the channel and * even our child process's stdout/stderr (once it's started). */ if (ssh_event_dopoll(event, -1) == SSH_ERROR) { ssh_channel_close(sdata.channel); } /* If child process's stdout/stderr has been registered with the event, * or the child process hasn't started yet, continue. */ if (cdata.event != NULL || cdata.pid == 0) { continue; } /* Executed only once, once the child process starts. */ cdata.event = event; /* If stdout valid, add stdout to be monitored by the poll event. */ if (cdata.child_stdout != -1) { if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stdout to poll context\n"); ssh_channel_close(sdata.channel); } } /* If stderr valid, add stderr to be monitored by the poll event. */ if (cdata.child_stderr != -1){ if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stderr to poll context\n"); ssh_channel_close(sdata.channel); } } } while(ssh_channel_is_open(sdata.channel) && (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0)); close(cdata.pty_master); close(cdata.child_stdin); close(cdata.child_stdout); close(cdata.child_stderr); /* Remove the descriptors from the polling context, since they are now * closed, they will always trigger during the poll calls. */ ssh_event_remove_fd(event, cdata.child_stdout); ssh_event_remove_fd(event, cdata.child_stderr); /* If the child process exited. */ if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) { rc = WEXITSTATUS(rc); ssh_channel_request_send_exit_status(sdata.channel, rc); /* If client terminated the channel or the process did not exit nicely, * but only if something has been forked. */ } else if (cdata.pid > 0) { kill(cdata.pid, SIGKILL); } ssh_channel_send_eof(sdata.channel); ssh_channel_close(sdata.channel); /* Wait up to 5 seconds for the client to terminate the session. */ for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) { ssh_event_dopoll(event, 100); } } /* SIGCHLD handler for cleaning up dead children. */ static void sigchld_handler(int signo) { (void) signo; while (waitpid(-1, NULL, WNOHANG) > 0); } int main(int argc, char **argv) { ssh_bind sshbind; ssh_session session; ssh_event event; struct sigaction sa; int rc; /* Set up SIGCHLD handler. */ sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa, NULL) != 0) { fprintf(stderr, "Failed to register SIGCHLD handler\n"); return 1; } rc = ssh_init(); if (rc < 0) { fprintf(stderr, "ssh_init failed\n"); return 1; } sshbind = ssh_bind_new(); if (sshbind == NULL) { fprintf(stderr, "ssh_bind_new failed\n"); return 1; } #ifdef HAVE_ARGP_H argp_parse(&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; set_default_keys(sshbind, 0, 0, 0); #endif /* HAVE_ARGP_H */ if(ssh_bind_listen(sshbind) < 0) { fprintf(stderr, "%s\n", ssh_get_error(sshbind)); return 1; } while (1) { session = ssh_new(); if (session == NULL) { fprintf(stderr, "Failed to allocate session\n"); continue; } /* Blocks until there is a new incoming connection. */ if(ssh_bind_accept(sshbind, session) != SSH_ERROR) { switch(fork()) { case 0: /* Remove the SIGCHLD handler inherited from parent. */ sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); /* Remove socket binding, which allows us to restart the * parent process, without terminating existing sessions. */ ssh_bind_free(sshbind); event = ssh_event_new(); if (event != NULL) { /* Blocks until the SSH session ends by either * child process exiting, or client disconnecting. */ handle_session(event, session); ssh_event_free(event); } else { fprintf(stderr, "Could not create polling context\n"); } ssh_disconnect(session); ssh_free(session); exit(0); case -1: fprintf(stderr, "Failed to fork\n"); } } else { fprintf(stderr, "%s\n", ssh_get_error(sshbind)); } /* Since the session has been passed to a child fork, do some cleaning * up at the parent process. */ ssh_disconnect(session); ssh_free(session); } ssh_bind_free(sshbind); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/examples/sshd_direct-tcpip.c ================================================ /* This is a sample implementation of a libssh based SSH server */ /* Copyright 2003-2009 Aris Adamantiadis Copyright 2018 T. Wimmer This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ /* Example: ./sshd_direct-tcpip -v -p 2022 -d serverkey.dsa -r serverkey.rsa 127.0.0.1 */ #include "config.h" #include #include #include #ifdef HAVE_ARGP_H #include #endif #include #include #include #include #include #include #include #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) #ifndef __unused__ # ifdef HAVE_UNUSED_ATTRIBUTE # define __unused__ __attribute__((unused)) # else /* HAVE_UNUSED_ATTRIBUTE */ # define __unused__ # endif /* HAVE_UNUSED_ATTRIBUTE */ #endif /* __unused__ */ #ifndef UNUSED_PARAM #define UNUSED_PARAM(param) param __unused__ #endif /* UNUSED_PARAM */ #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif #define USER "user" #define PASSWORD "pwd" struct event_fd_data_struct { int *p_fd; ssh_channel channel; struct ssh_channel_callbacks_struct *cb_chan; int stacked; }; struct cleanup_node_struct { struct event_fd_data_struct *data; struct cleanup_node_struct *next; }; static bool authenticated = false; static int tries = 0; static bool error_set = false; static int sockets_cnt = 0; static ssh_event mainloop = NULL; static struct cleanup_node_struct *cleanup_stack = NULL; static void _close_socket(struct event_fd_data_struct event_fd_data); static void cleanup_push(struct cleanup_node_struct** head_ref, struct event_fd_data_struct *new_data) { // Allocate memory for node struct cleanup_node_struct *new_node = malloc(sizeof *new_node); new_node->next = (*head_ref); // Copy new_data new_node->data = new_data; // Change head pointer as new node is added at the beginning (*head_ref) = new_node; } static void do_cleanup(struct cleanup_node_struct **head_ref) { struct cleanup_node_struct *current = (*head_ref); struct cleanup_node_struct *previous = NULL, *gone = NULL; while (current != NULL) { if (ssh_channel_is_closed(current->data->channel)) { if (current == (*head_ref)) { (*head_ref) = current->next; } if (previous != NULL) { previous->next = current->next; } gone = current; current = current->next; if (gone->data->channel) { _close_socket(*gone->data); ssh_remove_channel_callbacks(gone->data->channel, gone->data->cb_chan); ssh_channel_free(gone->data->channel); gone->data->channel = NULL; SAFE_FREE(gone->data->p_fd); SAFE_FREE(gone->data->cb_chan); SAFE_FREE(gone->data); SAFE_FREE(gone); } else { fprintf(stderr, "channel already freed!\n"); } _ssh_log(SSH_LOG_FUNCTIONS, "=== do_cleanup", "Freed."); } else { ssh_channel_close(current->data->channel); previous = current; current = current->next; } } } static int auth_password(ssh_session session, const char *user, const char *password, UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, "=== auth_password", "Authenticating user %s pwd %s", user, password); if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0) { authenticated = true; printf("Authenticated\n"); return SSH_AUTH_SUCCESS; } if (tries >= 3) { printf("Too many authentication tries\n"); ssh_disconnect(session); error_set = true; return SSH_AUTH_DENIED; } tries++; return SSH_AUTH_DENIED; } static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, UNUSED_PARAM(void *userdata)) { ssh_gssapi_creds creds = ssh_gssapi_get_creds(session); printf("Authenticating user %s with gssapi principal %s\n", user, principal); if (creds != NULL) { printf("Received some gssapi credentials\n"); } else { printf("Not received any forwardable creds\n"); } printf("authenticated\n"); authenticated = true; return SSH_AUTH_SUCCESS; } static int subsystem_request(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), const char *subsystem, UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Channel subsystem reqeuest: %s", subsystem); return 0; } struct ssh_channel_callbacks_struct channel_cb = { .channel_subsystem_request_function = subsystem_request }; static ssh_channel new_session_channel(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Session channel request"); /* For TCP forward only there seems to be no need for a session channel */ /*if(chan != NULL) return NULL; printf("Session channel request\n"); chan = ssh_channel_new(session); ssh_callbacks_init(&channel_cb); ssh_set_channel_callbacks(chan, &channel_cb); return chan;*/ return NULL; } static void stack_socket_close(UNUSED_PARAM(ssh_session session), struct event_fd_data_struct *event_fd_data) { if (event_fd_data->stacked != 1) { _ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close", "Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd, sockets_cnt); event_fd_data->stacked = 1; cleanup_push(&cleanup_stack, event_fd_data); } } static void _close_socket(struct event_fd_data_struct event_fd_data) { _ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket", "Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd, sockets_cnt); ssh_event_remove_fd(mainloop, *event_fd_data.p_fd); sockets_cnt--; #ifdef _WIN32 closesocket(*event_fd_data.p_fd); #else close(*event_fd_data.p_fd); #endif // _WIN32 (*event_fd_data.p_fd) = SSH_INVALID_SOCKET; } static int service_request(UNUSED_PARAM(ssh_session session), const char *service, UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, "=== service_request", "Service request: %s", service); return 0; } static void global_request(UNUSED_PARAM(ssh_session session), ssh_message message, UNUSED_PARAM(void *userdata)) { _ssh_log(SSH_LOG_PROTOCOL, "=== global_request", "Global request, message type: %d", ssh_message_type(message)); } static void my_channel_close_function(ssh_session session, UNUSED_PARAM(ssh_channel channel), void *userdata) { struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata; _ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_close_function", "Channel closed by remote."); stack_socket_close(session, event_fd_data); } static void my_channel_eof_function(ssh_session session, UNUSED_PARAM(ssh_channel channel), void *userdata) { struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata; _ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_eof_function", "Got EOF on channel. Shuting down write on socket (fd = %d).", *event_fd_data->p_fd); stack_socket_close(session, event_fd_data); } static void my_channel_exit_status_function(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), int exit_status, void *userdata) { struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata; _ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_exit_status_function", "Got exit status %d on channel fd = %d.", exit_status, *event_fd_data->p_fd); } static int my_channel_data_function(ssh_session session, UNUSED_PARAM(ssh_channel channel), void *data, uint32_t len, UNUSED_PARAM(int is_stderr), void *userdata) { int i = 0; struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata; if (event_fd_data->channel == NULL) { fprintf(stderr, "Why we're here? Stacked = %d\n", event_fd_data->stacked); } _ssh_log(SSH_LOG_PROTOCOL, "=== my_channel_data_function", "%d bytes waiting on channel for reading. Fd = %d", len, *event_fd_data->p_fd); if (len > 0) { i = send(*event_fd_data->p_fd, data, len, 0); } if (i < 0) { _ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function", "Writing to tcp socket %d: %s", *event_fd_data->p_fd, strerror(errno)); stack_socket_close(session, event_fd_data); } else { _ssh_log(SSH_LOG_FUNCTIONS, "=== my_channel_data_function", "Sent %d bytes", i); } return i; } static int my_fd_data_function(UNUSED_PARAM(socket_t fd), int revents, void *userdata) { struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata; ssh_channel channel = event_fd_data->channel; ssh_session session; int len, i, wr; char buf[16384]; int blocking; if (channel == NULL) { _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel == NULL!"); return 0; } session = ssh_channel_get_session(channel); if (ssh_channel_is_closed(channel)) { _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel is closed!"); stack_socket_close(session, event_fd_data); return 0; } if (!(revents & POLLIN)) { if (revents & POLLPRI) { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLPRI"); } if (revents & POLLOUT) { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLOUT"); } if (revents & POLLHUP) { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLHUP"); } if (revents & POLLNVAL) { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLNVAL"); } if (revents & POLLERR) { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLERR"); } return 0; } blocking = ssh_is_blocking(session); ssh_set_blocking(session, 0); _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "Trying to read from tcp socket fd = %d", *event_fd_data->p_fd); #ifdef _WIN32 struct sockaddr from; int fromlen = sizeof(from); len = recvfrom(*event_fd_data->p_fd, buf, sizeof(buf), 0, &from, &fromlen); #else len = recv(*event_fd_data->p_fd, buf, sizeof(buf), 0); #endif // _WIN32 if (len < 0) { _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Reading from tcp socket: %s", strerror(errno)); ssh_channel_send_eof(channel); } else if (len > 0) { if (ssh_channel_is_open(channel)) { wr = 0; do { i = ssh_channel_write(channel, buf, len); if (i < 0) { _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Error writing on the direct-tcpip channel: %d", i); len = wr; break; } wr += i; _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel_write (%d from %d)", wr, len); } while (i > 0 && wr < len); } else { _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Can't write on closed channel!"); } } else { _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "The destination host has disconnected!"); ssh_channel_close(channel); #ifdef _WIN32 shutdown(*event_fd_data->p_fd, SD_RECEIVE); #else shutdown(*event_fd_data->p_fd, SHUT_RD); #endif // _WIN32 } ssh_set_blocking(session, blocking); return len; } static int open_tcp_socket(ssh_message msg) { struct sockaddr_in sin; int forwardsock = -1; struct hostent *host; const char *dest_hostname; int dest_port; forwardsock = socket(AF_INET, SOCK_STREAM, 0); if (forwardsock < 0) { _ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR opening socket: %s", strerror(errno)); return -1; } dest_hostname = ssh_message_channel_request_open_destination(msg); dest_port = ssh_message_channel_request_open_destination_port(msg); _ssh_log(SSH_LOG_PROTOCOL, "=== open_tcp_socket", "Connecting to %s on port %d", dest_hostname, dest_port); host = gethostbyname(dest_hostname); if (host == NULL) { close(forwardsock); _ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR, no such host: %s", dest_hostname); return -1; } memset((char *)&sin, '\0', sizeof(sin)); sin.sin_family = AF_INET; memcpy((char *)&sin.sin_addr.s_addr, (char *)host->h_addr, host->h_length); sin.sin_port = htons(dest_port); if (connect(forwardsock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { close(forwardsock); _ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR connecting: %s", strerror(errno)); return -1; } sockets_cnt++; _ssh_log(SSH_LOG_FUNCTIONS, "=== open_tcp_socket", "Connected. sockets_cnt = %d", sockets_cnt); return forwardsock; } static int message_callback(UNUSED_PARAM(ssh_session session), ssh_message message, UNUSED_PARAM(void *userdata)) { ssh_channel channel; int socket_fd, *pFd; struct ssh_channel_callbacks_struct *cb_chan; struct event_fd_data_struct *event_fd_data; _ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d", ssh_message_type(message)); _ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d", ssh_message_subtype(message)); if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN) { _ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "channel_request_open"); if (ssh_message_subtype(message) == SSH_CHANNEL_DIRECT_TCPIP) { channel = ssh_message_channel_request_open_reply_accept(message); if (channel == NULL) { _ssh_log(SSH_LOG_WARNING, "=== message_callback", "Accepting direct-tcpip channel failed!"); return 1; } else { _ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "Connected to channel!"); socket_fd = open_tcp_socket(message); if (-1 == socket_fd) { return 1; } pFd = malloc(sizeof *pFd); cb_chan = malloc(sizeof *cb_chan); event_fd_data = malloc(sizeof *event_fd_data); (*pFd) = socket_fd; event_fd_data->channel = channel; event_fd_data->p_fd = pFd; event_fd_data->stacked = 0; event_fd_data->cb_chan = cb_chan; cb_chan->userdata = event_fd_data; cb_chan->channel_eof_function = my_channel_eof_function; cb_chan->channel_close_function = my_channel_close_function; cb_chan->channel_data_function = my_channel_data_function; cb_chan->channel_exit_status_function = my_channel_exit_status_function; ssh_callbacks_init(cb_chan); ssh_set_channel_callbacks(channel, cb_chan); ssh_event_add_fd(mainloop, (socket_t)*pFd, POLLIN, my_fd_data_function, event_fd_data); return 0; } } } return 1; } #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh server example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; switch (key) { case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "1"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ int main(int argc, char **argv) { ssh_session session; ssh_bind sshbind; struct ssh_server_callbacks_struct cb = { .userdata = NULL, .auth_password_function = auth_password, .auth_gssapi_mic_function = auth_gssapi_mic, .channel_open_request_session_function = new_session_channel, .service_request_function = service_request }; struct ssh_callbacks_struct cb_gen = { .userdata = NULL, .global_request_function = global_request }; int ret = 1; sshbind = ssh_bind_new(); session = ssh_new(); mainloop = ssh_event_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void)argc; (void)argv; #endif if (ssh_bind_listen(sshbind) < 0) { printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } if (ssh_bind_accept(sshbind, session) == SSH_ERROR) { printf("error accepting a connection : %s\n", ssh_get_error(sshbind)); ret = 1; goto shutdown; } ssh_callbacks_init(&cb); ssh_callbacks_init(&cb_gen); ssh_set_server_callbacks(session, &cb); ssh_set_callbacks(session, &cb_gen); ssh_set_message_callback(session, message_callback, (void *)NULL); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); ssh_event_add_session(mainloop, session); while (!authenticated) { if (error_set) { break; } if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR) { printf("Error : %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } } if (error_set) { printf("Error, exiting loop\n"); } else { printf("Authenticated and got a channel\n"); while (!error_set) { if (ssh_event_dopoll(mainloop, 100) == SSH_ERROR) { printf("Error : %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } do_cleanup(&cleanup_stack); } } shutdown: ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); return ret; } ================================================ FILE: src/libssh/examples/sshnetcat.c ================================================ /* Copyright 2010 Aris Adamantiadis This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include "config.h" #include #include #include #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include "examples_common.h" char *host; const char *desthost="localhost"; const char *port="22"; #ifdef WITH_PCAP #include char *pcap_file=NULL; #endif static void usage(void) { fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n"); exit(1); } static int opts(int argc, char **argv){ int i; while((i=getopt(argc,argv,"P:"))!=-1){ switch(i){ #ifdef WITH_PCAP case 'P': pcap_file=optarg; break; #endif default: fprintf(stderr,"unknown option %c\n",optopt); usage(); } } if(optind < argc) host=argv[optind++]; if(optind < argc) desthost=argv[optind++]; if(optind < argc) port=argv[optind++]; if(host==NULL) usage(); return 0; } static void select_loop(ssh_session session,ssh_channel channel){ fd_set fds; struct timeval timeout; char buffer[4096]; /* channels will be set to the channels to poll. * outchannels will contain the result of the poll */ ssh_channel channels[2], outchannels[2]; int lus; int eof=0; int maxfd; int ret; while(channel){ do{ int fd; ZERO_STRUCT(fds); FD_ZERO(&fds); if(!eof) FD_SET(0,&fds); timeout.tv_sec=30; timeout.tv_usec=0; fd = ssh_get_fd(session); if (fd == -1) { fprintf(stderr, "Error getting the session file descriptor: %s\n", ssh_get_error(session)); return; } FD_SET(fd, &fds); maxfd = fd + 1; channels[0]=channel; // set the first channel we want to read from channels[1]=NULL; ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout); if(ret==EINTR) continue; if(FD_ISSET(0,&fds)){ lus=read(0,buffer,sizeof(buffer)); if(lus) ssh_channel_write(channel,buffer,lus); else { eof=1; ssh_channel_send_eof(channel); } } if(channel && ssh_channel_is_closed(channel)){ ssh_channel_free(channel); channel=NULL; channels[0]=NULL; } if(outchannels[0]){ while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){ lus = ssh_channel_read(channel,buffer,sizeof(buffer),0); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ ssh_channel_free(channel); channel=channels[0]=NULL; } else { ret = write(1, buffer, lus); if (ret < 0) { fprintf(stderr, "Error writing to stdin: %s", strerror(errno)); return; } } } while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */ lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1); if(lus==-1){ fprintf(stderr, "Error reading channel: %s\n", ssh_get_error(session)); return; } if(lus==0){ ssh_channel_free(channel); channel=channels[0]=NULL; } else { ret = write(2, buffer, lus); if (ret < 0) { fprintf(stderr, "Error writing to stderr: %s", strerror(errno)); return; } } } } if(channel && ssh_channel_is_closed(channel)){ ssh_channel_free(channel); channel=NULL; } } while (ret==EINTR || ret==SSH_EINTR); } } static void forwarding(ssh_session session){ ssh_channel channel; int r; channel = ssh_channel_new(session); r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22); if(r<0) { printf("error forwarding port : %s\n",ssh_get_error(session)); return; } select_loop(session,channel); } static int client(ssh_session session){ int auth=0; char *banner; int state; if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) return -1; ssh_options_parse_config(session, NULL); if(ssh_connect(session)){ fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); return -1; } state=verify_knownhost(session); if (state != 0) return -1; ssh_userauth_none(session, NULL); banner=ssh_get_issue_banner(session); if(banner){ printf("%s\n",banner); free(banner); } auth=authenticate_console(session); if(auth != SSH_AUTH_SUCCESS){ return -1; } forwarding(session); return 0; } #ifdef WITH_PCAP ssh_pcap_file pcap; void set_pcap(ssh_session session); void set_pcap(ssh_session session){ if(!pcap_file) return; pcap=ssh_pcap_file_new(); if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){ printf("Error opening pcap file\n"); ssh_pcap_file_free(pcap); pcap=NULL; return; } ssh_set_pcap_file(session,pcap); } void cleanup_pcap(void); void cleanup_pcap(){ ssh_pcap_file_free(pcap); pcap=NULL; } #endif int main(int argc, char **argv){ ssh_session session; session = ssh_new(); if(ssh_options_getopt(session, &argc, argv)) { fprintf(stderr, "error parsing command line :%s\n", ssh_get_error(session)); usage(); } opts(argc,argv); #ifdef WITH_PCAP set_pcap(session); #endif client(session); ssh_disconnect(session); ssh_free(session); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; } ================================================ FILE: src/libssh/include/CMakeLists.txt ================================================ project(libssh-headers-x C) add_subdirectory(libssh) ================================================ FILE: src/libssh/include/libssh/CMakeLists.txt ================================================ project(libssh-headers C) set(libssh_HDRS callbacks.h libssh.h ssh2.h legacy.h libsshpp.hpp ) if (WITH_SFTP) set(libssh_HDRS ${libssh_HDRS} sftp.h ) endif (WITH_SFTP) if (WITH_SERVER) set(libssh_HDRS ${libssh_HDRS} server.h ) endif (WITH_SERVER) install( FILES ${libssh_HDRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME} COMPONENT headers ) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libssh_version.h.cmake ${libssh_BINARY_DIR}/include/libssh/libssh_version.h @ONLY) install(FILES ${libssh_BINARY_DIR}/include/libssh/libssh_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME} COMPONENT headers) ================================================ FILE: src/libssh/include/libssh/agent.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2008-2009 Andreas Schneider * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __AGENT_H #define __AGENT_H #include "libssh/libssh.h" /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENTC_RSA_CHALLENGE 3 #define SSH_AGENT_RSA_RESPONSE 4 #define SSH_AGENT_FAILURE 5 #define SSH_AGENT_SUCCESS 6 #define SSH_AGENTC_ADD_RSA_IDENTITY 7 #define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* private OpenSSH extensions for SSH2 */ #define SSH2_AGENTC_REQUEST_IDENTITIES 11 #define SSH2_AGENT_IDENTITIES_ANSWER 12 #define SSH2_AGENTC_SIGN_REQUEST 13 #define SSH2_AGENT_SIGN_RESPONSE 14 #define SSH2_AGENTC_ADD_IDENTITY 17 #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 /* smartcard */ #define SSH_AGENTC_ADD_SMARTCARD_KEY 20 #define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 /* lock/unlock the agent */ #define SSH_AGENTC_LOCK 22 #define SSH_AGENTC_UNLOCK 23 /* add key with constraints */ #define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 /* extended failure messages */ #define SSH2_AGENT_FAILURE 30 /* additional error code for ssh.com's ssh-agent2 */ #define SSH_COM_AGENT2_FAILURE 102 #define SSH_AGENT_OLD_SIGNATURE 0x01 /* Signature flags from draft-miller-ssh-agent-02 */ #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 struct ssh_agent_struct { #ifndef _WIN32 struct ssh_socket_struct *sock; #endif ssh_buffer ident; unsigned int count; ssh_channel channel; }; /* agent.c */ /** * @brief Create a new ssh agent structure. * * @return An allocated ssh agent structure or NULL on error. */ struct ssh_agent_struct *ssh_agent_new(struct ssh_session_struct *session); void ssh_agent_close(struct ssh_agent_struct *agent); /** * @brief Free an allocated ssh agent structure. * * @param agent The ssh agent structure to free. */ void ssh_agent_free(struct ssh_agent_struct *agent); /** * @brief Check if the ssh agent is running. * * @param session The ssh session to check for the agent. * * @return 1 if it is running, 0 if not. */ int ssh_agent_is_running(struct ssh_session_struct *session); uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session); ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session, char **comment); ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session, char **comment); ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data); #endif /* __AGENT_H */ ================================================ FILE: src/libssh/include/libssh/auth.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef AUTH_H_ #define AUTH_H_ #include "config.h" #include "libssh/callbacks.h" SSH_PACKET_CALLBACK(ssh_packet_userauth_banner); SSH_PACKET_CALLBACK(ssh_packet_userauth_failure); SSH_PACKET_CALLBACK(ssh_packet_userauth_success); SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok); SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request); SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response); /** @internal * kdbint structure must be shared with message.c * and server.c */ struct ssh_kbdint_struct { uint32_t nprompts; uint32_t nanswers; char *name; char *instruction; char **prompts; unsigned char *echo; /* bool array */ char **answers; }; typedef struct ssh_kbdint_struct* ssh_kbdint; ssh_kbdint ssh_kbdint_new(void); void ssh_kbdint_clean(ssh_kbdint kbd); void ssh_kbdint_free(ssh_kbdint kbd); /** @internal * States of authentication in the client-side. They describe * what was the last response from the server */ enum ssh_auth_state_e { /** No authentication asked */ SSH_AUTH_STATE_NONE=0, /** Last authentication response was a partial success */ SSH_AUTH_STATE_PARTIAL, /** Last authentication response was a success */ SSH_AUTH_STATE_SUCCESS, /** Last authentication response was failed */ SSH_AUTH_STATE_FAILED, /** Last authentication was erroneous */ SSH_AUTH_STATE_ERROR, /** Last state was a keyboard-interactive ask for info */ SSH_AUTH_STATE_INFO, /** Last state was a public key accepted for authentication */ SSH_AUTH_STATE_PK_OK, /** We asked for a keyboard-interactive authentication */ SSH_AUTH_STATE_KBDINT_SENT, /** We have sent an userauth request with gssapi-with-mic */ SSH_AUTH_STATE_GSSAPI_REQUEST_SENT, /** We are exchanging tokens until authentication */ SSH_AUTH_STATE_GSSAPI_TOKEN, /** We have sent the MIC and expecting to be authenticated */ SSH_AUTH_STATE_GSSAPI_MIC_SENT, /** We have offered a pubkey to check if it is supported */ SSH_AUTH_STATE_PUBKEY_OFFER_SENT, /** We have sent pubkey and signature expecting to be authenticated */ SSH_AUTH_STATE_PUBKEY_AUTH_SENT, /** We have sent a password expecting to be authenticated */ SSH_AUTH_STATE_PASSWORD_AUTH_SENT, /** We have sent a request without auth information (method 'none') */ SSH_AUTH_STATE_AUTH_NONE_SENT, }; /** @internal * @brief states of the authentication service request */ enum ssh_auth_service_state_e { /** initial state */ SSH_AUTH_SERVICE_NONE=0, /** Authentication service request packet sent */ SSH_AUTH_SERVICE_SENT, /** Service accepted */ SSH_AUTH_SERVICE_ACCEPTED, /** Access to service denied (fatal) */ SSH_AUTH_SERVICE_DENIED, }; #endif /* AUTH_H_ */ ================================================ FILE: src/libssh/include/libssh/bignum.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2014 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BIGNUM_H_ #define BIGNUM_H_ #include "libssh/libcrypto.h" #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" bignum ssh_make_string_bn(ssh_string string); ssh_string ssh_make_bignum_string(bignum num); void ssh_print_bignum(const char *which, const_bignum num); #endif /* BIGNUM_H_ */ ================================================ FILE: src/libssh/include/libssh/bind.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BIND_H_ #define BIND_H_ #include "libssh/priv.h" #include "libssh/kex.h" #include "libssh/session.h" struct ssh_bind_struct { struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */ struct ssh_bind_callbacks_struct *bind_callbacks; void *bind_callbacks_userdata; struct ssh_poll_handle_struct *poll; /* options */ char *wanted_methods[SSH_KEX_METHODS]; char *banner; char *ecdsakey; char *dsakey; char *rsakey; char *ed25519key; ssh_key ecdsa; ssh_key dsa; ssh_key rsa; ssh_key ed25519; char *bindaddr; socket_t bindfd; unsigned int bindport; int blocking; int toaccept; bool config_processed; char *config_dir; char *pubkey_accepted_key_types; }; struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct *sshbind); #endif /* BIND_H_ */ ================================================ FILE: src/libssh/include/libssh/bind_config.h ================================================ /* * bind_config.h - Parse the SSH server configuration file * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef BIND_CONFIG_H_ #define BIND_CONFIG_H_ #include "libssh/server.h" enum ssh_bind_config_opcode_e { /* Known but not allowed in Match block */ BIND_CFG_NOT_ALLOWED_IN_MATCH = -4, /* Unknown opcode */ BIND_CFG_UNKNOWN = -3, /* Known and not applicable to libssh */ BIND_CFG_NA = -2, /* Known but not supported by current libssh version */ BIND_CFG_UNSUPPORTED = -1, BIND_CFG_INCLUDE, BIND_CFG_HOSTKEY, BIND_CFG_LISTENADDRESS, BIND_CFG_PORT, BIND_CFG_LOGLEVEL, BIND_CFG_CIPHERS, BIND_CFG_MACS, BIND_CFG_KEXALGORITHMS, BIND_CFG_MATCH, BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES, BIND_CFG_HOSTKEY_ALGORITHMS, BIND_CFG_MAX /* Keep this one last in the list */ }; /* @brief Parse configuration file and set the options to the given ssh_bind * * @params[in] sshbind The ssh_bind context to be configured * @params[in] filename The path to the configuration file * * @returns 0 on successful parsing the configuration file, -1 on error */ int ssh_bind_config_parse_file(ssh_bind sshbind, const char *filename); #endif /* BIND_CONFIG_H_ */ ================================================ FILE: src/libssh/include/libssh/blf.h ================================================ /* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */ /* * Blowfish - a fast block cipher designed by Bruce Schneier * * Copyright 1997 Niels Provos * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Niels Provos. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. */ #ifndef _BLF_H_ #define _BLF_H_ //#include "includes.h" #if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) /* Schneier specifies a maximum key length of 56 bytes. * This ensures that every key bit affects every cipher * bit. However, the subkeys can hold up to 72 bytes. * Warning: For normal blowfish encryption only 56 bytes * of the key affect all cipherbits. */ #define BLF_N 16 /* Number of Subkeys */ #define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */ #define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */ /* Blowfish context */ typedef struct BlowfishContext { uint32_t S[4][256]; /* S-Boxes */ uint32_t P[BLF_N + 2]; /* Subkeys */ } ssh_blf_ctx; /* Raw access to customized Blowfish * blf_key is just: * Blowfish_initstate( state ) * Blowfish_expand0state( state, key, keylen ) */ void Blowfish_encipher(ssh_blf_ctx *, uint32_t *, uint32_t *); void Blowfish_decipher(ssh_blf_ctx *, uint32_t *, uint32_t *); void Blowfish_initstate(ssh_blf_ctx *); void Blowfish_expand0state(ssh_blf_ctx *, const uint8_t *, uint16_t); void Blowfish_expandstate (ssh_blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t); /* Standard Blowfish */ void ssh_blf_key(ssh_blf_ctx *, const uint8_t *, uint16_t); void ssh_blf_enc(ssh_blf_ctx *, uint32_t *, uint16_t); void ssh_blf_dec(ssh_blf_ctx *, uint32_t *, uint16_t); void ssh_blf_ecb_encrypt(ssh_blf_ctx *, uint8_t *, uint32_t); void ssh_blf_ecb_decrypt(ssh_blf_ctx *, uint8_t *, uint32_t); void ssh_blf_cbc_encrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); void ssh_blf_cbc_decrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); /* Converts uint8_t to uint32_t */ uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *); #endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */ #endif /* _BLF_H */ ================================================ FILE: src/libssh/include/libssh/buffer.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BUFFER_H_ #define BUFFER_H_ #include #include "libssh/libssh.h" #define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3) void ssh_buffer_set_secure(ssh_buffer buffer); int ssh_buffer_add_ssh_string(ssh_buffer buffer, ssh_string string); int ssh_buffer_add_u8(ssh_buffer buffer, uint8_t data); int ssh_buffer_add_u16(ssh_buffer buffer, uint16_t data); int ssh_buffer_add_u32(ssh_buffer buffer, uint32_t data); int ssh_buffer_add_u64(ssh_buffer buffer, uint64_t data); int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len); void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len); int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer, uint32_t len); int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, const char *format, size_t argc, va_list ap); int _ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, size_t argc, ...); #define ssh_buffer_pack(buffer, format, ...) \ _ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END) int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, const char *format, size_t argc, va_list ap); int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, size_t argc, ...); #define ssh_buffer_unpack(buffer, format, ...) \ _ssh_buffer_unpack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END) int ssh_buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len); int ssh_buffer_add_buffer(ssh_buffer buffer, ssh_buffer source); /* buffer_read_*() returns the number of bytes read, except for ssh strings */ int ssh_buffer_get_u8(ssh_buffer buffer, uint8_t *data); int ssh_buffer_get_u32(ssh_buffer buffer, uint32_t *data); int ssh_buffer_get_u64(ssh_buffer buffer, uint64_t *data); /* ssh_buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer); /* ssh_buffer_pass_bytes acts as if len bytes have been read (used for padding) */ uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len); uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len); #endif /* BUFFER_H_ */ ================================================ FILE: src/libssh/include/libssh/bytearray.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 Andreas Schneider * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _BYTEARRAY_H #define _BYTEARRAY_H #define _DATA_BYTE_CONST(data, pos) \ ((uint8_t)(((const uint8_t *)(data))[(pos)])) #define _DATA_BYTE(data, pos) \ (((uint8_t *)(data))[(pos)]) /* * These macros pull or push integer values from byte arrays stored in * little-endian byte order. */ #define PULL_LE_U8(data, pos) \ (_DATA_BYTE_CONST(data, pos)) #define PULL_LE_U16(data, pos) \ ((uint16_t)PULL_LE_U8(data, pos) | ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8) #define PULL_LE_U32(data, pos) \ ((uint32_t)(PULL_LE_U16(data, pos) | ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16)) #define PULL_LE_U64(data, pos) \ ((uint64_t)(PULL_LE_U32(data, pos) | ((uint64_t)PULL_LE_U32(data, (pos) + 4)) << 32)) #define PUSH_LE_U8(data, pos, val) \ (_DATA_BYTE(data, pos) = ((uint8_t)(val))) #define PUSH_LE_U16(data, pos, val) \ (PUSH_LE_U8((data), (pos), (uint8_t)((uint16_t)(val) & 0xff)), PUSH_LE_U8((data), (pos) + 1, (uint8_t)((uint16_t)(val) >> 8))) #define PUSH_LE_U32(data, pos, val) \ (PUSH_LE_U16((data), (pos), (uint16_t)((uint32_t)(val) & 0xffff)), PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16))) #define PUSH_LE_U64(data, pos, val) \ (PUSH_LE_U32((data), (pos), (uint32_t)((uint64_t)(val) & 0xffffffff)), PUSH_LE_U32((data), (pos) + 4, (uint32_t)((uint64_t)(val) >> 32))) /* * These macros pull or push integer values from byte arrays stored in * big-endian byte order (network byte order). */ #define PULL_BE_U8(data, pos) \ (_DATA_BYTE_CONST(data, pos)) #define PULL_BE_U16(data, pos) \ ((((uint16_t)(PULL_BE_U8(data, pos))) << 8) | (uint16_t)PULL_BE_U8(data, (pos) + 1)) #define PULL_BE_U32(data, pos) \ ((((uint32_t)PULL_BE_U16(data, pos)) << 16) | (uint32_t)(PULL_BE_U16(data, (pos) + 2))) #define PULL_BE_U64(data, pos) \ ((((uint64_t)PULL_BE_U32(data, pos)) << 32) | (uint64_t)(PULL_BE_U32(data, (pos) + 4))) #define PUSH_BE_U8(data, pos, val) \ (_DATA_BYTE(data, pos) = ((uint8_t)(val))) #define PUSH_BE_U16(data, pos, val) \ (PUSH_BE_U8((data), (pos), (uint8_t)(((uint16_t)(val)) >> 8)), PUSH_BE_U8((data), (pos) + 1, (uint8_t)((val) & 0xff))) #define PUSH_BE_U32(data, pos, val) \ (PUSH_BE_U16((data), (pos), (uint16_t)(((uint32_t)(val)) >> 16)), PUSH_BE_U16((data), (pos) + 2, (uint16_t)((val) & 0xffff))) #define PUSH_BE_U64(data, pos, val) \ (PUSH_BE_U32((data), (pos), (uint32_t)(((uint64_t)(val)) >> 32)), PUSH_BE_U32((data), (pos) + 4, (uint32_t)((val) & 0xffffffff))) #endif /* _BYTEARRAY_H */ ================================================ FILE: src/libssh/include/libssh/callbacks.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* callback.h * This file includes the public declarations for the libssh callback mechanism */ #ifndef _SSH_CALLBACK_H #define _SSH_CALLBACK_H #include #include #ifdef __cplusplus extern "C" { #endif /** * @defgroup libssh_callbacks The libssh callbacks * @ingroup libssh * * Callback which can be replaced in libssh. * * @{ */ /** @internal * @brief callback to process simple codes * @param code value to transmit * @param user Userdata to pass in callback */ typedef void (*ssh_callback_int) (int code, void *user); /** @internal * @brief callback for data received messages. * @param data data retrieved from the socket or stream * @param len number of bytes available from this stream * @param user user-supplied pointer sent along with all callback messages * @returns number of bytes processed by the callee. The remaining bytes will * be sent in the next callback message, when more data is available. */ typedef int (*ssh_callback_data) (const void *data, size_t len, void *user); typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user); typedef int (*ssh_message_callback) (ssh_session, ssh_message message, void *user); typedef int (*ssh_channel_callback_int) (ssh_channel channel, int code, void *user); typedef int (*ssh_channel_callback_data) (ssh_channel channel, int code, void *data, size_t len, void *user); /** * @brief SSH log callback. All logging messages will go through this callback * @param session Current session handler * @param priority Priority of the log, the smaller being the more important * @param message the actual message * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_log_callback) (ssh_session session, int priority, const char *message, void *userdata); /** * @brief SSH log callback. * * All logging messages will go through this callback. * * @param priority Priority of the log, the smaller being the more important. * * @param function The function name calling the the logging fucntions. * * @param message The actual message * * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_logging_callback) (int priority, const char *function, const char *buffer, void *userdata); /** * @brief SSH Connection status callback. * @param session Current session handler * @param status Percentage of connection status, going from 0.0 to 1.0 * once connection is done. * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_status_callback) (ssh_session session, float status, void *userdata); /** * @brief SSH global request callback. All global request will go through this * callback. * @param session Current session handler * @param message the actual message * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_global_request_callback) (ssh_session session, ssh_message message, void *userdata); /** * @brief Handles an SSH new channel open X11 request. This happens when the server * sends back an X11 connection attempt. This is a client-side API * @param session current session handler * @param userdata Userdata to be passed to the callback function. * @returns a valid ssh_channel handle if the request is to be allowed * @returns NULL if the request should not be allowed * @warning The channel pointer returned by this callback must be closed by the application. */ typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session session, const char * originator_address, int originator_port, void *userdata); /** * @brief Handles an SSH new channel open "auth-agent" request. This happens when the server * sends back an "auth-agent" connection attempt. This is a client-side API * @param session current session handler * @param userdata Userdata to be passed to the callback function. * @returns a valid ssh_channel handle if the request is to be allowed * @returns NULL if the request should not be allowed * @warning The channel pointer returned by this callback must be closed by the application. */ typedef ssh_channel (*ssh_channel_open_request_auth_agent_callback) (ssh_session session, void *userdata); /** * The structure to replace libssh functions with appropriate callbacks. */ struct ssh_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ size_t size; /** * User-provided data. User is free to set anything he wants here */ void *userdata; /** * This functions will be called if e.g. a keyphrase is needed. */ ssh_auth_callback auth_function; /** * This function will be called each time a loggable event happens. */ ssh_log_callback log_function; /** * This function gets called during connection time to indicate the * percentage of connection steps completed. */ void (*connect_status_function)(void *userdata, float status); /** * This function will be called each time a global request is received. */ ssh_global_request_callback global_request_function; /** This function will be called when an incoming X11 request is received. */ ssh_channel_open_request_x11_callback channel_open_request_x11_function; /** This function will be called when an incoming "auth-agent" request is received. */ ssh_channel_open_request_auth_agent_callback channel_open_request_auth_agent_function; }; typedef struct ssh_callbacks_struct *ssh_callbacks; /** These are callbacks used specifically in SSH servers. */ /** * @brief SSH authentication callback. * @param session Current session handler * @param user User that wants to authenticate * @param password Password used for authentication * @param userdata Userdata to be passed to the callback function. * @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_DENIED Authentication failed. */ typedef int (*ssh_auth_password_callback) (ssh_session session, const char *user, const char *password, void *userdata); /** * @brief SSH authentication callback. Tries to authenticates user with the "none" method * which is anonymous or passwordless. * @param session Current session handler * @param user User that wants to authenticate * @param userdata Userdata to be passed to the callback function. * @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_DENIED Authentication failed. */ typedef int (*ssh_auth_none_callback) (ssh_session session, const char *user, void *userdata); /** * @brief SSH authentication callback. Tries to authenticates user with the "gssapi-with-mic" method * @param session Current session handler * @param user Username of the user (can be spoofed) * @param principal Authenticated principal of the user, including realm. * @param userdata Userdata to be passed to the callback function. * @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_DENIED Authentication failed. * @warning Implementations should verify that parameter user matches in some way the principal. * user and principal can be different. Only the latter is guaranteed to be safe. */ typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *user, const char *principal, void *userdata); /** * @brief SSH authentication callback. * @param session Current session handler * @param user User that wants to authenticate * @param pubkey public key used for authentication * @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe), * SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be * replied with a SSH_AUTH_DENIED. * @param userdata Userdata to be passed to the callback function. * @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_DENIED Authentication failed. */ typedef int (*ssh_auth_pubkey_callback) (ssh_session session, const char *user, struct ssh_key_struct *pubkey, char signature_state, void *userdata); /** * @brief Handles an SSH service request * @param session current session handler * @param service name of the service (e.g. "ssh-userauth") requested * @param userdata Userdata to be passed to the callback function. * @returns 0 if the request is to be allowed * @returns -1 if the request should not be allowed */ typedef int (*ssh_service_request_callback) (ssh_session session, const char *service, void *userdata); /** * @brief Handles an SSH new channel open session request * @param session current session handler * @param userdata Userdata to be passed to the callback function. * @returns a valid ssh_channel handle if the request is to be allowed * @returns NULL if the request should not be allowed * @warning The channel pointer returned by this callback must be closed by the application. */ typedef ssh_channel (*ssh_channel_open_request_session_callback) (ssh_session session, void *userdata); /* * @brief handle the beginning of a GSSAPI authentication, server side. * @param session current session handler * @param user the username of the client * @param n_oid number of available oids * @param oids OIDs provided by the client * @returns an ssh_string containing the chosen OID, that's supported by both * client and server. * @warning It is not necessary to fill this callback in if libssh is linked * with libgssapi. */ typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const char *user, int n_oid, ssh_string *oids, void *userdata); /* * @brief handle the negociation of a security context, server side. * @param session current session handler * @param[in] input_token input token provided by client * @param[out] output_token output of the gssapi accept_sec_context method, * NULL after completion. * @returns SSH_OK if the token was generated correctly or accept_sec_context * returned GSS_S_COMPLETE * @returns SSH_ERROR in case of error * @warning It is not necessary to fill this callback in if libssh is linked * with libgssapi. */ typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session, ssh_string input_token, ssh_string *output_token, void *userdata); /* * @brief Verify and authenticates a MIC, server side. * @param session current session handler * @param[in] mic input mic to be verified provided by client * @param[in] mic_buffer buffer of data to be signed. * @param[in] mic_buffer_size size of mic_buffer * @returns SSH_OK if the MIC was authenticated correctly * @returns SSH_ERROR in case of error * @warning It is not necessary to fill this callback in if libssh is linked * with libgssapi. */ typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session, ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata); /** * This structure can be used to implement a libssh server, with appropriate callbacks. */ struct ssh_server_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ size_t size; /** * User-provided data. User is free to set anything he wants here */ void *userdata; /** This function gets called when a client tries to authenticate through * password method. */ ssh_auth_password_callback auth_password_function; /** This function gets called when a client tries to authenticate through * none method. */ ssh_auth_none_callback auth_none_function; /** This function gets called when a client tries to authenticate through * gssapi-mic method. */ ssh_auth_gssapi_mic_callback auth_gssapi_mic_function; /** this function gets called when a client tries to authenticate or offer * a public key. */ ssh_auth_pubkey_callback auth_pubkey_function; /** This functions gets called when a service request is issued by the * client */ ssh_service_request_callback service_request_function; /** This functions gets called when a new channel request is issued by * the client */ ssh_channel_open_request_session_callback channel_open_request_session_function; /** This function will be called when a new gssapi authentication is attempted. */ ssh_gssapi_select_oid_callback gssapi_select_oid_function; /** This function will be called when a gssapi token comes in. */ ssh_gssapi_accept_sec_ctx_callback gssapi_accept_sec_ctx_function; /* This function will be called when a MIC needs to be verified. */ ssh_gssapi_verify_mic_callback gssapi_verify_mic_function; }; typedef struct ssh_server_callbacks_struct *ssh_server_callbacks; /** * @brief Set the session server callback functions. * * This functions sets the callback structure to use your own callback * functions for user authentication, new channels and requests. * * @code * struct ssh_server_callbacks_struct cb = { * .userdata = data, * .auth_password_function = my_auth_function * }; * ssh_callbacks_init(&cb); * ssh_set_server_callbacks(session, &cb); * @endcode * * @param session The session to set the callback structure. * * @param cb The callback structure itself. * * @return SSH_OK on success, SSH_ERROR on error. */ LIBSSH_API int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb); /** * These are the callbacks exported by the socket structure * They are called by the socket module when a socket event appears */ struct ssh_socket_callbacks_struct { /** * User-provided data. User is free to set anything he wants here */ void *userdata; /** * This function will be called each time data appears on socket. The data * not consumed will appear on the next data event. */ ssh_callback_data data; /** This function will be called each time a controlflow state changes, i.e. * the socket is available for reading or writing. */ ssh_callback_int controlflow; /** This function will be called each time an exception appears on socket. An * exception can be a socket problem (timeout, ...) or an end-of-file. */ ssh_callback_int_int exception; /** This function is called when the ssh_socket_connect was used on the socket * on nonblocking state, and the connection successed. */ ssh_callback_int_int connected; }; typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks; struct ssh_socket_external_callbacks_struct { /** * User-provided data. User is free to set anything he wants here */ void *userdata; /** This function will be called each time data need send. */ ssh_callback_data send; }; typedef struct ssh_socket_external_callbacks_struct *ssh_socket_external_callbacks; #define SSH_SOCKET_FLOW_WRITEWILLBLOCK 1 #define SSH_SOCKET_FLOW_WRITEWONTBLOCK 2 #define SSH_SOCKET_EXCEPTION_EOF 1 #define SSH_SOCKET_EXCEPTION_ERROR 2 #define SSH_SOCKET_CONNECTED_OK 1 #define SSH_SOCKET_CONNECTED_ERROR 2 #define SSH_SOCKET_CONNECTED_TIMEOUT 3 /** * @brief Initializes an ssh_callbacks_struct * A call to this macro is mandatory when you have set a new * ssh_callback_struct structure. Its goal is to maintain the binary * compatibility with future versions of libssh as the structure * evolves with time. */ #define ssh_callbacks_init(p) do {\ (p)->size=sizeof(*(p)); \ } while(0); /** * @internal * @brief tests if a callback can be called without crash * verifies that the struct size if big enough * verifies that the callback pointer exists * @param p callback pointer * @param c callback name * @returns nonzero if callback can be called */ #define ssh_callbacks_exists(p,c) (\ (p != NULL) && ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \ ((p)-> c != NULL) \ ) /** * @internal * * @brief Iterate through a list of callback structures * * This tests for their validity and executes them. The userdata argument is * automatically passed through. * * @param list list of callbacks * * @param cbtype type of the callback * * @param c callback name * * @param va_args parameters to be passed */ #define ssh_callbacks_execute_list(list, cbtype, c, ...) \ do { \ struct ssh_iterator *i = ssh_list_get_iterator(list); \ cbtype cb; \ while (i != NULL){ \ cb = ssh_iterator_value(cbtype, i); \ if (ssh_callbacks_exists(cb, c)) \ cb-> c (__VA_ARGS__, cb->userdata); \ i = i->next; \ } \ } while(0) /** * @internal * * @brief iterate through a list of callback structures. * * This tests for their validity and give control back to the calling code to * execute them. Caller can decide to break the loop or continue executing the * callbacks with different parameters * * @code * ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, * channel_eof_function){ * rc = ssh_callbacks_iterate_exec(session, channel); * if (rc != SSH_OK){ * break; * } * } * ssh_callbacks_iterate_end(); * @endcode */ #define ssh_callbacks_iterate(_cb_list, _cb_type, _cb_name) \ do { \ struct ssh_iterator *_cb_i = ssh_list_get_iterator(_cb_list); \ _cb_type _cb; \ for (; _cb_i != NULL; _cb_i = _cb_i->next) { \ _cb = ssh_iterator_value(_cb_type, _cb_i); \ if (ssh_callbacks_exists(_cb, _cb_name)) #define ssh_callbacks_iterate_exec(_cb_name, ...) \ _cb->_cb_name(__VA_ARGS__, _cb->userdata) #define ssh_callbacks_iterate_end() \ } \ } while(0) /** @brief Prototype for a packet callback, to be called when a new packet arrives * @param session The current session of the packet * @param type packet type (see ssh2.h) * @param packet buffer containing the packet, excluding size, type and padding fields * @param user user argument to the callback * and are called each time a packet shows up * @returns SSH_PACKET_USED Packet was parsed and used * @returns SSH_PACKET_NOT_USED Packet was not used or understood, processing must continue */ typedef int (*ssh_packet_callback) (ssh_session session, uint8_t type, ssh_buffer packet, void *user); /** return values for a ssh_packet_callback */ /** Packet was used and should not be parsed by another callback */ #define SSH_PACKET_USED 1 /** Packet was not used and should be passed to any other callback * available */ #define SSH_PACKET_NOT_USED 2 /** @brief This macro declares a packet callback handler * @code * SSH_PACKET_CALLBACK(mycallback){ * ... * } * @endcode */ #define SSH_PACKET_CALLBACK(name) \ int name (ssh_session session, uint8_t type, ssh_buffer packet, void *user) struct ssh_packet_callbacks_struct { /** Index of the first packet type being handled */ uint8_t start; /** Number of packets being handled by this callback struct */ uint8_t n_callbacks; /** A pointer to n_callbacks packet callbacks */ ssh_packet_callback *callbacks; /** * User-provided data. User is free to set anything he wants here */ void *user; }; typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks; /** * @brief Set the session callback functions. * * This functions sets the callback structure to use your own callback * functions for auth, logging and status. * * @code * struct ssh_callbacks_struct cb = { * .userdata = data, * .auth_function = my_auth_function * }; * ssh_callbacks_init(&cb); * ssh_set_callbacks(session, &cb); * @endcode * * @param session The session to set the callback structure. * * @param cb The callback structure itself. * * @return SSH_OK on success, SSH_ERROR on error. */ LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb); /** * @brief SSH channel data callback. Called when data is available on a channel * @param session Current session handler * @param channel the actual channel * @param data the data that has been read on the channel * @param len the length of the data * @param is_stderr is 0 for stdout or 1 for stderr * @param userdata Userdata to be passed to the callback function. * @returns number of bytes processed by the callee. The remaining bytes will * be sent in the next callback message, when more data is available. */ typedef int (*ssh_channel_data_callback) (ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata); /** * @brief SSH channel eof callback. Called when a channel receives EOF * @param session Current session handler * @param channel the actual channel * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_eof_callback) (ssh_session session, ssh_channel channel, void *userdata); /** * @brief SSH channel close callback. Called when a channel is closed by remote peer * @param session Current session handler * @param channel the actual channel * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_close_callback) (ssh_session session, ssh_channel channel, void *userdata); /** * @brief SSH channel signal callback. Called when a channel has received a signal * @param session Current session handler * @param channel the actual channel * @param signal the signal name (without the SIG prefix) * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_signal_callback) (ssh_session session, ssh_channel channel, const char *signal, void *userdata); /** * @brief SSH channel exit status callback. Called when a channel has received an exit status * @param session Current session handler * @param channel the actual channel * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_exit_status_callback) (ssh_session session, ssh_channel channel, int exit_status, void *userdata); /** * @brief SSH channel exit signal callback. Called when a channel has received an exit signal * @param session Current session handler * @param channel the actual channel * @param signal the signal name (without the SIG prefix) * @param core a boolean telling wether a core has been dumped or not * @param errmsg the description of the exception * @param lang the language of the description (format: RFC 3066) * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_exit_signal_callback) (ssh_session session, ssh_channel channel, const char *signal, int core, const char *errmsg, const char *lang, void *userdata); /** * @brief SSH channel PTY request from a client. * @param channel the channel * @param term The type of terminal emulation * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels * @param pxheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied */ typedef int (*ssh_channel_pty_request_callback) (ssh_session session, ssh_channel channel, const char *term, int width, int height, int pxwidth, int pwheight, void *userdata); /** * @brief SSH channel Shell request from a client. * @param channel the channel * @param userdata Userdata to be passed to the callback function. * @returns 0 if the shell request is accepted * @returns 1 if the request is denied */ typedef int (*ssh_channel_shell_request_callback) (ssh_session session, ssh_channel channel, void *userdata); /** * @brief SSH auth-agent-request from the client. This request is * sent by a client when agent forwarding is available. * Server is free to ignore this callback, no answer is expected. * @param channel the channel * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_auth_agent_req_callback) (ssh_session session, ssh_channel channel, void *userdata); /** * @brief SSH X11 request from the client. This request is * sent by a client when X11 forwarding is requested(and available). * Server is free to ignore this callback, no answer is expected. * @param channel the channel * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_channel_x11_req_callback) (ssh_session session, ssh_channel channel, int single_connection, const char *auth_protocol, const char *auth_cookie, uint32_t screen_number, void *userdata); /** * @brief SSH channel PTY windows change (terminal size) from a client. * @param channel the channel * @param width width of the terminal, in characters * @param height height of the terminal, in characters * @param pxwidth width of the terminal, in pixels * @param pxheight height of the terminal, in pixels * @param userdata Userdata to be passed to the callback function. * @returns 0 if the pty request is accepted * @returns -1 if the request is denied */ typedef int (*ssh_channel_pty_window_change_callback) (ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata); /** * @brief SSH channel Exec request from a client. * @param channel the channel * @param command the shell command to be executed * @param userdata Userdata to be passed to the callback function. * @returns 0 if the exec request is accepted * @returns 1 if the request is denied */ typedef int (*ssh_channel_exec_request_callback) (ssh_session session, ssh_channel channel, const char *command, void *userdata); /** * @brief SSH channel environment request from a client. * @param channel the channel * @param env_name name of the environment value to be set * @param env_value value of the environment value to be set * @param userdata Userdata to be passed to the callback function. * @returns 0 if the env request is accepted * @returns 1 if the request is denied * @warning some environment variables can be dangerous if changed (e.g. * LD_PRELOAD) and should not be fulfilled. */ typedef int (*ssh_channel_env_request_callback) (ssh_session session, ssh_channel channel, const char *env_name, const char *env_value, void *userdata); /** * @brief SSH channel subsystem request from a client. * @param channel the channel * @param subsystem the subsystem required * @param userdata Userdata to be passed to the callback function. * @returns 0 if the subsystem request is accepted * @returns 1 if the request is denied */ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session, ssh_channel channel, const char *subsystem, void *userdata); /** * @brief SSH channel write will not block (flow control). * * @param channel the channel * * @param[in] bytes size of the remote window in bytes. Writing as much data * will not block. * * @param[in] userdata Userdata to be passed to the callback function. * * @returns 0 default return value (other return codes may be added in future). */ typedef int (*ssh_channel_write_wontblock_callback) (ssh_session session, ssh_channel channel, size_t bytes, void *userdata); struct ssh_channel_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ size_t size; /** * User-provided data. User is free to set anything he wants here */ void *userdata; /** * This functions will be called when there is data available. */ ssh_channel_data_callback channel_data_function; /** * This functions will be called when the channel has received an EOF. */ ssh_channel_eof_callback channel_eof_function; /** * This functions will be called when the channel has been closed by remote */ ssh_channel_close_callback channel_close_function; /** * This functions will be called when a signal has been received */ ssh_channel_signal_callback channel_signal_function; /** * This functions will be called when an exit status has been received */ ssh_channel_exit_status_callback channel_exit_status_function; /** * This functions will be called when an exit signal has been received */ ssh_channel_exit_signal_callback channel_exit_signal_function; /** * This function will be called when a client requests a PTY */ ssh_channel_pty_request_callback channel_pty_request_function; /** * This function will be called when a client requests a shell */ ssh_channel_shell_request_callback channel_shell_request_function; /** This function will be called when a client requests agent * authentication forwarding. */ ssh_channel_auth_agent_req_callback channel_auth_agent_req_function; /** This function will be called when a client requests X11 * forwarding. */ ssh_channel_x11_req_callback channel_x11_req_function; /** This function will be called when a client requests a * window change. */ ssh_channel_pty_window_change_callback channel_pty_window_change_function; /** This function will be called when a client requests a * command execution. */ ssh_channel_exec_request_callback channel_exec_request_function; /** This function will be called when a client requests an environment * variable to be set. */ ssh_channel_env_request_callback channel_env_request_function; /** This function will be called when a client requests a subsystem * (like sftp). */ ssh_channel_subsystem_request_callback channel_subsystem_request_function; /** This function will be called when the channel write is guaranteed * not to block. */ ssh_channel_write_wontblock_callback channel_write_wontblock_function; }; typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks; /** * @brief Set the channel callback functions. * * This functions sets the callback structure to use your own callback * functions for channel data and exceptions * * @code * struct ssh_channel_callbacks_struct cb = { * .userdata = data, * .channel_data_function = my_channel_data_function * }; * ssh_callbacks_init(&cb); * ssh_set_channel_callbacks(channel, &cb); * @endcode * * @param channel The channel to set the callback structure. * * @param cb The callback structure itself. * * @return SSH_OK on success, SSH_ERROR on error. * @warning this function will not replace existing callbacks but set the * new one atop of them. */ LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb); /** * @brief Add channel callback functions * * This function will add channel callback functions to the channel callback * list. * Callbacks missing from a callback structure will be probed in the next * on the list. * * @param channel The channel to set the callback structure. * * @param cb The callback structure itself. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_set_channel_callbacks */ LIBSSH_API int ssh_add_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb); /** * @brief Remove a channel callback. * * The channel has been added with ssh_add_channel_callbacks or * ssh_set_channel_callbacks in this case. * * @param channel The channel to remove the callback structure from. * * @param cb The callback structure to remove * * @returns SSH_OK on success, SSH_ERROR on error. */ LIBSSH_API int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb); /** @} */ /** @group libssh_threads * @{ */ typedef int (*ssh_thread_callback) (void **lock); typedef unsigned long (*ssh_thread_id_callback) (void); struct ssh_threads_callbacks_struct { const char *type; ssh_thread_callback mutex_init; ssh_thread_callback mutex_destroy; ssh_thread_callback mutex_lock; ssh_thread_callback mutex_unlock; ssh_thread_id_callback thread_id; }; /** * @brief Set the thread callbacks structure. * * This is necessary if your program is using libssh in a multithreaded fashion. * This function must be called first, outside of any threading context (in your * main() function for instance), before you call ssh_init(). * * @param[in] cb A pointer to a ssh_threads_callbacks_struct structure, which * contains the different callbacks to be set. * * @returns Always returns SSH_OK. * * @see ssh_threads_callbacks_struct * @see SSH_THREADS_PTHREAD * @bug libgcrypt 1.6 and bigger backend does not support custom callback. * Using anything else than pthreads here will fail. */ LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct *cb); /** * @brief Returns a pointer to the appropriate callbacks structure for the * environment, to be used with ssh_threads_set_callbacks. * * @returns A pointer to a ssh_threads_callbacks_struct to be used with * ssh_threads_set_callbacks. * * @see ssh_threads_set_callbacks */ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_default(void); /** * @brief Returns a pointer on the pthread threads callbacks, to be used with * ssh_threads_set_callbacks. * * @see ssh_threads_set_callbacks */ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void); /** * @brief Get the noop threads callbacks structure * * This can be used with ssh_threads_set_callbacks. These callbacks do nothing * and are being used by default. * * @return Always returns a valid pointer to the noop callbacks structure. * * @see ssh_threads_set_callbacks */ LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void); /** * @brief Set the logging callback function. * * @param[in] cb The callback to set. * * @return 0 on success, < 0 on errror. */ LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb); /** * @brief Get the pointer to the logging callback function. * * @return The pointer the the callback or NULL if none set. */ LIBSSH_API ssh_logging_callback ssh_get_log_callback(void); /** @} */ #ifdef __cplusplus } #endif #endif /*_SSH_CALLBACK_H */ /* @} */ ================================================ FILE: src/libssh/include/libssh/chacha.h ================================================ /* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ #ifndef CHACHA_H #define CHACHA_H struct chacha_ctx { uint32_t input[16]; }; #define CHACHA_MINKEYLEN 16 #define CHACHA_NONCELEN 8 #define CHACHA_CTRLEN 8 #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) #define CHACHA_BLOCKLEN 64 void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))) #endif ; void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))) #endif ; void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m, uint8_t *c, uint32_t bytes) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__buffer__, 2, 4))) __attribute__((__bounded__(__buffer__, 3, 4))) #endif ; #endif /* CHACHA_H */ ================================================ FILE: src/libssh/include/libssh/channels.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CHANNELS_H_ #define CHANNELS_H_ #include "libssh/priv.h" /** @internal * Describes the different possible states in a * outgoing (client) channel request */ enum ssh_channel_request_state_e { /** No request has been made */ SSH_CHANNEL_REQ_STATE_NONE = 0, /** A request has been made and answer is pending */ SSH_CHANNEL_REQ_STATE_PENDING, /** A request has been replied and accepted */ SSH_CHANNEL_REQ_STATE_ACCEPTED, /** A request has been replied and refused */ SSH_CHANNEL_REQ_STATE_DENIED, /** A request has been replied and an error happend */ SSH_CHANNEL_REQ_STATE_ERROR }; enum ssh_channel_state_e { SSH_CHANNEL_STATE_NOT_OPEN = 0, SSH_CHANNEL_STATE_OPENING, SSH_CHANNEL_STATE_OPEN_DENIED, SSH_CHANNEL_STATE_OPEN, SSH_CHANNEL_STATE_CLOSED }; /* The channel has been closed by the remote side */ #define SSH_CHANNEL_FLAG_CLOSED_REMOTE 0x0001 /* The channel has been closed locally */ #define SSH_CHANNEL_FLAG_CLOSED_LOCAL 0x0002 /* The channel has been freed by the calling program */ #define SSH_CHANNEL_FLAG_FREED_LOCAL 0x0004 /* the channel has not yet been bound to a remote one */ #define SSH_CHANNEL_FLAG_NOT_BOUND 0x0008 struct ssh_channel_struct { ssh_session session; /* SSH_SESSION pointer */ uint32_t local_channel; uint32_t local_window; int local_eof; uint32_t local_maxpacket; uint32_t remote_channel; uint32_t remote_window; int remote_eof; /* end of file received */ uint32_t remote_maxpacket; enum ssh_channel_state_e state; int delayed_close; int flags; ssh_buffer stdout_buffer; ssh_buffer stderr_buffer; void *userarg; int exit_status; enum ssh_channel_request_state_e request_state; struct ssh_list *callbacks; /* list of ssh_channel_callbacks */ /* counters */ ssh_counter counter; }; SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf); SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail); SSH_PACKET_CALLBACK(ssh_packet_channel_success); SSH_PACKET_CALLBACK(ssh_packet_channel_failure); SSH_PACKET_CALLBACK(ssh_request_success); SSH_PACKET_CALLBACK(ssh_request_denied); SSH_PACKET_CALLBACK(channel_rcv_change_window); SSH_PACKET_CALLBACK(channel_rcv_eof); SSH_PACKET_CALLBACK(channel_rcv_close); SSH_PACKET_CALLBACK(channel_rcv_request); SSH_PACKET_CALLBACK(channel_rcv_data); int channel_default_bufferize(ssh_channel channel, void *data, size_t len, bool is_stderr); int ssh_channel_flush(ssh_channel channel); uint32_t ssh_channel_new_id(ssh_session session); ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id); void ssh_channel_do_free(ssh_channel channel); int ssh_global_request(ssh_session session, const char *request, ssh_buffer buffer, int reply); #endif /* CHANNELS_H_ */ ================================================ FILE: src/libssh/include/libssh/config.h ================================================ /* * config.h - parse the ssh config file * * This file is part of the SSH Library * * Copyright (c) 2009-2018 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef LIBSSH_CONFIG_H_ #define LIBSSH_CONFIG_H_ enum ssh_config_opcode_e { /* Unknown opcode */ SOC_UNKNOWN = -3, /* Known and not applicable to libssh */ SOC_NA = -2, /* Known but not supported by current libssh version */ SOC_UNSUPPORTED = -1, SOC_HOST, SOC_MATCH, SOC_HOSTNAME, SOC_PORT, SOC_USERNAME, SOC_IDENTITY, SOC_CIPHERS, SOC_MACS, SOC_COMPRESSION, SOC_TIMEOUT, SOC_PROTOCOL, SOC_STRICTHOSTKEYCHECK, SOC_KNOWNHOSTS, SOC_PROXYCOMMAND, SOC_PROXYJUMP, SOC_GSSAPISERVERIDENTITY, SOC_GSSAPICLIENTIDENTITY, SOC_GSSAPIDELEGATECREDENTIALS, SOC_INCLUDE, SOC_BINDADDRESS, SOC_GLOBALKNOWNHOSTSFILE, SOC_LOGLEVEL, SOC_HOSTKEYALGORITHMS, SOC_KEXALGORITHMS, SOC_GSSAPIAUTHENTICATION, SOC_KBDINTERACTIVEAUTHENTICATION, SOC_PASSWORDAUTHENTICATION, SOC_PUBKEYAUTHENTICATION, SOC_PUBKEYACCEPTEDTYPES, SOC_REKEYLIMIT, SOC_MAX /* Keep this one last in the list */ }; #endif /* LIBSSH_CONFIG_H_ */ ================================================ FILE: src/libssh/include/libssh/config_parser.h ================================================ /* * config_parser.h - Common configuration file parser functions * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef CONFIG_PARSER_H_ #define CONFIG_PARSER_H_ char *ssh_config_get_cmd(char **str); char *ssh_config_get_token(char **str); long ssh_config_get_long(char **str, long notfound); const char *ssh_config_get_str_tok(char **str, const char *def); int ssh_config_get_yesno(char **str, int notfound); /* @brief Parse SSH URI in format [user@]host[:port] from the given string * * @param[in] tok String to parse * @param[out] username Pointer to the location, where the new username will * be stored or NULL if we do not care about the result. * @param[out] hostname Pointer to the location, where the new hostname will * be stored or NULL if we do not care about the result. * @param[out] port Pointer to the location, where the new port will * be stored or NULL if we do not care about the result. * * @returns SSH_OK if the provided string is in format of SSH URI, * SSH_ERROR on failure */ int ssh_config_parse_uri(const char *tok, char **username, char **hostname, char **port); #endif /* LIBSSH_CONFIG_H_ */ ================================================ FILE: src/libssh/include/libssh/crypto.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * crypto.h is an include file for internal cryptographic structures of libssh */ #ifndef _CRYPTO_H_ #define _CRYPTO_H_ #include #include "config.h" #ifdef HAVE_LIBGCRYPT #include #elif defined(HAVE_LIBMBEDCRYPTO) #include #endif #include "libssh/wrapper.h" #ifdef cbc_encrypt #undef cbc_encrypt #endif #ifdef cbc_decrypt #undef cbc_decrypt #endif #ifdef HAVE_OPENSSL_ECDH_H #include #endif #include "libssh/dh.h" #include "libssh/ecdh.h" #include "libssh/kex.h" #include "libssh/curve25519.h" #define DIGEST_MAX_LEN 64 #define AES_GCM_TAGLEN 16 #define AES_GCM_IVLEN 12 enum ssh_key_exchange_e { /* diffie-hellman-group1-sha1 */ SSH_KEX_DH_GROUP1_SHA1=1, /* diffie-hellman-group14-sha1 */ SSH_KEX_DH_GROUP14_SHA1, #ifdef WITH_GEX /* diffie-hellman-group-exchange-sha1 */ SSH_KEX_DH_GEX_SHA1, /* diffie-hellman-group-exchange-sha256 */ SSH_KEX_DH_GEX_SHA256, #endif /* WITH_GEX */ /* ecdh-sha2-nistp256 */ SSH_KEX_ECDH_SHA2_NISTP256, /* ecdh-sha2-nistp384 */ SSH_KEX_ECDH_SHA2_NISTP384, /* ecdh-sha2-nistp521 */ SSH_KEX_ECDH_SHA2_NISTP521, /* curve25519-sha256@libssh.org */ SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG, /* curve25519-sha256 */ SSH_KEX_CURVE25519_SHA256, /* diffie-hellman-group16-sha512 */ SSH_KEX_DH_GROUP16_SHA512, /* diffie-hellman-group18-sha512 */ SSH_KEX_DH_GROUP18_SHA512, /* diffie-hellman-group14-sha256 */ SSH_KEX_DH_GROUP14_SHA256, }; enum ssh_cipher_e { SSH_NO_CIPHER=0, #ifdef WITH_BLOWFISH_CIPHER SSH_BLOWFISH_CBC, #endif /* WITH_BLOWFISH_CIPHER */ SSH_3DES_CBC, SSH_AES128_CBC, SSH_AES192_CBC, SSH_AES256_CBC, SSH_AES128_CTR, SSH_AES192_CTR, SSH_AES256_CTR, SSH_AEAD_AES128_GCM, SSH_AEAD_AES256_GCM, SSH_AEAD_CHACHA20_POLY1305 }; struct dh_ctx; struct ssh_crypto_struct { bignum shared_secret; struct dh_ctx *dh_ctx; #ifdef WITH_GEX size_t dh_pmin; size_t dh_pn; size_t dh_pmax; /* preferred group parameters */ #endif /* WITH_GEX */ #ifdef HAVE_ECDH #ifdef HAVE_OPENSSL_ECC EC_KEY *ecdh_privkey; #elif defined HAVE_GCRYPT_ECC gcry_sexp_t ecdh_privkey; #elif defined HAVE_LIBMBEDCRYPTO mbedtls_ecp_keypair *ecdh_privkey; #endif ssh_string ecdh_client_pubkey; ssh_string ecdh_server_pubkey; #endif #ifdef HAVE_CURVE25519 ssh_curve25519_privkey curve25519_privkey; ssh_curve25519_pubkey curve25519_client_pubkey; ssh_curve25519_pubkey curve25519_server_pubkey; #endif ssh_string dh_server_signature; /* information used by dh_handshake. */ size_t digest_len; /* len of the two fields below */ unsigned char *session_id; unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */ unsigned char *encryptIV; unsigned char *decryptIV; unsigned char *decryptkey; unsigned char *encryptkey; unsigned char *encryptMAC; unsigned char *decryptMAC; unsigned char hmacbuf[DIGEST_MAX_LEN]; struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */ enum ssh_hmac_e in_hmac, out_hmac; /* the MAC algorithms used */ bool in_hmac_etm, out_hmac_etm; /* Whether EtM mode is used or not */ ssh_key server_pubkey; int do_compress_out; /* idem */ int do_compress_in; /* don't set them, set the option instead */ int delayed_compress_in; /* Use of zlib@openssh.org */ int delayed_compress_out; void *compress_out_ctx; /* don't touch it */ void *compress_in_ctx; /* really, don't */ /* kex sent by server, client, and mutually elected methods */ struct ssh_kex_struct server_kex; struct ssh_kex_struct client_kex; char *kex_methods[SSH_KEX_METHODS]; enum ssh_key_exchange_e kex_type; enum ssh_kdf_digest digest_type; /* Digest type for session keys derivation */ enum ssh_crypto_direction_e used; /* Is this crypto still used for either of directions? */ }; struct ssh_cipher_struct { const char *name; /* ssh name of the algorithm */ unsigned int blocksize; /* blocksize of the algo */ enum ssh_cipher_e ciphertype; uint32_t lenfield_blocksize; /* blocksize of the packet length field */ size_t keylen; /* length of the key structure */ #ifdef HAVE_LIBGCRYPT gcry_cipher_hd_t *key; unsigned char last_iv[AES_GCM_IVLEN]; #elif defined HAVE_LIBCRYPTO struct ssh_3des_key_schedule *des3_key; struct ssh_aes_key_schedule *aes_key; const EVP_CIPHER *cipher; EVP_CIPHER_CTX *ctx; #elif defined HAVE_LIBMBEDCRYPTO mbedtls_cipher_context_t encrypt_ctx; mbedtls_cipher_context_t decrypt_ctx; mbedtls_cipher_type_t type; #ifdef MBEDTLS_GCM_C mbedtls_gcm_context gcm_ctx; unsigned char last_iv[AES_GCM_IVLEN]; #endif /* MBEDTLS_GCM_C */ #endif struct chacha20_poly1305_keysched *chacha20_schedule; unsigned int keysize; /* bytes of key used. != keylen */ size_t tag_size; /* overhead required for tag */ /* Counters for rekeying initialization */ uint32_t packets; uint64_t blocks; /* Rekeying limit for the cipher or manually enforced */ uint64_t max_blocks; /* sets the new key for immediate use */ int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV); int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV); void (*encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len); void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len); void (*aead_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len, uint8_t *mac, uint64_t seq); int (*aead_decrypt_length)(struct ssh_cipher_struct *cipher, void *in, uint8_t *out, size_t len, uint64_t seq); int (*aead_decrypt)(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out, size_t encrypted_size, uint64_t seq); void (*cleanup)(struct ssh_cipher_struct *cipher); }; const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void); int sshkdf_derive_key(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len); #endif /* _CRYPTO_H_ */ ================================================ FILE: src/libssh/include/libssh/curve25519.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2013 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef CURVE25519_H_ #define CURVE25519_H_ #include "config.h" #include "libssh.h" #ifdef WITH_NACL #include #define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES #define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES #define crypto_scalarmult_base crypto_scalarmult_curve25519_base #define crypto_scalarmult crypto_scalarmult_curve25519 #else #define CURVE25519_PUBKEY_SIZE 32 #define CURVE25519_PRIVKEY_SIZE 32 int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); #endif /* WITH_NACL */ #ifdef HAVE_ECC #define HAVE_CURVE25519 1 #endif typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE]; typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE]; int ssh_client_curve25519_init(ssh_session session); #ifdef WITH_SERVER void ssh_server_curve25519_init(ssh_session session); #endif /* WITH_SERVER */ #endif /* CURVE25519_H_ */ ================================================ FILE: src/libssh/include/libssh/dh-gex.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2016 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef SRC_DH_GEX_H_ #define SRC_DH_GEX_H_ int ssh_client_dhgex_init(ssh_session session); #ifdef WITH_SERVER void ssh_server_dhgex_init(ssh_session session); #endif /* WITH_SERVER */ #endif /* SRC_DH_GEX_H_ */ ================================================ FILE: src/libssh/include/libssh/dh.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DH_H_ #define DH_H_ #include "config.h" #include "libssh/crypto.h" struct dh_ctx; #define DH_CLIENT_KEYPAIR 0 #define DH_SERVER_KEYPAIR 1 /* functions implemented by crypto backends */ int ssh_dh_init_common(struct ssh_crypto_struct *crypto); void ssh_dh_cleanup(struct ssh_crypto_struct *crypto); int ssh_dh_get_parameters(struct dh_ctx *ctx, const_bignum *modulus, const_bignum *generator); int ssh_dh_set_parameters(struct dh_ctx *ctx, const bignum modulus, const bignum generator); int ssh_dh_keypair_gen_keys(struct dh_ctx *ctx, int peer); int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, const_bignum *priv, const_bignum *pub); int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, const bignum priv, const bignum pub); int ssh_dh_compute_shared_secret(struct dh_ctx *ctx, int local, int remote, bignum *dest); void ssh_dh_debug_crypto(struct ssh_crypto_struct *c); /* common functions */ int ssh_dh_init(void); void ssh_dh_finalize(void); int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob); ssh_key ssh_dh_get_current_server_publickey(ssh_session session); int ssh_dh_get_current_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob); ssh_key ssh_dh_get_next_server_publickey(ssh_session session); int ssh_dh_get_next_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob); int ssh_client_dh_init(ssh_session session); #ifdef WITH_SERVER void ssh_server_dh_init(ssh_session session); #endif /* WITH_SERVER */ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet); int ssh_fallback_group(uint32_t pmax, bignum *p, bignum *g); bool ssh_dh_is_known_group(bignum modulus, bignum generator); #endif /* DH_H_ */ ================================================ FILE: src/libssh/include/libssh/ecdh.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2011 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ECDH_H_ #define ECDH_H_ #include "config.h" #include "libssh/callbacks.h" #ifdef HAVE_LIBCRYPTO #ifdef HAVE_OPENSSL_ECDH_H #ifdef HAVE_ECC #define HAVE_ECDH 1 #endif #endif /* HAVE_OPENSSL_ECDH_H */ #endif /* HAVE_LIBCRYPTO */ #ifdef HAVE_GCRYPT_ECC #define HAVE_ECDH 1 #endif #ifdef HAVE_LIBMBEDCRYPTO #define HAVE_ECDH 1 #endif extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks; /* Backend-specific functions. */ int ssh_client_ecdh_init(ssh_session session); int ecdh_build_k(ssh_session session); #ifdef WITH_SERVER extern struct ssh_packet_callbacks_struct ssh_ecdh_server_callbacks; void ssh_server_ecdh_init(ssh_session session); SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init); #endif /* WITH_SERVER */ #endif /* ECDH_H_ */ ================================================ FILE: src/libssh/include/libssh/ed25519.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2014 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ED25519_H_ #define ED25519_H_ #include "libssh/priv.h" /** * @defgroup ed25519 ed25519 API * @internal * @brief API for DJB's ed25519 * * @{ */ #define ED25519_PK_LEN 32 #define ED25519_SK_LEN 64 #define ED25519_SIG_LEN 64 typedef uint8_t ed25519_pubkey[ED25519_PK_LEN]; typedef uint8_t ed25519_privkey[ED25519_SK_LEN]; typedef uint8_t ed25519_signature[ED25519_SIG_LEN]; /** @internal * @brief generate an ed25519 key pair * @param[out] pk generated public key * @param[out] sk generated secret key * @return 0 on success, -1 on error. * */ int crypto_sign_ed25519_keypair(ed25519_pubkey pk, ed25519_privkey sk); /** @internal * @brief sign a message with ed25519 * @param[out] sm location to store the signed message. * Its length should be mlen + 64. * @param[out] smlen pointer to the size of the signed message * @param[in] m message to be signed * @param[in] mlen length of the message to be signed * @param[in] sk secret key to sign the message with * @return 0 on success. */ int crypto_sign_ed25519( unsigned char *sm, uint64_t *smlen, const unsigned char *m, uint64_t mlen, const ed25519_privkey sk); /** @internal * @brief "open" and verify the signature of a signed message * @param[out] m location to store the verified message. * Its length should be equal to smlen. * @param[out] mlen pointer to the size of the verified message * @param[in] sm signed message to verify * @param[in] smlen length of the signed message to verify * @param[in] pk public key used to sign the message * @returns 0 on success (supposedly). */ int crypto_sign_ed25519_open( unsigned char *m, uint64_t *mlen, const unsigned char *sm, uint64_t smlen, const ed25519_pubkey pk); /** @} */ #endif /* ED25519_H_ */ ================================================ FILE: src/libssh/include/libssh/fe25519.h ================================================ /* $OpenBSD: fe25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.h */ #ifndef FE25519_H #define FE25519_H #include "libssh/priv.h" #define fe25519 crypto_sign_ed25519_ref_fe25519 #define fe25519_freeze crypto_sign_ed25519_ref_fe25519_freeze #define fe25519_unpack crypto_sign_ed25519_ref_fe25519_unpack #define fe25519_pack crypto_sign_ed25519_ref_fe25519_pack #define fe25519_iszero crypto_sign_ed25519_ref_fe25519_iszero #define fe25519_iseq_vartime crypto_sign_ed25519_ref_fe25519_iseq_vartime #define fe25519_cmov crypto_sign_ed25519_ref_fe25519_cmov #define fe25519_setone crypto_sign_ed25519_ref_fe25519_setone #define fe25519_setzero crypto_sign_ed25519_ref_fe25519_setzero #define fe25519_neg crypto_sign_ed25519_ref_fe25519_neg #define fe25519_getparity crypto_sign_ed25519_ref_fe25519_getparity #define fe25519_add crypto_sign_ed25519_ref_fe25519_add #define fe25519_sub crypto_sign_ed25519_ref_fe25519_sub #define fe25519_mul crypto_sign_ed25519_ref_fe25519_mul #define fe25519_square crypto_sign_ed25519_ref_fe25519_square #define fe25519_invert crypto_sign_ed25519_ref_fe25519_invert #define fe25519_pow2523 crypto_sign_ed25519_ref_fe25519_pow2523 typedef struct { uint32_t v[32]; } fe25519; void fe25519_freeze(fe25519 *r); void fe25519_unpack(fe25519 *r, const unsigned char x[32]); void fe25519_pack(unsigned char r[32], const fe25519 *x); uint32_t fe25519_iszero(const fe25519 *x); int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y); void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b); void fe25519_setone(fe25519 *r); void fe25519_setzero(fe25519 *r); void fe25519_neg(fe25519 *r, const fe25519 *x); unsigned char fe25519_getparity(const fe25519 *x); void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y); void fe25519_square(fe25519 *r, const fe25519 *x); void fe25519_invert(fe25519 *r, const fe25519 *x); void fe25519_pow2523(fe25519 *r, const fe25519 *x); #endif ================================================ FILE: src/libssh/include/libssh/ge25519.h ================================================ /* $OpenBSD: ge25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519.h */ #ifndef GE25519_H #define GE25519_H #include "fe25519.h" #include "sc25519.h" #define ge25519 crypto_sign_ed25519_ref_ge25519 #define ge25519_base crypto_sign_ed25519_ref_ge25519_base #define ge25519_unpackneg_vartime crypto_sign_ed25519_ref_unpackneg_vartime #define ge25519_pack crypto_sign_ed25519_ref_pack #define ge25519_isneutral_vartime crypto_sign_ed25519_ref_isneutral_vartime #define ge25519_double_scalarmult_vartime crypto_sign_ed25519_ref_double_scalarmult_vartime #define ge25519_scalarmult_base crypto_sign_ed25519_ref_scalarmult_base typedef struct { fe25519 x; fe25519 y; fe25519 z; fe25519 t; } ge25519; extern const ge25519 ge25519_base; int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]); void ge25519_pack(unsigned char r[32], const ge25519 *p); int ge25519_isneutral_vartime(const ge25519 *p); void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const ge25519 *p2, const sc25519 *s2); void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s); #endif ================================================ FILE: src/libssh/include/libssh/gssapi.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2013 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GSSAPI_H_ #define GSSAPI_H_ #include "config.h" #include "session.h" /* all OID begin with the tag identifier + length */ #define SSH_OID_TAG 06 typedef struct ssh_gssapi_struct *ssh_gssapi; #ifdef WITH_SERVER int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic); #endif /* WITH_SERVER */ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client); SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response); int ssh_gssapi_auth_mic(ssh_session session); #endif /* GSSAPI_H */ ================================================ FILE: src/libssh/include/libssh/kex.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KEX_H_ #define KEX_H_ #include "libssh/priv.h" #include "libssh/callbacks.h" #define SSH_KEX_METHODS 10 struct ssh_kex_struct { unsigned char cookie[16]; char *methods[SSH_KEX_METHODS]; }; SSH_PACKET_CALLBACK(ssh_packet_kexinit); int ssh_send_kex(ssh_session session, int server_kex); void ssh_list_kex(struct ssh_kex_struct *kex); int ssh_set_client_kex(ssh_session session); int ssh_kex_select_methods(ssh_session session); int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name); char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list); char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list); char **ssh_space_tokenize(const char *chain); int ssh_get_kex1(ssh_session session); char *ssh_find_matching(const char *in_d, const char *what_d); const char *ssh_kex_get_supported_method(uint32_t algo); const char *ssh_kex_get_default_methods(uint32_t algo); const char *ssh_kex_get_fips_methods(uint32_t algo); const char *ssh_kex_get_description(uint32_t algo); char *ssh_client_select_hostkeys(ssh_session session); int ssh_send_rekex(ssh_session session); int server_set_kex(ssh_session session); int ssh_make_sessionid(ssh_session session); /* add data for the final cookie */ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie); int ssh_hashbufout_add_cookie(ssh_session session); int ssh_generate_session_keys(ssh_session session); #endif /* KEX_H_ */ ================================================ FILE: src/libssh/include/libssh/keys.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KEYS_H_ #define KEYS_H_ #include "config.h" #include "libssh/libssh.h" #include "libssh/wrapper.h" struct ssh_public_key_struct { int type; const char *type_c; /* Don't free it ! it is static */ #if defined(HAVE_LIBGCRYPT) gcry_sexp_t dsa_pub; gcry_sexp_t rsa_pub; #elif defined(HAVE_LIBCRYPTO) DSA *dsa_pub; RSA *rsa_pub; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa_pub; void *dsa_pub; #endif }; struct ssh_private_key_struct { int type; #if defined(HAVE_LIBGCRYPT) gcry_sexp_t dsa_priv; gcry_sexp_t rsa_priv; #elif defined(HAVE_LIBCRYPTO) DSA *dsa_priv; RSA *rsa_priv; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa_priv; void *dsa_priv; #endif }; const char *ssh_type_to_char(int type); int ssh_type_from_name(const char *name); ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s); #endif /* KEYS_H_ */ ================================================ FILE: src/libssh/include/libssh/knownhosts.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 20014 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SSH_KNOWNHOSTS_H_ #define SSH_KNOWNHOSTS_H_ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session); char *ssh_known_hosts_get_algorithms_names(ssh_session session); enum ssh_known_hosts_e ssh_session_get_known_hosts_entry_file(ssh_session session, const char *filename, struct ssh_knownhosts_entry **pentry); #endif /* SSH_KNOWNHOSTS_H_ */ ================================================ FILE: src/libssh/include/libssh/legacy.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Since libssh.h includes legacy.h, it's important that libssh.h is included * first. we don't define LEGACY_H now because we want it to be defined when * included from libssh.h * All function calls declared in this header are deprecated and meant to be * removed in future. */ #ifndef LEGACY_H_ #define LEGACY_H_ typedef struct ssh_private_key_struct* ssh_private_key; typedef struct ssh_public_key_struct* ssh_public_key; LIBSSH_API int ssh_auth_list(ssh_session session); LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey); LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey); LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username, ssh_public_key publickey); LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase); LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username, const char *filename, const char *passphrase); SSH_DEPRECATED LIBSSH_API void buffer_free(ssh_buffer buffer); SSH_DEPRECATED LIBSSH_API void *buffer_get(ssh_buffer buffer); SSH_DEPRECATED LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer); SSH_DEPRECATED LIBSSH_API ssh_buffer buffer_new(void); SSH_DEPRECATED LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms); SSH_DEPRECATED LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows); SSH_DEPRECATED LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms); SSH_DEPRECATED LIBSSH_API int channel_close(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port); SSH_DEPRECATED LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port); SSH_DEPRECATED LIBSSH_API void channel_free(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_get_exit_status(ssh_channel channel); SSH_DEPRECATED LIBSSH_API ssh_session channel_get_session(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_is_closed(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_is_eof(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_is_open(ssh_channel channel); SSH_DEPRECATED LIBSSH_API ssh_channel channel_new(ssh_session session); SSH_DEPRECATED LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport); SSH_DEPRECATED LIBSSH_API int channel_open_session(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr); SSH_DEPRECATED LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr); SSH_DEPRECATED LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count, int is_stderr); SSH_DEPRECATED LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count, int is_stderr); SSH_DEPRECATED LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value); SSH_DEPRECATED LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd); SSH_DEPRECATED LIBSSH_API int channel_request_pty(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term, int cols, int rows); SSH_DEPRECATED LIBSSH_API int channel_request_shell(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum); SSH_DEPRECATED LIBSSH_API int channel_request_sftp(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem); SSH_DEPRECATED LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol, const char *cookie, int screen_number); SSH_DEPRECATED LIBSSH_API int channel_send_eof(ssh_channel channel); SSH_DEPRECATED LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout); SSH_DEPRECATED LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking); SSH_DEPRECATED LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len); LIBSSH_API void privatekey_free(ssh_private_key prv); LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename, int type, const char *passphrase); LIBSSH_API void publickey_free(ssh_public_key key); LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file, ssh_string pubkey, int type); LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename, int *type); LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv); LIBSSH_API ssh_string publickey_to_string(ssh_public_key key); LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile, ssh_string *publickey, int *type); LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey); LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session); LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype); LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg); SSH_DEPRECATED LIBSSH_API void string_burn(ssh_string str); SSH_DEPRECATED LIBSSH_API ssh_string string_copy(ssh_string str); SSH_DEPRECATED LIBSSH_API void *string_data(ssh_string str); SSH_DEPRECATED LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len); SSH_DEPRECATED LIBSSH_API void string_free(ssh_string str); SSH_DEPRECATED LIBSSH_API ssh_string string_from_char(const char *what); SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str); SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size); SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str); #endif /* LEGACY_H_ */ ================================================ FILE: src/libssh/include/libssh/libcrypto.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBCRYPTO_H_ #define LIBCRYPTO_H_ #include "config.h" #ifdef HAVE_LIBCRYPTO #include #include #include #include #include #include #include typedef EVP_MD_CTX* SHACTX; typedef EVP_MD_CTX* SHA256CTX; typedef EVP_MD_CTX* SHA384CTX; typedef EVP_MD_CTX* SHA512CTX; typedef EVP_MD_CTX* MD5CTX; typedef HMAC_CTX* HMACCTX; #ifdef HAVE_ECC typedef EVP_MD_CTX *EVPCTX; #else typedef void *EVPCTX; #endif #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH #define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH #define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH #ifdef MD5_DIGEST_LEN #undef MD5_DIGEST_LEN #endif #define MD5_DIGEST_LEN MD5_DIGEST_LENGTH #ifdef HAVE_OPENSSL_ECC #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE #endif #include #include #define OPENSSL_0_9_7b 0x0090702fL #if (OPENSSL_VERSION_NUMBER <= OPENSSL_0_9_7b) #define BROKEN_AES_CTR #endif typedef BIGNUM* bignum; typedef const BIGNUM* const_bignum; typedef BN_CTX* bignum_CTX; #define bignum_new() BN_new() #define bignum_safe_free(num) do { \ if ((num) != NULL) { \ BN_clear_free((num)); \ (num)=NULL; \ } \ } while(0) #define bignum_set_word(bn,n) BN_set_word(bn,n) #define bignum_bin2bn(data, datalen, dest) \ do { \ (*dest) = BN_new(); \ if ((*dest) != NULL) { \ BN_bin2bn(data,datalen,(*dest)); \ } \ } while(0) #define bignum_bn2dec(num) BN_bn2dec(num) #define bignum_dec2bn(data, bn) BN_dec2bn(bn, data) #define bignum_hex2bn(data, bn) BN_hex2bn(bn, data) #define bignum_bn2hex(num, dest) (*dest)=(unsigned char *)BN_bn2hex(num) #define bignum_rand(rnd, bits) BN_rand(rnd, bits, 0, 1) #define bignum_rand_range(rnd, max) BN_rand_range(rnd, max) #define bignum_ctx_new() BN_CTX_new() #define bignum_ctx_free(num) BN_CTX_free(num) #define bignum_ctx_invalid(ctx) ((ctx) == NULL) #define bignum_mod_exp(dest,generator,exp,modulo,ctx) BN_mod_exp(dest,generator,exp,modulo,ctx) #define bignum_add(dest, a, b) BN_add(dest, a, b) #define bignum_sub(dest, a, b) BN_sub(dest, a, b) #define bignum_mod(dest, a, b, ctx) BN_mod(dest, a, b, ctx) #define bignum_num_bytes(num) (size_t)BN_num_bytes(num) #define bignum_num_bits(num) (size_t)BN_num_bits(num) #define bignum_is_bit_set(num,bit) BN_is_bit_set(num, (int)bit) #define bignum_bn2bin(num,len, ptr) BN_bn2bin(num, ptr) #define bignum_cmp(num1,num2) BN_cmp(num1,num2) #define bignum_rshift1(dest, src) BN_rshift1(dest, src) #define bignum_dup(orig, dest) do { \ if (*(dest) == NULL) { \ *(dest) = BN_dup(orig); \ } else { \ BN_copy(*(dest), orig); \ } \ } while(0) /* Returns true if the OpenSSL is operating in FIPS mode */ #ifdef HAVE_OPENSSL_FIPS_MODE #define ssh_fips_mode() (FIPS_mode() != 0) #else #define ssh_fips_mode() false #endif #endif /* HAVE_LIBCRYPTO */ #endif /* LIBCRYPTO_H_ */ ================================================ FILE: src/libssh/include/libssh/libgcrypt.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBGCRYPT_H_ #define LIBGCRYPT_H_ #include "config.h" #ifdef HAVE_LIBGCRYPT #include typedef gcry_md_hd_t SHACTX; typedef gcry_md_hd_t SHA256CTX; typedef gcry_md_hd_t SHA384CTX; typedef gcry_md_hd_t SHA512CTX; typedef gcry_md_hd_t MD5CTX; typedef gcry_md_hd_t HMACCTX; typedef gcry_md_hd_t EVPCTX; #define SHA_DIGEST_LENGTH 20 #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define MD5_DIGEST_LEN 16 #define SHA256_DIGEST_LENGTH 32 #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH #define SHA384_DIGEST_LENGTH 48 #define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH #define SHA512_DIGEST_LENGTH 64 #define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 #endif #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE typedef gcry_mpi_t bignum; typedef const struct gcry_mpi *const_bignum; typedef void* bignum_CTX; /* Constants for curves. */ #define NID_gcrypt_nistp256 0 #define NID_gcrypt_nistp384 1 #define NID_gcrypt_nistp521 2 /* missing gcrypt functions */ int ssh_gcry_dec2bn(bignum *bn, const char *data); char *ssh_gcry_bn2dec(bignum bn); int ssh_gcry_rand_range(bignum rnd, bignum max); #define bignum_new() gcry_mpi_new(0) #define bignum_safe_free(num) do { \ if ((num) != NULL) { \ gcry_mpi_release((num)); \ (num)=NULL; \ } \ } while (0) #define bignum_free(num) gcry_mpi_release(num) #define bignum_ctx_new() NULL #define bignum_ctx_free(ctx) do {(ctx) = NULL;} while(0) #define bignum_ctx_invalid(ctx) (ctx != NULL) #define bignum_set_word(bn,n) (gcry_mpi_set_ui(bn,n)!=NULL ? 1 : 0) #define bignum_bin2bn(data,datalen,dest) gcry_mpi_scan(dest,GCRYMPI_FMT_USG,data,datalen,NULL) #define bignum_bn2dec(num) ssh_gcry_bn2dec(num) #define bignum_dec2bn(num, data) ssh_gcry_dec2bn(data, num) #define bignum_bn2hex(num, data) \ gcry_mpi_aprint(GCRYMPI_FMT_HEX, data, NULL, (const gcry_mpi_t)num) #define bignum_hex2bn(data, num) (gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,0,NULL)==0?1:0) #define bignum_rand(num,bits) 1,gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0) #define bignum_mod_exp(dest,generator,exp,modulo, ctx) 1,gcry_mpi_powm(dest,generator,exp,modulo) #define bignum_num_bits(num) gcry_mpi_get_nbits(num) #define bignum_num_bytes(num) ((gcry_mpi_get_nbits(num)+7)/8) #define bignum_is_bit_set(num,bit) gcry_mpi_test_bit(num,bit) #define bignum_bn2bin(num,datalen,data) gcry_mpi_print(GCRYMPI_FMT_USG,data,datalen,NULL,num) #define bignum_cmp(num1,num2) gcry_mpi_cmp(num1,num2) #define bignum_rshift1(dest, src) gcry_mpi_rshift (dest, src, 1) #define bignum_add(dst, a, b) gcry_mpi_add(dst, a, b) #define bignum_sub(dst, a, b) gcry_mpi_sub(dst, a, b) #define bignum_mod(dst, a, b, ctx) 1,gcry_mpi_mod(dst, a, b) #define bignum_rand_range(rnd, max) ssh_gcry_rand_range(rnd, max); #define bignum_dup(orig, dest) do { \ if (*(dest) == NULL) { \ *(dest) = gcry_mpi_copy(orig); \ } else { \ gcry_mpi_set(*(dest), orig); \ } \ } while(0) /* Helper functions for data conversions. */ /* Extract an MPI from the given s-expression SEXP named NAME which is encoded using INFORMAT and store it in a newly allocated ssh_string encoded using OUTFORMAT. */ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, const char *name, enum gcry_mpi_format informat, enum gcry_mpi_format outformat); #define ssh_fips_mode() false #endif /* HAVE_LIBGCRYPT */ #endif /* LIBGCRYPT_H_ */ ================================================ FILE: src/libssh/include/libssh/libmbedcrypto.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2017 Sartura d.o.o. * * Author: Juraj Vijtiuk * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef LIBMBEDCRYPTO_H_ #define LIBMBEDCRYPTO_H_ #include "config.h" #ifdef HAVE_LIBMBEDCRYPTO #include #include #include #include #include #include typedef mbedtls_md_context_t *SHACTX; typedef mbedtls_md_context_t *SHA256CTX; typedef mbedtls_md_context_t *SHA384CTX; typedef mbedtls_md_context_t *SHA512CTX; typedef mbedtls_md_context_t *MD5CTX; typedef mbedtls_md_context_t *HMACCTX; typedef mbedtls_md_context_t *EVPCTX; #define SHA_DIGEST_LENGTH 20 #define SHA_DIGEST_LEN SHA_DIGEST_LENGTH #define MD5_DIGEST_LEN 16 #define SHA256_DIGEST_LENGTH 32 #define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH #define SHA384_DIGEST_LENGTH 48 #define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH #define SHA512_DIGEST_LENGTH 64 #define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 #endif #define EVP_DIGEST_LEN EVP_MAX_MD_SIZE typedef mbedtls_mpi *bignum; typedef const mbedtls_mpi *const_bignum; typedef void* bignum_CTX; /* Constants for curves */ #define NID_mbedtls_nistp256 0 #define NID_mbedtls_nistp384 1 #define NID_mbedtls_nistp521 2 struct mbedtls_ecdsa_sig { bignum r; bignum s; }; bignum ssh_mbedcry_bn_new(void); void ssh_mbedcry_bn_free(bignum num); unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix); int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom); int ssh_mbedcry_is_bit_set(bignum num, size_t pos); int ssh_mbedcry_rand_range(bignum dest, bignum max); int ssh_mbedcry_hex2bn(bignum *dest, char *data); #define bignum_new() ssh_mbedcry_bn_new() #define bignum_safe_free(num) do { \ if ((num) != NULL) { \ ssh_mbedcry_bn_free(num); \ (num)=NULL; \ } \ } while(0) #define bignum_ctx_new() NULL #define bignum_ctx_free(num) do {(num) = NULL;} while(0) #define bignum_ctx_invalid(ctx) (ctx == NULL?0:1) #define bignum_set_word(bn, n) (mbedtls_mpi_lset(bn, n)==0?1:0) /* TODO fix overflow/underflow */ #define bignum_bin2bn(data, datalen, bn) do { \ *(bn) = bignum_new(); \ if (*(bn) != NULL) { \ mbedtls_mpi_read_binary(*(bn), data, datalen); \ } \ } while(0) #define bignum_bn2dec(num) ssh_mbedcry_bn2num(num, 10) #define bignum_dec2bn(data, bn) mbedtls_mpi_read_string(bn, 10, data) #define bignum_bn2hex(num, dest) (*dest)=ssh_mbedcry_bn2num(num, 16) #define bignum_hex2bn(data, dest) ssh_mbedcry_hex2bn(dest, data) #define bignum_rand(rnd, bits) ssh_mbedcry_rand((rnd), (bits), 0, 1) #define bignum_rand_range(rnd, max) ssh_mbedcry_rand_range(rnd, max) #define bignum_mod_exp(dest, generator, exp, modulo, ctx) \ (mbedtls_mpi_exp_mod(dest, generator, exp, modulo, NULL)==0?1:0) #define bignum_add(dest, a, b) mbedtls_mpi_add_mpi(dest, a, b) #define bignum_sub(dest, a, b) mbedtls_mpi_sub_mpi(dest, a, b) #define bignum_mod(dest, a, b, ctx) \ (mbedtls_mpi_mod_mpi(dest, a, b) == 0 ? 1 : 0) #define bignum_num_bytes(num) mbedtls_mpi_size(num) #define bignum_num_bits(num) mbedtls_mpi_bitlen(num) #define bignum_is_bit_set(num, bit) ssh_mbedcry_is_bit_set(num, bit) #define bignum_bn2bin(num, len, ptr) mbedtls_mpi_write_binary(num, ptr, \ mbedtls_mpi_size(num)) #define bignum_cmp(num1, num2) mbedtls_mpi_cmp_mpi(num1, num2) #define bignum_rshift1(dest, src) mbedtls_mpi_copy(dest, src), mbedtls_mpi_shift_r(dest, 1) #define bignum_dup(orig, dest) do { \ if (*(dest) == NULL) { \ *(dest) = bignum_new(); \ } \ if (*(dest) != NULL) { \ mbedtls_mpi_copy(orig, *(dest)); \ } \ } while(0) mbedtls_ctr_drbg_context *ssh_get_mbedtls_ctr_drbg_context(void); int ssh_mbedtls_random(void *where, int len, int strong); ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const mbedtls_ecp_point *p); #define ssh_fips_mode() false #endif /* HAVE_LIBMBEDCRYPTO */ #endif /* LIBMBEDCRYPTO_H_ */ ================================================ FILE: src/libssh/include/libssh/libssh.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LIBSSH_H #define _LIBSSH_H #include #if defined _WIN32 || defined __CYGWIN__ #ifdef LIBSSH_STATIC #define LIBSSH_API #else #ifdef LIBSSH_EXPORTS #ifdef __GNUC__ #define LIBSSH_API __attribute__((dllexport)) #else #define LIBSSH_API __declspec(dllexport) #endif #else #ifdef __GNUC__ #define LIBSSH_API __attribute__((dllimport)) #else #define LIBSSH_API __declspec(dllimport) #endif #endif #endif #else #if __GNUC__ >= 4 && !defined(__OS2__) #define LIBSSH_API __attribute__((visibility("default"))) #else #define LIBSSH_API #endif #endif #ifdef _MSC_VER /* Visual Studio hasn't inttypes.h so it doesn't know uint32_t */ typedef int int32_t; typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; typedef unsigned long long uint64_t; typedef int mode_t; #else /* _MSC_VER */ #include #include #include #endif /* _MSC_VER */ #ifdef _WIN32 #include #else /* _WIN32 */ #include /* for fd_set * */ #include #endif /* _WIN32 */ #define SSH_STRINGIFY(s) SSH_TOSTRING(s) #define SSH_TOSTRING(s) #s /* GCC have printf type attribute check. */ #ifdef __GNUC__ #define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b))) #else #define PRINTF_ATTRIBUTE(a,b) #endif /* __GNUC__ */ #ifdef __GNUC__ #define SSH_DEPRECATED __attribute__ ((deprecated)) #else #define SSH_DEPRECATED #endif #ifdef __cplusplus extern "C" { #endif struct ssh_counter_struct { uint64_t in_bytes; uint64_t out_bytes; uint64_t in_packets; uint64_t out_packets; }; typedef struct ssh_counter_struct *ssh_counter; typedef struct ssh_agent_struct* ssh_agent; typedef struct ssh_buffer_struct* ssh_buffer; typedef struct ssh_channel_struct* ssh_channel; typedef struct ssh_message_struct* ssh_message; typedef struct ssh_pcap_file_struct* ssh_pcap_file; typedef struct ssh_key_struct* ssh_key; typedef struct ssh_scp_struct* ssh_scp; typedef struct ssh_session_struct* ssh_session; typedef struct ssh_string_struct* ssh_string; typedef struct ssh_event_struct* ssh_event; typedef struct ssh_connector_struct * ssh_connector; typedef void* ssh_gssapi_creds; /* Socket type */ #ifdef _WIN32 #ifndef socket_t typedef SOCKET socket_t; #endif /* socket_t */ #else /* _WIN32 */ #ifndef socket_t typedef int socket_t; #endif #endif /* _WIN32 */ #define SSH_INVALID_SOCKET ((socket_t) -1) /* the offsets of methods */ enum ssh_kex_types_e { SSH_KEX=0, SSH_HOSTKEYS, SSH_CRYPT_C_S, SSH_CRYPT_S_C, SSH_MAC_C_S, SSH_MAC_S_C, SSH_COMP_C_S, SSH_COMP_S_C, SSH_LANG_C_S, SSH_LANG_S_C }; #define SSH_CRYPT 2 #define SSH_MAC 3 #define SSH_COMP 4 #define SSH_LANG 5 enum ssh_auth_e { SSH_AUTH_SUCCESS=0, SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, SSH_AUTH_INFO, SSH_AUTH_AGAIN, SSH_AUTH_ERROR=-1 }; /* auth flags */ #define SSH_AUTH_METHOD_UNKNOWN 0x0000u #define SSH_AUTH_METHOD_NONE 0x0001u #define SSH_AUTH_METHOD_PASSWORD 0x0002u #define SSH_AUTH_METHOD_PUBLICKEY 0x0004u #define SSH_AUTH_METHOD_HOSTBASED 0x0008u #define SSH_AUTH_METHOD_INTERACTIVE 0x0010u #define SSH_AUTH_METHOD_GSSAPI_MIC 0x0020u /* messages */ enum ssh_requests_e { SSH_REQUEST_AUTH=1, SSH_REQUEST_CHANNEL_OPEN, SSH_REQUEST_CHANNEL, SSH_REQUEST_SERVICE, SSH_REQUEST_GLOBAL }; enum ssh_channel_type_e { SSH_CHANNEL_UNKNOWN=0, SSH_CHANNEL_SESSION, SSH_CHANNEL_DIRECT_TCPIP, SSH_CHANNEL_FORWARDED_TCPIP, SSH_CHANNEL_X11, SSH_CHANNEL_AUTH_AGENT }; enum ssh_channel_requests_e { SSH_CHANNEL_REQUEST_UNKNOWN=0, SSH_CHANNEL_REQUEST_PTY, SSH_CHANNEL_REQUEST_EXEC, SSH_CHANNEL_REQUEST_SHELL, SSH_CHANNEL_REQUEST_ENV, SSH_CHANNEL_REQUEST_SUBSYSTEM, SSH_CHANNEL_REQUEST_WINDOW_CHANGE, SSH_CHANNEL_REQUEST_X11 }; enum ssh_global_requests_e { SSH_GLOBAL_REQUEST_UNKNOWN=0, SSH_GLOBAL_REQUEST_TCPIP_FORWARD, SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD, SSH_GLOBAL_REQUEST_KEEPALIVE }; enum ssh_publickey_state_e { SSH_PUBLICKEY_STATE_ERROR=-1, SSH_PUBLICKEY_STATE_NONE=0, SSH_PUBLICKEY_STATE_VALID=1, SSH_PUBLICKEY_STATE_WRONG=2 }; /* Status flags */ /** Socket is closed */ #define SSH_CLOSED 0x01 /** Reading to socket won't block */ #define SSH_READ_PENDING 0x02 /** Session was closed due to an error */ #define SSH_CLOSED_ERROR 0x04 /** Output buffer not empty */ #define SSH_WRITE_PENDING 0x08 enum ssh_server_known_e { SSH_SERVER_ERROR=-1, SSH_SERVER_NOT_KNOWN=0, SSH_SERVER_KNOWN_OK, SSH_SERVER_KNOWN_CHANGED, SSH_SERVER_FOUND_OTHER, SSH_SERVER_FILE_NOT_FOUND }; enum ssh_known_hosts_e { /** * There had been an error checking the host. */ SSH_KNOWN_HOSTS_ERROR = -2, /** * The known host file does not exist. The host is thus unknown. File will * be created if host key is accepted. */ SSH_KNOWN_HOSTS_NOT_FOUND = -1, /** * The server is unknown. User should confirm the public key hash is * correct. */ SSH_KNOWN_HOSTS_UNKNOWN = 0, /** * The server is known and has not changed. */ SSH_KNOWN_HOSTS_OK, /** * The server key has changed. Either you are under attack or the * administrator changed the key. You HAVE to warn the user about a * possible attack. */ SSH_KNOWN_HOSTS_CHANGED, /** * The server gave use a key of a type while we had an other type recorded. * It is a possible attack. */ SSH_KNOWN_HOSTS_OTHER, }; #ifndef MD5_DIGEST_LEN #define MD5_DIGEST_LEN 16 #endif /* errors */ enum ssh_error_types_e { SSH_NO_ERROR=0, SSH_REQUEST_DENIED, SSH_FATAL, SSH_EINTR }; /* some types for keys */ enum ssh_keytypes_e{ SSH_KEYTYPE_UNKNOWN=0, SSH_KEYTYPE_DSS=1, SSH_KEYTYPE_RSA, SSH_KEYTYPE_RSA1, SSH_KEYTYPE_ECDSA, /* deprecated */ SSH_KEYTYPE_ED25519, SSH_KEYTYPE_DSS_CERT01, SSH_KEYTYPE_RSA_CERT01, SSH_KEYTYPE_ECDSA_P256, SSH_KEYTYPE_ECDSA_P384, SSH_KEYTYPE_ECDSA_P521, SSH_KEYTYPE_ECDSA_P256_CERT01, SSH_KEYTYPE_ECDSA_P384_CERT01, SSH_KEYTYPE_ECDSA_P521_CERT01, SSH_KEYTYPE_ED25519_CERT01, }; enum ssh_keycmp_e { SSH_KEY_CMP_PUBLIC = 0, SSH_KEY_CMP_PRIVATE }; #define SSH_ADDRSTRLEN 46 struct ssh_knownhosts_entry { char *hostname; char *unparsed; ssh_key publickey; char *comment; }; /* Error return codes */ #define SSH_OK 0 /* No error */ #define SSH_ERROR -1 /* Error of some kind */ #define SSH_AGAIN -2 /* The nonblocking call must be repeated */ #define SSH_EOF -127 /* We have already a eof */ /** * @addtogroup libssh_log * * @{ */ enum { /** No logging at all */ SSH_LOG_NOLOG=0, /** Only warnings */ SSH_LOG_WARNING, /** High level protocol information */ SSH_LOG_PROTOCOL, /** Lower level protocol infomations, packet level */ SSH_LOG_PACKET, /** Every function path */ SSH_LOG_FUNCTIONS }; /** @} */ #define SSH_LOG_RARE SSH_LOG_WARNING /** * @name Logging levels * * @brief Debug levels for logging. * @{ */ /** No logging at all */ #define SSH_LOG_NONE 0 /** Show only warnings */ #define SSH_LOG_WARN 1 /** Get some information what's going on */ #define SSH_LOG_INFO 2 /** Get detailed debuging information **/ #define SSH_LOG_DEBUG 3 /** Get trace output, packet information, ... */ #define SSH_LOG_TRACE 4 /** @} */ enum ssh_options_e { SSH_OPTIONS_HOST, SSH_OPTIONS_PORT, SSH_OPTIONS_PORT_STR, SSH_OPTIONS_PROXY_HOST, SSH_OPTIONS_PROXY_PORT, SSH_OPTIONS_PROXY_PORT_STR, SSH_OPTIONS_FD, SSH_OPTIONS_USER, SSH_OPTIONS_SSH_DIR, SSH_OPTIONS_IDENTITY, SSH_OPTIONS_ADD_IDENTITY, SSH_OPTIONS_KNOWNHOSTS, SSH_OPTIONS_TIMEOUT, SSH_OPTIONS_TIMEOUT_USEC, SSH_OPTIONS_SSH1, SSH_OPTIONS_SSH2, SSH_OPTIONS_LOG_VERBOSITY, SSH_OPTIONS_LOG_VERBOSITY_STR, SSH_OPTIONS_CIPHERS_C_S, SSH_OPTIONS_CIPHERS_S_C, SSH_OPTIONS_COMPRESSION_C_S, SSH_OPTIONS_COMPRESSION_S_C, SSH_OPTIONS_PROXYCOMMAND, SSH_OPTIONS_BINDADDR, SSH_OPTIONS_STRICTHOSTKEYCHECK, SSH_OPTIONS_COMPRESSION, SSH_OPTIONS_COMPRESSION_LEVEL, SSH_OPTIONS_KEY_EXCHANGE, SSH_OPTIONS_HOSTKEYS, SSH_OPTIONS_GSSAPI_SERVER_IDENTITY, SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, SSH_OPTIONS_HMAC_C_S, SSH_OPTIONS_HMAC_S_C, SSH_OPTIONS_PASSWORD_AUTH, SSH_OPTIONS_PUBKEY_AUTH, SSH_OPTIONS_KBDINT_AUTH, SSH_OPTIONS_GSSAPI_AUTH, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, SSH_OPTIONS_NODELAY, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, SSH_OPTIONS_PROCESS_CONFIG, SSH_OPTIONS_REKEY_DATA, SSH_OPTIONS_REKEY_TIME, SSH_OPTIONS_EXTERNAL_CALLBACKS }; enum { /** Code is going to write/create remote files */ SSH_SCP_WRITE, /** Code is going to read remote files */ SSH_SCP_READ, SSH_SCP_RECURSIVE=0x10 }; enum ssh_scp_request_types { /** A new directory is going to be pulled */ SSH_SCP_REQUEST_NEWDIR=1, /** A new file is going to be pulled */ SSH_SCP_REQUEST_NEWFILE, /** End of requests */ SSH_SCP_REQUEST_EOF, /** End of directory */ SSH_SCP_REQUEST_ENDDIR, /** Warning received */ SSH_SCP_REQUEST_WARNING }; enum ssh_connector_flags_e { /** Only the standard stream of the channel */ SSH_CONNECTOR_STDOUT = 1, SSH_CONNECTOR_STDINOUT = 1, /** Only the exception stream of the channel */ SSH_CONNECTOR_STDERR = 2, /** Merge both standard and exception streams */ SSH_CONNECTOR_BOTH = 3 }; LIBSSH_API int ssh_blocking_flush(ssh_session session, int timeout); LIBSSH_API ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms); LIBSSH_API int ssh_channel_change_pty_size(ssh_channel channel,int cols,int rows); LIBSSH_API int ssh_channel_close(ssh_channel channel); LIBSSH_API void ssh_channel_free(ssh_channel channel); LIBSSH_API int ssh_channel_get_exit_status(ssh_channel channel); LIBSSH_API ssh_session ssh_channel_get_session(ssh_channel channel); LIBSSH_API int ssh_channel_is_closed(ssh_channel channel); LIBSSH_API int ssh_channel_is_eof(ssh_channel channel); LIBSSH_API int ssh_channel_is_open(ssh_channel channel); LIBSSH_API ssh_channel ssh_channel_new(ssh_session session); LIBSSH_API int ssh_channel_open_auth_agent(ssh_channel channel); LIBSSH_API int ssh_channel_open_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport); LIBSSH_API int ssh_channel_open_forward_unix(ssh_channel channel, const char *remotepath, const char *sourcehost, int localport); LIBSSH_API int ssh_channel_open_session(ssh_channel channel); LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port); LIBSSH_API int ssh_channel_poll(ssh_channel channel, int is_stderr); LIBSSH_API int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr); LIBSSH_API int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr); LIBSSH_API int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout_ms); LIBSSH_API int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count, int is_stderr); LIBSSH_API int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value); LIBSSH_API int ssh_channel_request_exec(ssh_channel channel, const char *cmd); LIBSSH_API int ssh_channel_request_pty(ssh_channel channel); LIBSSH_API int ssh_channel_request_pty_size(ssh_channel channel, const char *term, int cols, int rows); LIBSSH_API int ssh_channel_request_shell(ssh_channel channel); LIBSSH_API int ssh_channel_request_send_signal(ssh_channel channel, const char *signum); LIBSSH_API int ssh_channel_request_send_break(ssh_channel channel, uint32_t length); LIBSSH_API int ssh_channel_request_sftp(ssh_channel channel); LIBSSH_API int ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem); LIBSSH_API int ssh_channel_request_x11(ssh_channel channel, int single_connection, const char *protocol, const char *cookie, int screen_number); LIBSSH_API int ssh_channel_request_auth_agent(ssh_channel channel); LIBSSH_API int ssh_channel_send_eof(ssh_channel channel); LIBSSH_API int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout); LIBSSH_API void ssh_channel_set_blocking(ssh_channel channel, int blocking); LIBSSH_API void ssh_channel_set_counter(ssh_channel channel, ssh_counter counter); LIBSSH_API int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len); LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len); LIBSSH_API uint32_t ssh_channel_window_size(ssh_channel channel); LIBSSH_API char *ssh_basename (const char *path); LIBSSH_API void ssh_clean_pubkey_hash(unsigned char **hash); LIBSSH_API int ssh_connect(ssh_session session); LIBSSH_API ssh_connector ssh_connector_new(ssh_session session); LIBSSH_API void ssh_connector_free(ssh_connector connector); LIBSSH_API int ssh_connector_set_in_channel(ssh_connector connector, ssh_channel channel, enum ssh_connector_flags_e flags); LIBSSH_API int ssh_connector_set_out_channel(ssh_connector connector, ssh_channel channel, enum ssh_connector_flags_e flags); LIBSSH_API void ssh_connector_set_in_fd(ssh_connector connector, socket_t fd); LIBSSH_API void ssh_connector_set_out_fd(ssh_connector connector, socket_t fd); LIBSSH_API const char *ssh_copyright(void); LIBSSH_API void ssh_disconnect(ssh_session session); LIBSSH_API char *ssh_dirname (const char *path); LIBSSH_API int ssh_finalize(void); /* REVERSE PORT FORWARDING */ LIBSSH_API ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int *destination_port); LIBSSH_API int ssh_channel_cancel_forward(ssh_session session, const char *address, int port); LIBSSH_API int ssh_channel_listen_forward(ssh_session session, const char *address, int port, int *bound_port); LIBSSH_API void ssh_free(ssh_session session); LIBSSH_API const char *ssh_get_disconnect_message(ssh_session session); LIBSSH_API const char *ssh_get_error(void *error); LIBSSH_API int ssh_get_error_code(void *error); LIBSSH_API socket_t ssh_get_fd(ssh_session session); LIBSSH_API char *ssh_get_hexa(const unsigned char *what, size_t len); LIBSSH_API char *ssh_get_issue_banner(ssh_session session); LIBSSH_API int ssh_get_openssh_version(ssh_session session); LIBSSH_API int ssh_get_server_publickey(ssh_session session, ssh_key *key); enum ssh_publickey_hash_type { SSH_PUBLICKEY_HASH_SHA1, SSH_PUBLICKEY_HASH_MD5, SSH_PUBLICKEY_HASH_SHA256 }; LIBSSH_API int ssh_get_publickey_hash(const ssh_key key, enum ssh_publickey_hash_type type, unsigned char **hash, size_t *hlen); /* DEPRECATED FUNCTIONS */ SSH_DEPRECATED LIBSSH_API int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash); SSH_DEPRECATED LIBSSH_API ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms); SSH_DEPRECATED LIBSSH_API int ssh_forward_cancel(ssh_session session, const char *address, int port); SSH_DEPRECATED LIBSSH_API int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port); SSH_DEPRECATED LIBSSH_API int ssh_get_publickey(ssh_session session, ssh_key *key); SSH_DEPRECATED LIBSSH_API int ssh_write_knownhost(ssh_session session); SSH_DEPRECATED LIBSSH_API char *ssh_dump_knownhost(ssh_session session); SSH_DEPRECATED LIBSSH_API int ssh_is_server_known(ssh_session session); SSH_DEPRECATED LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len); LIBSSH_API int ssh_get_random(void *where,int len,int strong); LIBSSH_API int ssh_get_version(ssh_session session); LIBSSH_API int ssh_get_status(ssh_session session); LIBSSH_API int ssh_get_poll_flags(ssh_session session); LIBSSH_API int ssh_init(void); LIBSSH_API int ssh_is_blocking(ssh_session session); LIBSSH_API int ssh_is_connected(ssh_session session); /* KNOWN HOSTS */ LIBSSH_API void ssh_knownhosts_entry_free(struct ssh_knownhosts_entry *entry); #define SSH_KNOWNHOSTS_ENTRY_FREE(e) do { \ if ((e) != NULL) { \ ssh_knownhosts_entry_free(e); \ e = NULL; \ } \ } while(0) LIBSSH_API int ssh_known_hosts_parse_line(const char *host, const char *line, struct ssh_knownhosts_entry **entry); LIBSSH_API enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session); LIBSSH_API int ssh_session_export_known_hosts_entry(ssh_session session, char **pentry_string); LIBSSH_API int ssh_session_update_known_hosts(ssh_session session); LIBSSH_API enum ssh_known_hosts_e ssh_session_get_known_hosts_entry(ssh_session session, struct ssh_knownhosts_entry **pentry); LIBSSH_API enum ssh_known_hosts_e ssh_session_is_known_server(ssh_session session); /* LOGGING */ LIBSSH_API int ssh_set_log_level(int level); LIBSSH_API int ssh_get_log_level(void); LIBSSH_API void *ssh_get_log_userdata(void); LIBSSH_API int ssh_set_log_userdata(void *data); LIBSSH_API void _ssh_log(int verbosity, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); /* legacy */ SSH_DEPRECATED LIBSSH_API void ssh_log(ssh_session session, int prioriry, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); LIBSSH_API ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg); LIBSSH_API int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan); LIBSSH_API int ssh_message_channel_request_reply_success(ssh_message msg); #define SSH_MESSAGE_FREE(x) \ do { if ((x) != NULL) { ssh_message_free(x); (x) = NULL; } } while(0) LIBSSH_API void ssh_message_free(ssh_message msg); LIBSSH_API ssh_message ssh_message_get(ssh_session session); LIBSSH_API int ssh_message_subtype(ssh_message msg); LIBSSH_API int ssh_message_type(ssh_message msg); LIBSSH_API int ssh_mkdir (const char *pathname, mode_t mode); LIBSSH_API ssh_session ssh_new(void); LIBSSH_API int ssh_options_copy(ssh_session src, ssh_session *dest); LIBSSH_API int ssh_options_getopt(ssh_session session, int *argcptr, char **argv); LIBSSH_API int ssh_options_parse_config(ssh_session session, const char *filename); LIBSSH_API int ssh_options_set(ssh_session session, enum ssh_options_e type, const void *value); LIBSSH_API int ssh_options_get(ssh_session session, enum ssh_options_e type, char **value); LIBSSH_API int ssh_options_get_port(ssh_session session, unsigned int * port_target); LIBSSH_API int ssh_pcap_file_close(ssh_pcap_file pcap); LIBSSH_API void ssh_pcap_file_free(ssh_pcap_file pcap); LIBSSH_API ssh_pcap_file ssh_pcap_file_new(void); LIBSSH_API int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename); /** * @addtogroup libssh_auth * * @{ */ /** * @brief SSH authentication callback for password and publickey auth. * * @param prompt Prompt to be displayed. * @param buf Buffer to save the password. You should null-terminate it. * @param len Length of the buffer. * @param echo Enable or disable the echo of what you type. * @param verify Should the password be verified? * @param userdata Userdata to be passed to the callback function. Useful * for GUI applications. * * @return 0 on success, < 0 on error. */ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata); /** @} */ LIBSSH_API ssh_key ssh_key_new(void); #define SSH_KEY_FREE(x) \ do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0) LIBSSH_API void ssh_key_free (ssh_key key); LIBSSH_API enum ssh_keytypes_e ssh_key_type(const ssh_key key); LIBSSH_API const char *ssh_key_type_to_char(enum ssh_keytypes_e type); LIBSSH_API enum ssh_keytypes_e ssh_key_type_from_name(const char *name); LIBSSH_API int ssh_key_is_public(const ssh_key k); LIBSSH_API int ssh_key_is_private(const ssh_key k); LIBSSH_API int ssh_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); LIBSSH_API int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey); LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, ssh_key *pkey); LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, char **b64_key); LIBSSH_API int ssh_pki_import_privkey_file(const char *filename, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, ssh_key *pkey); LIBSSH_API int ssh_pki_export_privkey_file(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, const char *filename); LIBSSH_API int ssh_pki_copy_cert_to_privkey(const ssh_key cert_key, ssh_key privkey); LIBSSH_API int ssh_pki_import_pubkey_base64(const char *b64_key, enum ssh_keytypes_e type, ssh_key *pkey); LIBSSH_API int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey); LIBSSH_API int ssh_pki_import_cert_base64(const char *b64_cert, enum ssh_keytypes_e type, ssh_key *pkey); LIBSSH_API int ssh_pki_import_cert_file(const char *filename, ssh_key *pkey); LIBSSH_API int ssh_pki_export_privkey_to_pubkey(const ssh_key privkey, ssh_key *pkey); LIBSSH_API int ssh_pki_export_pubkey_base64(const ssh_key key, char **b64_key); LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key, const char *filename); LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key); LIBSSH_API char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len); LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len); LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data); LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display); LIBSSH_API void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds); LIBSSH_API int ssh_scp_accept_request(ssh_scp scp); LIBSSH_API int ssh_scp_close(ssh_scp scp); LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason); LIBSSH_API void ssh_scp_free(ssh_scp scp); LIBSSH_API int ssh_scp_init(ssh_scp scp); LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp); LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location); LIBSSH_API int ssh_scp_pull_request(ssh_scp scp); LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode); LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int perms); LIBSSH_API int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int perms); LIBSSH_API int ssh_scp_read(ssh_scp scp, void *buffer, size_t size); LIBSSH_API const char *ssh_scp_request_get_filename(ssh_scp scp); LIBSSH_API int ssh_scp_request_get_permissions(ssh_scp scp); LIBSSH_API size_t ssh_scp_request_get_size(ssh_scp scp); LIBSSH_API uint64_t ssh_scp_request_get_size64(ssh_scp scp); LIBSSH_API const char *ssh_scp_request_get_warning(ssh_scp scp); LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len); LIBSSH_API int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, fd_set *readfds, struct timeval *timeout); LIBSSH_API int ssh_service_request(ssh_session session, const char *service); LIBSSH_API int ssh_set_agent_channel(ssh_session session, ssh_channel channel); #ifndef _WIN32 LIBSSH_API int ssh_set_agent_socket(ssh_session session, socket_t fd); #endif LIBSSH_API void ssh_set_blocking(ssh_session session, int blocking); LIBSSH_API void ssh_set_counters(ssh_session session, ssh_counter scounter, ssh_counter rcounter); LIBSSH_API void ssh_set_fd_except(ssh_session session); LIBSSH_API void ssh_set_fd_toread(ssh_session session); LIBSSH_API void ssh_set_fd_towrite(ssh_session session); LIBSSH_API void ssh_silent_disconnect(ssh_session session); LIBSSH_API int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile); /* USERAUTH */ LIBSSH_API int ssh_userauth_none(ssh_session session, const char *username); LIBSSH_API int ssh_userauth_list(ssh_session session, const char *username); LIBSSH_API int ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey); LIBSSH_API int ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey); LIBSSH_API int ssh_userauth_agent(ssh_session session, const char *username); LIBSSH_API int ssh_userauth_publickey_auto(ssh_session session, const char *username, const char *passphrase); LIBSSH_API int ssh_userauth_password(ssh_session session, const char *username, const char *password); LIBSSH_API int ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods); LIBSSH_API const char *ssh_userauth_kbdint_getinstruction(ssh_session session); LIBSSH_API const char *ssh_userauth_kbdint_getname(ssh_session session); LIBSSH_API int ssh_userauth_kbdint_getnprompts(ssh_session session); LIBSSH_API const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, char *echo); LIBSSH_API int ssh_userauth_kbdint_getnanswers(ssh_session session); LIBSSH_API const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i); LIBSSH_API int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i, const char *answer); LIBSSH_API int ssh_userauth_gssapi(ssh_session session); LIBSSH_API const char *ssh_version(int req_version); LIBSSH_API void ssh_string_burn(ssh_string str); LIBSSH_API ssh_string ssh_string_copy(ssh_string str); LIBSSH_API void *ssh_string_data(ssh_string str); LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len); #define SSH_STRING_FREE(x) \ do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0) LIBSSH_API void ssh_string_free(ssh_string str); LIBSSH_API ssh_string ssh_string_from_char(const char *what); LIBSSH_API size_t ssh_string_len(ssh_string str); LIBSSH_API ssh_string ssh_string_new(size_t size); LIBSSH_API const char *ssh_string_get_char(ssh_string str); LIBSSH_API char *ssh_string_to_char(ssh_string str); #define SSH_STRING_FREE_CHAR(x) \ do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0) LIBSSH_API void ssh_string_free_char(char *s); LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo, int verify); typedef int (*ssh_event_callback)(socket_t fd, int revents, void *userdata); LIBSSH_API ssh_event ssh_event_new(void); LIBSSH_API int ssh_event_add_fd(ssh_event event, socket_t fd, short events, ssh_event_callback cb, void *userdata); LIBSSH_API int ssh_event_add_session(ssh_event event, ssh_session session); LIBSSH_API int ssh_event_add_connector(ssh_event event, ssh_connector connector); LIBSSH_API int ssh_event_dopoll(ssh_event event, int timeout); LIBSSH_API int ssh_event_remove_fd(ssh_event event, socket_t fd); LIBSSH_API int ssh_event_remove_session(ssh_event event, ssh_session session); LIBSSH_API int ssh_event_remove_connector(ssh_event event, ssh_connector connector); LIBSSH_API void ssh_event_free(ssh_event event); LIBSSH_API const char* ssh_get_clientbanner(ssh_session session); LIBSSH_API const char* ssh_get_serverbanner(ssh_session session); LIBSSH_API const char* ssh_get_kex_algo(ssh_session session); LIBSSH_API const char* ssh_get_cipher_in(ssh_session session); LIBSSH_API const char* ssh_get_cipher_out(ssh_session session); LIBSSH_API const char* ssh_get_hmac_in(ssh_session session); LIBSSH_API const char* ssh_get_hmac_out(ssh_session session); LIBSSH_API ssh_buffer ssh_buffer_new(void); LIBSSH_API void ssh_buffer_free(ssh_buffer buffer); #define SSH_BUFFER_FREE(x) \ do { if ((x) != NULL) { ssh_buffer_free(x); x = NULL; } } while(0) LIBSSH_API int ssh_buffer_reinit(ssh_buffer buffer); LIBSSH_API int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len); LIBSSH_API uint32_t ssh_buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen); LIBSSH_API void *ssh_buffer_get(ssh_buffer buffer); LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer); #ifndef LIBSSH_LEGACY_0_4 #include "libssh/legacy.h" #endif #ifdef __cplusplus } #endif #endif /* _LIBSSH_H */ ================================================ FILE: src/libssh/include/libssh/libssh_version.h.cmake ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2020 by Heiko Thiery * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LIBSSH_VERSION_H #define _LIBSSH_VERSION_H /* libssh version macros */ #define SSH_VERSION_INT(a, b, c) ((a) << 16 | (b) << 8 | (c)) #define SSH_VERSION_DOT(a, b, c) a ##.## b ##.## c #define SSH_VERSION(a, b, c) SSH_VERSION_DOT(a, b, c) /* libssh version */ #define LIBSSH_VERSION_MAJOR @libssh_VERSION_MAJOR@ #define LIBSSH_VERSION_MINOR @libssh_VERSION_MINOR@ #define LIBSSH_VERSION_MICRO @libssh_VERSION_PATCH@ #define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \ LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MICRO) #define LIBSSH_VERSION SSH_VERSION(LIBSSH_VERSION_MAJOR, \ LIBSSH_VERSION_MINOR, \ LIBSSH_VERSION_MICRO) #endif /* _LIBSSH_VERSION_H */ ================================================ FILE: src/libssh/include/libssh/libsshpp.hpp ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LIBSSHPP_HPP_ #define LIBSSHPP_HPP_ /** * @defgroup ssh_cpp The libssh C++ wrapper * * The C++ bindings for libssh are completely embedded in a single .hpp file, and * this for two reasons: * - C++ is hard to keep binary compatible, C is easy. We try to keep libssh C version * as much as possible binary compatible between releases, while this would be hard for * C++. If you compile your program with these headers, you will only link to the C version * of libssh which will be kept ABI compatible. No need to recompile your C++ program * each time a new binary-compatible version of libssh is out * - Most of the functions in this file are really short and are probably worth the "inline" * linking mode, which the compiler can decide to do in some case. There would be nearly no * performance penalty of using the wrapper rather than native calls. * * Please visit the documentation of ssh::Session and ssh::Channel * @see ssh::Session * @see ssh::Channel * * If you wish not to use C++ exceptions, please define SSH_NO_CPP_EXCEPTIONS: * @code * #define SSH_NO_CPP_EXCEPTIONS * #include * @endcode * All functions will then return SSH_ERROR in case of error. * @{ */ /* do not use deprecated functions */ #define LIBSSH_LEGACY_0_4 #include #include #include #include #include #include namespace ssh { class Channel; /** Some people do not like C++ exceptions. With this define, we give * the choice to use or not exceptions. * @brief if defined, disable C++ exceptions for libssh c++ wrapper */ #ifndef SSH_NO_CPP_EXCEPTIONS /** @brief This class describes a SSH Exception object. This object can be thrown * by several SSH functions that interact with the network, and may fail because of * socket, protocol or memory errors. */ class SshException{ public: SshException(ssh_session csession){ code=ssh_get_error_code(csession); description=std::string(ssh_get_error(csession)); } SshException(const SshException &e){ code=e.code; description=e.description; } /** @brief returns the Error code * @returns SSH_FATAL Fatal error happened (not recoverable) * @returns SSH_REQUEST_DENIED Request was denied by remote host * @see ssh_get_error_code */ int getCode(){ return code; } /** @brief returns the error message of the last exception * @returns pointer to a c string containing the description of error * @see ssh_get_error */ std::string getError(){ return description; } private: int code; std::string description; }; /** @internal * @brief Macro to throw exception if there was an error */ #define ssh_throw(x) if((x)==SSH_ERROR) throw SshException(getCSession()) #define ssh_throw_null(CSession,x) if((x)==NULL) throw SshException(CSession) #define void_throwable void #define return_throwable return #else /* No exception at all. All functions will return an error code instead * of an exception */ #define ssh_throw(x) if((x)==SSH_ERROR) return SSH_ERROR #define ssh_throw_null(CSession,x) if((x)==NULL) return NULL #define void_throwable int #define return_throwable return SSH_OK #endif /** * The ssh::Session class contains the state of a SSH connection. */ class Session { friend class Channel; public: Session(){ c_session=ssh_new(); } ~Session(){ ssh_free(c_session); c_session=NULL; } /** @brief sets an SSH session options * @param type Type of option * @param option cstring containing the value of option * @throws SshException on error * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, const char *option){ ssh_throw(ssh_options_set(c_session,type,option)); return_throwable; } /** @brief sets an SSH session options * @param type Type of option * @param option long integer containing the value of option * @throws SshException on error * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, long int option){ ssh_throw(ssh_options_set(c_session,type,&option)); return_throwable; } /** @brief sets an SSH session options * @param type Type of option * @param option void pointer containing the value of option * @throws SshException on error * @see ssh_options_set */ void_throwable setOption(enum ssh_options_e type, void *option){ ssh_throw(ssh_options_set(c_session,type,option)); return_throwable; } /** @brief connects to the remote host * @throws SshException on error * @see ssh_connect */ void_throwable connect(){ int ret=ssh_connect(c_session); ssh_throw(ret); return_throwable; } /** @brief Authenticates automatically using public key * @throws SshException on error * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED * @see ssh_userauth_autopubkey */ int userauthPublickeyAuto(void){ int ret=ssh_userauth_publickey_auto(c_session, NULL, NULL); ssh_throw(ret); return ret; } /** @brief Authenticates using the "none" method. Prefer using autopubkey if * possible. * @throws SshException on error * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED * @see ssh_userauth_none * @see Session::userauthAutoPubkey */ int userauthNone(){ int ret=ssh_userauth_none(c_session,NULL); ssh_throw(ret); return ret; } /** * @brief Authenticate through the "keyboard-interactive" method. * * @param[in] username The username to authenticate. You can specify NULL if * ssh_option_set_username() has been used. You cannot * try two different logins in a row. * * @param[in] submethods Undocumented. Set it to NULL. * * @throws SshException on error * * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED, * SSH_AUTH_ERROR, SSH_AUTH_INFO, SSH_AUTH_AGAIN * * @see ssh_userauth_kbdint */ int userauthKbdint(const char* username, const char* submethods){ int ret = ssh_userauth_kbdint(c_session, username, submethods); ssh_throw(ret); return ret; } /** @brief Get the number of prompts (questions) the server has given. * @returns The number of prompts. * @see ssh_userauth_kbdint_getnprompts */ int userauthKbdintGetNPrompts(){ return ssh_userauth_kbdint_getnprompts(c_session); } /** * @brief Set the answer for a question from a message block. * * @param[in] index The index number of the prompt. * @param[in] answer The answer to give to the server. The answer MUST be * encoded UTF-8. It is up to the server how to interpret * the value and validate it. However, if you read the * answer in some other encoding, you MUST convert it to * UTF-8. * * @throws SshException on error * * @returns 0 on success, < 0 on error * * @see ssh_userauth_kbdint_setanswer */ int userauthKbdintSetAnswer(unsigned int index, const char *answer) { int ret = ssh_userauth_kbdint_setanswer(c_session, index, answer); ssh_throw(ret); return ret; } /** @brief Authenticates using the password method. * @param[in] password password to use for authentication * @throws SshException on error * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED * @see ssh_userauth_password */ int userauthPassword(const char *password){ int ret=ssh_userauth_password(c_session,NULL,password); ssh_throw(ret); return ret; } /** @brief Try to authenticate using the publickey method. * @param[in] pubkey public key to use for authentication * @throws SshException on error * @returns SSH_AUTH_SUCCESS if the pubkey is accepted, * @returns SSH_AUTH_DENIED if the pubkey is denied * @see ssh_userauth_try_pubkey */ int userauthTryPublickey(ssh_key pubkey){ int ret=ssh_userauth_try_publickey(c_session, NULL, pubkey); ssh_throw(ret); return ret; } /** @brief Authenticates using the publickey method. * @param[in] privkey private key to use for authentication * @throws SshException on error * @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED * @see ssh_userauth_pubkey */ int userauthPublickey(ssh_key privkey){ int ret=ssh_userauth_publickey(c_session, NULL, privkey); ssh_throw(ret); return ret; } /** @brief Returns the available authentication methods from the server * @throws SshException on error * @returns Bitfield of available methods. * @see ssh_userauth_list */ int getAuthList(){ int ret=ssh_userauth_list(c_session, NULL); ssh_throw(ret); return ret; } /** @brief Disconnects from the SSH server and closes connection * @see ssh_disconnect */ void disconnect(){ ssh_disconnect(c_session); } /** @brief Returns the disconnect message from the server, if any * @returns pointer to the message, or NULL. Do not attempt to free * the pointer. */ const char *getDisconnectMessage(){ const char *msg=ssh_get_disconnect_message(c_session); return msg; } /** @internal * @brief gets error message */ const char *getError(){ return ssh_get_error(c_session); } /** @internal * @brief returns error code */ int getErrorCode(){ return ssh_get_error_code(c_session); } /** @brief returns the file descriptor used for the communication * @returns the file descriptor * @warning if a proxycommand is used, this function will only return * one of the two file descriptors being used * @see ssh_get_fd */ socket_t getSocket(){ return ssh_get_fd(c_session); } /** @brief gets the Issue banner from the ssh server * @returns the issue banner. This is generally a MOTD from server * @see ssh_get_issue_banner */ std::string getIssueBanner(){ char *banner = ssh_get_issue_banner(c_session); std::string ret = ""; if (banner != NULL) { ret = std::string(banner); ::free(banner); } return ret; } /** @brief returns the OpenSSH version (server) if possible * @returns openssh version code * @see ssh_get_openssh_version */ int getOpensshVersion(){ return ssh_get_openssh_version(c_session); } /** @brief returns the version of the SSH protocol being used * @returns the SSH protocol version * @see ssh_get_version */ int getVersion(){ return ssh_get_version(c_session); } /** @brief verifies that the server is known * @throws SshException on error * @returns Integer value depending on the knowledge of the * server key * @see ssh_session_update_known_hosts */ int isServerKnown(){ int state = ssh_session_is_known_server(c_session); ssh_throw(state); return state; } void log(int priority, const char *format, ...){ char buffer[1024]; va_list va; va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); _ssh_log(priority, "libsshpp", "%s", buffer); } /** @brief copies options from a session to another * @throws SshException on error * @see ssh_options_copy */ void_throwable optionsCopy(const Session &source){ ssh_throw(ssh_options_copy(source.c_session,&c_session)); return_throwable; } /** @brief parses a configuration file for options * @throws SshException on error * @param[in] file configuration file name * @see ssh_options_parse_config */ void_throwable optionsParseConfig(const char *file){ ssh_throw(ssh_options_parse_config(c_session,file)); return_throwable; } /** @brief silently disconnect from remote host * @see ssh_silent_disconnect */ void silentDisconnect(){ ssh_silent_disconnect(c_session); } /** @brief Writes the known host file with current * host key * @throws SshException on error * @see ssh_write_knownhost */ int writeKnownhost(){ int ret = ssh_session_update_known_hosts(c_session); ssh_throw(ret); return ret; } /** @brief accept an incoming forward connection * @param[in] timeout_ms timeout for waiting, in ms * @returns new Channel pointer on the forward connection * @returns NULL in case of error * @warning you have to delete this pointer after use * @see ssh_channel_forward_accept * @see Session::listenForward */ inline Channel *acceptForward(int timeout_ms); /* implemented outside the class due Channel references */ void_throwable cancelForward(const char *address, int port){ int err=ssh_channel_cancel_forward(c_session, address, port); ssh_throw(err); return_throwable; } void_throwable listenForward(const char *address, int port, int &boundport){ int err=ssh_channel_listen_forward(c_session, address, port, &boundport); ssh_throw(err); return_throwable; } ssh_session getCSession(){ return c_session; } protected: ssh_session c_session; private: /* No copy constructor, no = operator */ Session(const Session &); Session& operator=(const Session &); }; /** @brief the ssh::Channel class describes the state of an SSH * channel. * @see ssh_channel */ class Channel { friend class Session; public: Channel(Session &ssh_session){ channel = ssh_channel_new(ssh_session.getCSession()); this->session = &ssh_session; } ~Channel(){ ssh_channel_free(channel); channel=NULL; } /** @brief accept an incoming X11 connection * @param[in] timeout_ms timeout for waiting, in ms * @returns new Channel pointer on the X11 connection * @returns NULL in case of error * @warning you have to delete this pointer after use * @see ssh_channel_accept_x11 * @see Channel::requestX11 */ Channel *acceptX11(int timeout_ms){ ssh_channel x11chan = ssh_channel_accept_x11(channel,timeout_ms); ssh_throw_null(getCSession(),x11chan); Channel *newchan = new Channel(getSession(),x11chan); return newchan; } /** @brief change the size of a pseudoterminal * @param[in] cols number of columns * @param[in] rows number of rows * @throws SshException on error * @see ssh_channel_change_pty_size */ void_throwable changePtySize(int cols, int rows){ int err=ssh_channel_change_pty_size(channel,cols,rows); ssh_throw(err); return_throwable; } /** @brief closes a channel * @throws SshException on error * @see ssh_channel_close */ void_throwable close(){ ssh_throw(ssh_channel_close(channel)); return_throwable; } int getExitStatus(){ return ssh_channel_get_exit_status(channel); } Session &getSession(){ return *session; } /** @brief returns true if channel is in closed state * @see ssh_channel_is_closed */ bool isClosed(){ return ssh_channel_is_closed(channel) != 0; } /** @brief returns true if channel is in EOF state * @see ssh_channel_is_eof */ bool isEof(){ return ssh_channel_is_eof(channel) != 0; } /** @brief returns true if channel is in open state * @see ssh_channel_is_open */ bool isOpen(){ return ssh_channel_is_open(channel) != 0; } int openForward(const char *remotehost, int remoteport, const char *sourcehost=NULL, int localport=0){ int err=ssh_channel_open_forward(channel,remotehost,remoteport, sourcehost, localport); ssh_throw(err); return err; } /* TODO: completely remove this ? */ void_throwable openSession(){ int err=ssh_channel_open_session(channel); ssh_throw(err); return_throwable; } int poll(bool is_stderr=false){ int err=ssh_channel_poll(channel,is_stderr); ssh_throw(err); return err; } int read(void *dest, size_t count){ int err; /* handle int overflow */ if(count > 0x7fffffff) count = 0x7fffffff; err=ssh_channel_read_timeout(channel,dest,count,false,-1); ssh_throw(err); return err; } int read(void *dest, size_t count, int timeout){ int err; /* handle int overflow */ if(count > 0x7fffffff) count = 0x7fffffff; err=ssh_channel_read_timeout(channel,dest,count,false,timeout); ssh_throw(err); return err; } int read(void *dest, size_t count, bool is_stderr=false, int timeout=-1){ int err; /* handle int overflow */ if(count > 0x7fffffff) count = 0x7fffffff; err=ssh_channel_read_timeout(channel,dest,count,is_stderr,timeout); ssh_throw(err); return err; } int readNonblocking(void *dest, size_t count, bool is_stderr=false){ int err; /* handle int overflow */ if(count > 0x7fffffff) count = 0x7fffffff; err=ssh_channel_read_nonblocking(channel,dest,count,is_stderr); ssh_throw(err); return err; } void_throwable requestEnv(const char *name, const char *value){ int err=ssh_channel_request_env(channel,name,value); ssh_throw(err); return_throwable; } void_throwable requestExec(const char *cmd){ int err=ssh_channel_request_exec(channel,cmd); ssh_throw(err); return_throwable; } void_throwable requestPty(const char *term=NULL, int cols=0, int rows=0){ int err; if(term != NULL && cols != 0 && rows != 0) err=ssh_channel_request_pty_size(channel,term,cols,rows); else err=ssh_channel_request_pty(channel); ssh_throw(err); return_throwable; } void_throwable requestShell(){ int err=ssh_channel_request_shell(channel); ssh_throw(err); return_throwable; } void_throwable requestSendSignal(const char *signum){ int err=ssh_channel_request_send_signal(channel, signum); ssh_throw(err); return_throwable; } void_throwable requestSubsystem(const char *subsystem){ int err=ssh_channel_request_subsystem(channel,subsystem); ssh_throw(err); return_throwable; } int requestX11(bool single_connection, const char *protocol, const char *cookie, int screen_number){ int err=ssh_channel_request_x11(channel,single_connection, protocol, cookie, screen_number); ssh_throw(err); return err; } void_throwable sendEof(){ int err=ssh_channel_send_eof(channel); ssh_throw(err); return_throwable; } /** @brief Writes on a channel * @param data data to write. * @param len number of bytes to write. * @param is_stderr write should be done on the stderr channel (server only) * @returns number of bytes written * @throws SshException in case of error * @see channel_write * @see channel_write_stderr */ int write(const void *data, size_t len, bool is_stderr=false){ int ret; if(is_stderr){ ret=ssh_channel_write_stderr(channel,data,len); } else { ret=ssh_channel_write(channel,data,len); } ssh_throw(ret); return ret; } ssh_session getCSession(){ return session->getCSession(); } ssh_channel getCChannel() { return channel; } protected: Session *session; ssh_channel channel; private: Channel (Session &ssh_session, ssh_channel c_channel){ this->channel=c_channel; this->session = &ssh_session; } /* No copy and no = operator */ Channel(const Channel &); Channel &operator=(const Channel &); }; inline Channel *Session::acceptForward(int timeout_ms){ ssh_channel forward = ssh_channel_accept_forward(c_session, timeout_ms, NULL); ssh_throw_null(c_session,forward); Channel *newchan = new Channel(*this,forward); return newchan; } } // namespace ssh /** @} */ #endif /* LIBSSHPP_HPP_ */ ================================================ FILE: src/libssh/include/libssh/messages.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MESSAGES_H_ #define MESSAGES_H_ #include "config.h" struct ssh_auth_request { char *username; int method; char *password; struct ssh_key_struct *pubkey; enum ssh_publickey_state_e signature_state; char kbdint_response; }; struct ssh_channel_request_open { int type; uint32_t sender; uint32_t window; uint32_t packet_size; char *originator; uint16_t originator_port; char *destination; uint16_t destination_port; }; struct ssh_service_request { char *service; }; struct ssh_global_request { int type; uint8_t want_reply; char *bind_address; uint16_t bind_port; }; struct ssh_channel_request { int type; ssh_channel channel; uint8_t want_reply; /* pty-req type specifics */ char *TERM; uint32_t width; uint32_t height; uint32_t pxwidth; uint32_t pxheight; ssh_string modes; /* env type request */ char *var_name; char *var_value; /* exec type request */ char *command; /* subsystem */ char *subsystem; /* X11 */ uint8_t x11_single_connection; char *x11_auth_protocol; char *x11_auth_cookie; uint32_t x11_screen_number; }; struct ssh_message_struct { ssh_session session; int type; struct ssh_auth_request auth_request; struct ssh_channel_request_open channel_request_open; struct ssh_channel_request channel_request; struct ssh_service_request service_request; struct ssh_global_request global_request; }; SSH_PACKET_CALLBACK(ssh_packet_channel_open); SSH_PACKET_CALLBACK(ssh_packet_global_request); #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_service_request); SSH_PACKET_CALLBACK(ssh_packet_userauth_request); #endif /* WITH_SERVER */ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet, const char *request, uint8_t want_reply); ssh_message ssh_message_pop_head(ssh_session session); #endif /* MESSAGES_H_ */ ================================================ FILE: src/libssh/include/libssh/misc.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MISC_H_ #define MISC_H_ /* in misc.c */ /* gets the user home dir. */ char *ssh_get_user_home_dir(void); char *ssh_get_local_username(void); int ssh_file_readaccess_ok(const char *file); int ssh_dir_writeable(const char *path); char *ssh_path_expand_tilde(const char *d); char *ssh_path_expand_escape(ssh_session session, const char *s); int ssh_analyze_banner(ssh_session session, int server); int ssh_is_ipaddr_v4(const char *str); int ssh_is_ipaddr(const char *str); /* list processing */ struct ssh_list { struct ssh_iterator *root; struct ssh_iterator *end; }; struct ssh_iterator { struct ssh_iterator *next; const void *data; }; struct ssh_timestamp { long seconds; long useconds; }; enum ssh_quote_state_e { NO_QUOTE, SINGLE_QUOTE, DOUBLE_QUOTE }; struct ssh_list *ssh_list_new(void); void ssh_list_free(struct ssh_list *list); struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list); struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value); size_t ssh_list_count(const struct ssh_list *list); int ssh_list_append(struct ssh_list *list, const void *data); int ssh_list_prepend(struct ssh_list *list, const void *data); void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator); char *ssh_lowercase(const char* str); char *ssh_hostport(const char *host, int port); const void *_ssh_list_pop_head(struct ssh_list *list); #define ssh_iterator_value(type, iterator)\ ((type)((iterator)->data)) /** @brief fetch the head element of a list and remove it from list * @param type type of the element to return * @param list the ssh_list to use * @return the first element of the list, or NULL if the list is empty */ #define ssh_list_pop_head(type, ssh_list)\ ((type)_ssh_list_pop_head(ssh_list)) int ssh_make_milliseconds(long sec, long usec); void ssh_timestamp_init(struct ssh_timestamp *ts); int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout); int ssh_timeout_update(struct ssh_timestamp *ts, int timeout); int ssh_match_group(const char *group, const char *object); void uint64_inc(unsigned char *counter); void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len); int ssh_mkdirs(const char *pathname, mode_t mode); int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len); int ssh_newline_vis(const char *string, char *buf, size_t buf_len); #endif /* MISC_H_ */ ================================================ FILE: src/libssh/include/libssh/options.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2011 Andreas Schneider * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _OPTIONS_H #define _OPTIONS_H int ssh_config_parse_file(ssh_session session, const char *filename); int ssh_options_set_algo(ssh_session session, enum ssh_kex_types_e algo, const char *list); int ssh_options_apply(ssh_session session); #endif /* _OPTIONS_H */ ================================================ FILE: src/libssh/include/libssh/packet.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PACKET_H_ #define PACKET_H_ #include "libssh/wrapper.h" struct ssh_socket_struct; /* this structure should go someday */ typedef struct packet_struct { int valid; uint32_t len; uint8_t type; } PACKET; /** different state of packet reading. */ enum ssh_packet_state_e { /** Packet not initialized, must read the size of packet */ PACKET_STATE_INIT, /** Size was read, waiting for the rest of data */ PACKET_STATE_SIZEREAD, /** Full packet was read and callbacks are being called. Future packets * should wait for the end of the callback. */ PACKET_STATE_PROCESSING }; enum ssh_packet_filter_result_e { SSH_PACKET_UNKNOWN, SSH_PACKET_ALLOWED, SSH_PACKET_DENIED }; int ssh_packet_send(ssh_session session); SSH_PACKET_CALLBACK(ssh_packet_unimplemented); SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback); SSH_PACKET_CALLBACK(ssh_packet_ignore_callback); SSH_PACKET_CALLBACK(ssh_packet_dh_reply); SSH_PACKET_CALLBACK(ssh_packet_newkeys); SSH_PACKET_CALLBACK(ssh_packet_service_accept); SSH_PACKET_CALLBACK(ssh_packet_ext_info); #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); #endif int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum); int ssh_packet_parse_type(ssh_session session); //int packet_flush(ssh_session session, int enforce_blocking); int ssh_packet_socket_callback(const void *data, size_t len, void *user); void ssh_packet_register_socket_callback(ssh_session session, struct ssh_socket_struct *s); void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks); void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks); void ssh_packet_set_default_callbacks(ssh_session session); void ssh_packet_process(ssh_session session, uint8_t type); /* PACKET CRYPT */ uint32_t ssh_packet_decrypt_len(ssh_session session, uint8_t *destination, uint8_t *source); int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *source, size_t start, size_t encrypted_size); unsigned char *ssh_packet_encrypt(ssh_session session, void *packet, unsigned int len); int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len, unsigned char *mac, enum ssh_hmac_e type); int ssh_packet_set_newkeys(ssh_session session, enum ssh_crypto_direction_e direction); struct ssh_crypto_struct *ssh_packet_get_current_crypto(ssh_session session, enum ssh_crypto_direction_e direction); #endif /* PACKET_H_ */ ================================================ FILE: src/libssh/include/libssh/pcap.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PCAP_H_ #define PCAP_H_ #include "config.h" #include "libssh/libssh.h" #ifdef WITH_PCAP typedef struct ssh_pcap_context_struct* ssh_pcap_context; int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len); ssh_pcap_context ssh_pcap_context_new(ssh_session session); void ssh_pcap_context_free(ssh_pcap_context ctx); enum ssh_pcap_direction{ SSH_PCAP_DIR_IN, SSH_PCAP_DIR_OUT }; void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file); int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data, uint32_t len, uint32_t origlen); #endif /* WITH_PCAP */ #endif /* PCAP_H_ */ ================================================ FILE: src/libssh/include/libssh/pki.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PKI_H_ #define PKI_H_ #include "libssh/priv.h" #ifdef HAVE_OPENSSL_EC_H #include #endif #ifdef HAVE_OPENSSL_ECDSA_H #include #endif #include "libssh/crypto.h" #ifdef HAVE_OPENSSL_ED25519 /* If using OpenSSL implementation, define the signature lenght which would be * defined in libssh/ed25519.h otherwise */ #define ED25519_SIG_LEN 64 #else #include "libssh/ed25519.h" #endif /* This definition is used for both OpenSSL and internal implementations */ #define ED25519_KEY_LEN 32 #define MAX_PUBKEY_SIZE 0x100000 /* 1M */ #define MAX_PRIVKEY_SIZE 0x400000 /* 4M */ #define SSH_KEY_FLAG_EMPTY 0x0 #define SSH_KEY_FLAG_PUBLIC 0x0001 #define SSH_KEY_FLAG_PRIVATE 0x0002 struct ssh_key_struct { enum ssh_keytypes_e type; int flags; const char *type_c; /* Don't free it ! it is static */ int ecdsa_nid; #if defined(HAVE_LIBGCRYPT) gcry_sexp_t dsa; gcry_sexp_t rsa; gcry_sexp_t ecdsa; #elif defined(HAVE_LIBMBEDCRYPTO) mbedtls_pk_context *rsa; mbedtls_ecdsa_context *ecdsa; void *dsa; #elif defined(HAVE_LIBCRYPTO) DSA *dsa; RSA *rsa; # if defined(HAVE_OPENSSL_ECC) EC_KEY *ecdsa; # else void *ecdsa; # endif /* HAVE_OPENSSL_EC_H */ #endif /* HAVE_LIBGCRYPT */ #ifdef HAVE_OPENSSL_ED25519 uint8_t *ed25519_pubkey; uint8_t *ed25519_privkey; #else ed25519_pubkey *ed25519_pubkey; ed25519_privkey *ed25519_privkey; #endif void *cert; enum ssh_keytypes_e cert_type; }; struct ssh_signature_struct { enum ssh_keytypes_e type; enum ssh_digest_e hash_type; const char *type_c; #if defined(HAVE_LIBGCRYPT) gcry_sexp_t dsa_sig; gcry_sexp_t rsa_sig; gcry_sexp_t ecdsa_sig; #elif defined(HAVE_LIBMBEDCRYPTO) ssh_string rsa_sig; struct mbedtls_ecdsa_sig ecdsa_sig; #endif /* HAVE_LIBGCRYPT */ #ifndef HAVE_OPENSSL_ED25519 ed25519_signature *ed25519_sig; #endif ssh_string raw_sig; }; typedef struct ssh_signature_struct *ssh_signature; /* SSH Key Functions */ ssh_key ssh_key_dup(const ssh_key key); void ssh_key_clean (ssh_key key); const char * ssh_key_get_signature_algorithm(ssh_session session, enum ssh_keytypes_e type); enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name); enum ssh_keytypes_e ssh_key_type_plain(enum ssh_keytypes_e type); enum ssh_digest_e ssh_key_type_to_hash(ssh_session session, enum ssh_keytypes_e type); enum ssh_digest_e ssh_key_hash_from_name(const char *name); #define is_ecdsa_key_type(t) \ ((t) >= SSH_KEYTYPE_ECDSA_P256 && (t) <= SSH_KEYTYPE_ECDSA_P521) #define is_cert_type(kt)\ ((kt) == SSH_KEYTYPE_DSS_CERT01 ||\ (kt) == SSH_KEYTYPE_RSA_CERT01 ||\ ((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\ (kt) <= SSH_KEYTYPE_ED25519_CERT01)) /* SSH Signature Functions */ ssh_signature ssh_signature_new(void); void ssh_signature_free(ssh_signature sign); int ssh_pki_export_signature_blob(const ssh_signature sign, ssh_string *sign_blob); int ssh_pki_import_signature_blob(const ssh_string sig_blob, const ssh_key pubkey, ssh_signature *psig); int ssh_pki_signature_verify(ssh_session session, ssh_signature sig, const ssh_key key, const unsigned char *digest, size_t dlen); /* SSH Public Key Functions */ int ssh_pki_export_pubkey_blob(const ssh_key key, ssh_string *pblob); int ssh_pki_import_pubkey_blob(const ssh_string key_blob, ssh_key *pkey); int ssh_pki_import_cert_blob(const ssh_string cert_blob, ssh_key *pkey); /* SSH Signing Functions */ ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf, const ssh_key privatekey, enum ssh_digest_e hash_type); ssh_string ssh_pki_do_sign_agent(ssh_session session, struct ssh_buffer_struct *buf, const ssh_key pubkey); ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, const ssh_key privkey, const enum ssh_digest_e digest); /* Temporary functions, to be removed after migration to ssh_key */ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key); ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key); int ssh_key_algorithm_allowed(ssh_session session, const char *type); #endif /* PKI_H_ */ ================================================ FILE: src/libssh/include/libssh/pki_priv.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PKI_PRIV_H_ #define PKI_PRIV_H_ #include "libssh/pki.h" /* defined in bcrypt_pbkdf.c */ int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, uint8_t *key, size_t keylen, unsigned int rounds); #define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----" #define RSA_HEADER_END "-----END RSA PRIVATE KEY-----" #define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----" #define DSA_HEADER_END "-----END DSA PRIVATE KEY-----" #define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----" #define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----" #define OPENSSH_HEADER_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----" #define OPENSSH_HEADER_END "-----END OPENSSH PRIVATE KEY-----" /* Magic defined in OpenSSH/PROTOCOL.key */ #define OPENSSH_AUTH_MAGIC "openssh-key-v1" int pki_key_ecdsa_nid_from_name(const char *name); const char *pki_key_ecdsa_nid_to_name(int nid); const char *ssh_key_signature_to_char(enum ssh_keytypes_e type, enum ssh_digest_e hash_type); enum ssh_digest_e ssh_key_type_to_hash(ssh_session session, enum ssh_keytypes_e type); /* SSH Key Functions */ ssh_key pki_key_dup(const ssh_key key, int demote); int pki_key_generate_rsa(ssh_key key, int parameter); int pki_key_generate_dss(ssh_key key, int parameter); int pki_key_generate_ecdsa(ssh_key key, int parameter); int pki_key_generate_ed25519(ssh_key key); int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); int pki_key_check_hash_compatible(ssh_key key, enum ssh_digest_e hash_type); /* SSH Private Key Functions */ enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey); ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); int pki_import_privkey_buffer(enum ssh_keytypes_e type, ssh_buffer buffer, ssh_key *pkey); /* SSH Public Key Functions */ int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey); int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n); int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e); ssh_string pki_publickey_to_blob(const ssh_key key); /* SSH Private Key Functions */ int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey, ssh_string privkey); int pki_privkey_build_rsa(ssh_key key, ssh_string n, ssh_string e, ssh_string d, ssh_string iqmp, ssh_string p, ssh_string q); int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp); ssh_string pki_publickey_to_blob(const ssh_key key); /* SSH Signature Functions */ ssh_signature pki_sign_data(const ssh_key privkey, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len); int pki_verify_data_signature(ssh_signature signature, const ssh_key pubkey, const unsigned char *input, size_t input_len); ssh_string pki_signature_to_blob(const ssh_signature sign); ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string sig_blob, enum ssh_keytypes_e type, enum ssh_digest_e hash_type); /* SSH Signing Functions */ ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *input, size_t input_len, enum ssh_digest_e hash_type); ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type); int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig, const unsigned char *hash, size_t hlen); int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig, const unsigned char *hash, size_t hlen); int pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what); int pki_ed25519_key_dup(ssh_key new, const ssh_key key); int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key); ssh_string pki_ed25519_signature_to_blob(ssh_signature sig); int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob); int pki_privkey_build_ed25519(ssh_key key, ssh_string pubkey, ssh_string privkey); /* PKI Container OpenSSH */ ssh_key ssh_pki_openssh_pubkey_import(const char *text_key); ssh_key ssh_pki_openssh_privkey_import(const char *text_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data); #endif /* PKI_PRIV_H_ */ ================================================ FILE: src/libssh/include/libssh/poll.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef POLL_H_ #define POLL_H_ #include "config.h" #ifdef HAVE_POLL #include typedef struct pollfd ssh_pollfd_t; #else /* HAVE_POLL */ /* poll emulation support */ typedef struct ssh_pollfd_struct { socket_t fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ } ssh_pollfd_t; typedef unsigned long int nfds_t; #ifdef _WIN32 #ifndef POLLRDNORM #define POLLRDNORM 0x0100 #endif #ifndef POLLRDBAND #define POLLRDBAND 0x0200 #endif #ifndef POLLIN #define POLLIN (POLLRDNORM | POLLRDBAND) #endif #ifndef POLLPRI #define POLLPRI 0x0400 #endif #ifndef POLLWRNORM #define POLLWRNORM 0x0010 #endif #ifndef POLLOUT #define POLLOUT (POLLWRNORM) #endif #ifndef POLLWRBAND #define POLLWRBAND 0x0020 #endif #ifndef POLLERR #define POLLERR 0x0001 #endif #ifndef POLLHUP #define POLLHUP 0x0002 #endif #ifndef POLLNVAL #define POLLNVAL 0x0004 #endif #else /* _WIN32 */ /* poll.c */ #ifndef POLLIN #define POLLIN 0x001 /* There is data to read. */ #endif #ifndef POLLPRI #define POLLPRI 0x002 /* There is urgent data to read. */ #endif #ifndef POLLOUT #define POLLOUT 0x004 /* Writing now will not block. */ #endif #ifndef POLLERR #define POLLERR 0x008 /* Error condition. */ #endif #ifndef POLLHUP #define POLLHUP 0x010 /* Hung up. */ #endif #ifndef POLLNVAL #define POLLNVAL 0x020 /* Invalid polling request. */ #endif #ifndef POLLRDNORM #define POLLRDNORM 0x040 /* mapped to read fds_set */ #endif #ifndef POLLRDBAND #define POLLRDBAND 0x080 /* mapped to exception fds_set */ #endif #ifndef POLLWRNORM #define POLLWRNORM 0x100 /* mapped to write fds_set */ #endif #ifndef POLLWRBAND #define POLLWRBAND 0x200 /* mapped to write fds_set */ #endif #endif /* WIN32 */ #endif /* HAVE_POLL */ void ssh_poll_init(void); void ssh_poll_cleanup(void); int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout); typedef struct ssh_poll_ctx_struct *ssh_poll_ctx; typedef struct ssh_poll_handle_struct *ssh_poll_handle; /** * @brief SSH poll callback. This callback will be used when an event * caught on the socket. * * @param p Poll object this callback belongs to. * @param fd The raw socket. * @param revents The current poll events on the socket. * @param userdata Userdata to be passed to the callback function. * * @return 0 on success, < 0 if you removed the poll object from * its poll context. */ typedef int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, int revents, void *userdata); struct ssh_socket_struct; ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb, void *userdata); void ssh_poll_free(ssh_poll_handle p); ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p); short ssh_poll_get_events(ssh_poll_handle p); void ssh_poll_set_events(ssh_poll_handle p, short events); void ssh_poll_add_events(ssh_poll_handle p, short events); void ssh_poll_remove_events(ssh_poll_handle p, short events); socket_t ssh_poll_get_fd(ssh_poll_handle p); void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd); void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata); ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size); void ssh_poll_ctx_free(ssh_poll_ctx ctx); int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p); int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s); void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p); int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout); ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session); int ssh_event_add_poll(ssh_event event, ssh_poll_handle p); void ssh_event_remove_poll(ssh_event event, ssh_poll_handle p); #endif /* POLL_H_ */ ================================================ FILE: src/libssh/include/libssh/poly1305.h ================================================ /* * Public Domain poly1305 from Andrew Moon * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna */ #ifndef POLY1305_H #define POLY1305_H #define POLY1305_KEYLEN 32 #define POLY1305_TAGLEN 16 void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen, const uint8_t key[POLY1305_KEYLEN]) #ifdef HAVE_GCC_BOUNDED_ATTRIBUTE __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN))) __attribute__((__bounded__(__buffer__, 2, 3))) __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN))) #endif ; #endif /* POLY1305_H */ ================================================ FILE: src/libssh/include/libssh/priv.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * priv.h file * This include file contains everything you shouldn't deal with in * user programs. Consider that anything in this file might change * without notice; libssh.h file will keep backward compatibility * on binary & source */ #ifndef _LIBSSH_PRIV_H #define _LIBSSH_PRIV_H #include #include #include #include #if !defined(HAVE_STRTOULL) # if defined(HAVE___STRTOULL) # define strtoull __strtoull # elif defined(HAVE__STRTOUI64) # define strtoull _strtoui64 # elif defined(__hpux) && defined(__LP64__) # define strtoull strtoul # else # error "no strtoull function found" # endif #endif /* !defined(HAVE_STRTOULL) */ #if !defined(HAVE_STRNDUP) char *strndup(const char *s, size_t n); #endif /* ! HAVE_STRNDUP */ #ifdef HAVE_BYTESWAP_H #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifndef bswap_32 #define bswap_32(x) \ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) #endif #ifdef _WIN32 /* Imitate define of inttypes.h */ # ifndef PRIdS # define PRIdS "Id" # endif # ifndef PRIu64 # if __WORDSIZE == 64 # define PRIu64 "lu" # else # define PRIu64 "llu" # endif /* __WORDSIZE */ # endif /* PRIu64 */ # ifndef PRIu32 # define PRIu32 "u" # endif /* PRIu32 */ # ifndef PRIx64 # if __WORDSIZE == 64 # define PRIx64 "lx" # else # define PRIx64 "llx" # endif /* __WORDSIZE */ # endif /* PRIx64 */ # ifndef PRIx32 # define PRIx32 "x" # endif /* PRIx32 */ # ifdef _MSC_VER # include # include /* va_copy define check */ /* On Microsoft compilers define inline to __inline on all others use inline */ # undef inline # define inline __inline # ifndef va_copy # define va_copy(dest, src) (dest = src) # endif # define strcasecmp _stricmp # define strncasecmp _strnicmp # if ! defined(HAVE_ISBLANK) # define isblank(ch) ((ch) == ' ' || (ch) == '\t' || (ch) == '\n' || (ch) == '\r') # endif # define usleep(X) Sleep(((X)+1000)/1000) # undef strtok_r # define strtok_r strtok_s # if defined(HAVE__SNPRINTF_S) # undef snprintf # define snprintf(d, n, ...) _snprintf_s((d), (n), _TRUNCATE, __VA_ARGS__) # else /* HAVE__SNPRINTF_S */ # if defined(HAVE__SNPRINTF) # undef snprintf # define snprintf _snprintf # else /* HAVE__SNPRINTF */ # if !defined(HAVE_SNPRINTF) # error "no snprintf compatible function found" # endif /* HAVE_SNPRINTF */ # endif /* HAVE__SNPRINTF */ # endif /* HAVE__SNPRINTF_S */ # if defined(HAVE__VSNPRINTF_S) # undef vsnprintf # define vsnprintf(s, n, f, v) _vsnprintf_s((s), (n), _TRUNCATE, (f), (v)) # else /* HAVE__VSNPRINTF_S */ # if defined(HAVE__VSNPRINTF) # undef vsnprintf # define vsnprintf _vsnprintf # else # if !defined(HAVE_VSNPRINTF) # error "No vsnprintf compatible function found" # endif /* HAVE_VSNPRINTF */ # endif /* HAVE__VSNPRINTF */ # endif /* HAVE__VSNPRINTF_S */ # ifndef _SSIZE_T_DEFINED # undef ssize_t # include typedef _W64 SSIZE_T ssize_t; # define _SSIZE_T_DEFINED # endif /* _SSIZE_T_DEFINED */ # endif /* _MSC_VER */ struct timeval; int gettimeofday(struct timeval *__p, void *__t); #define _XCLOSESOCKET closesocket #else /* _WIN32 */ #include #define PRIdS "zd" #define _XCLOSESOCKET close #endif /* _WIN32 */ #include "libssh/libssh.h" #include "libssh/callbacks.h" /* some constants */ #ifndef MAX_PACKAT_LEN #define MAX_PACKET_LEN 262144 #endif #ifndef ERROR_BUFFERLEN #define ERROR_BUFFERLEN 1024 #endif #ifndef CLIENT_BANNER_SSH2 #define CLIENT_BANNER_SSH2 "SSH-2.0-libssh_" SSH_STRINGIFY(LIBSSH_VERSION) #endif /* CLIENT_BANNER_SSH2 */ #ifndef KBDINT_MAX_PROMPT #define KBDINT_MAX_PROMPT 256 /* more than openssh's :) */ #endif #ifndef MAX_BUF_SIZE #define MAX_BUF_SIZE 4096 #endif #ifndef HAVE_COMPILER__FUNC__ # ifdef HAVE_COMPILER__FUNCTION__ # define __func__ __FUNCTION__ # else # error "Your system must provide a __func__ macro" # endif #endif #if defined(HAVE_GCC_THREAD_LOCAL_STORAGE) # define LIBSSH_THREAD __thread #elif defined(HAVE_MSC_THREAD_LOCAL_STORAGE) # define LIBSSH_THREAD __declspec(thread) #else # define LIBSSH_THREAD #endif /* * This makes sure that the compiler doesn't optimize out the code * * Use it in a macro where the provided variable is 'x'. */ #if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION) # define LIBSSH_MEM_PROTECTION __asm__ volatile("" : : "r"(&(x)) : "memory") #else # define LIBSSH_MEM_PROTECTION #endif /* forward declarations */ struct ssh_common_struct; struct ssh_kex_struct; enum ssh_digest_e { SSH_DIGEST_AUTO=0, SSH_DIGEST_SHA1=1, SSH_DIGEST_SHA256, SSH_DIGEST_SHA384, SSH_DIGEST_SHA512, }; int ssh_get_key_params(ssh_session session, ssh_key *privkey, enum ssh_digest_e *digest); /* LOGGING */ void ssh_log_function(int verbosity, const char *function, const char *buffer); #define SSH_LOG(priority, ...) \ _ssh_log(priority, __func__, __VA_ARGS__) /* LEGACY */ void ssh_log_common(struct ssh_common_struct *common, int verbosity, const char *function, const char *format, ...) PRINTF_ATTRIBUTE(4, 5); /* ERROR HANDLING */ /* error handling structure */ struct error_struct { int error_code; char error_buffer[ERROR_BUFFERLEN]; }; #define ssh_set_error(error, code, ...) \ _ssh_set_error(error, code, __func__, __VA_ARGS__) void _ssh_set_error(void *error, int code, const char *function, const char *descr, ...) PRINTF_ATTRIBUTE(4, 5); #define ssh_set_error_oom(error) \ _ssh_set_error_oom(error, __func__) void _ssh_set_error_oom(void *error, const char *function); #define ssh_set_error_invalid(error) \ _ssh_set_error_invalid(error, __func__) void _ssh_set_error_invalid(void *error, const char *function); void ssh_reset_error(void *error); /* server.c */ #ifdef WITH_SERVER int ssh_auth_reply_default(ssh_session session,int partial); int ssh_auth_reply_success(ssh_session session, int partial); #endif /* client.c */ int ssh_send_banner(ssh_session session, int is_server); /* connect.c */ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host, const char *bind_addr, int port); /* in base64.c */ ssh_buffer base64_to_bin(const char *source); uint8_t *bin_to_base64(const uint8_t *source, size_t len); /* gzip.c */ int compress_buffer(ssh_session session,ssh_buffer buf); int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen); /* match.c */ int match_pattern_list(const char *string, const char *pattern, unsigned int len, int dolower); int match_hostname(const char *host, const char *pattern, unsigned int len); /* connector.c */ int ssh_connector_set_event(ssh_connector connector, ssh_event event); int ssh_connector_remove_event(ssh_connector connector); #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /** Free memory space */ #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) /** Zero a structure */ #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) /** Zero a structure given a pointer to the structure */ #define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) /** Get the size of an array */ #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) #ifndef HAVE_EXPLICIT_BZERO void explicit_bzero(void *s, size_t n); #endif /* !HAVE_EXPLICIT_BZERO */ /** * This is a hack to fix warnings. The idea is to use this everywhere that we * get the "discarding const" warning by the compiler. That doesn't actually * fix the real issue, but marks the place and you can search the code for * discard_const. * * Please use this macro only when there is no other way to fix the warning. * We should use this function in only in a very few places. * * Also, please call this via the discard_const_p() macro interface, as that * makes the return type safe. */ #define discard_const(ptr) ((void *)((uintptr_t)(ptr))) /** * Type-safe version of discard_const */ #define discard_const_p(type, ptr) ((type *)discard_const(ptr)) /** * Get the argument cound of variadic arguments */ /* * Since MSVC 2010 there is a bug in passing __VA_ARGS__ to subsequent * macros as a single token, which results in: * warning C4003: not enough actual parameters for macro '_VA_ARG_N' * and incorrect behavior. This fixes issue. */ #define VA_APPLY_VARIADIC_MACRO(macro, tuple) macro tuple #define __VA_NARG__(...) \ (__VA_NARG_(__VA_ARGS__, __RSEQ_N())) #define __VA_NARG_(...) \ VA_APPLY_VARIADIC_MACRO(__VA_ARG_N, (__VA_ARGS__)) #define __VA_ARG_N( \ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N #define __RSEQ_N() \ 63, 62, 61, 60, \ 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0) #ifndef HAVE_HTONLL # ifdef WORDS_BIGENDIAN # define htonll(x) (x) # else # define htonll(x) \ (((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) # endif #endif #ifndef HAVE_NTOHLL # ifdef WORDS_BIGENDIAN # define ntohll(x) (x) # else # define ntohll(x) \ (((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) # endif #endif #ifndef FALL_THROUGH # ifdef HAVE_FALLTHROUGH_ATTRIBUTE # define FALL_THROUGH __attribute__ ((fallthrough)) # else /* HAVE_FALLTHROUGH_ATTRIBUTE */ # define FALL_THROUGH # endif /* HAVE_FALLTHROUGH_ATTRIBUTE */ #endif /* FALL_THROUGH */ #ifndef __attr_unused__ # ifdef HAVE_UNUSED_ATTRIBUTE # define __attr_unused__ __attribute__((unused)) # else /* HAVE_UNUSED_ATTRIBUTE */ # define __attr_unused__ # endif /* HAVE_UNUSED_ATTRIBUTE */ #endif /* __attr_unused__ */ #ifndef UNUSED_PARAM #define UNUSED_PARAM(param) param __attr_unused__ #endif /* UNUSED_PARAM */ #ifndef UNUSED_VAR #define UNUSED_VAR(var) __attr_unused__ var #endif /* UNUSED_VAR */ void ssh_agent_state_free(void *data); bool is_ssh_initialized(void); #endif /* _LIBSSH_PRIV_H */ ================================================ FILE: src/libssh/include/libssh/sc25519.h ================================================ /* $OpenBSD: sc25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/sc25519.h */ #ifndef SC25519_H #define SC25519_H #define sc25519 crypto_sign_ed25519_ref_sc25519 #define shortsc25519 crypto_sign_ed25519_ref_shortsc25519 #define sc25519_from32bytes crypto_sign_ed25519_ref_sc25519_from32bytes #define shortsc25519_from16bytes crypto_sign_ed25519_ref_shortsc25519_from16bytes #define sc25519_from64bytes crypto_sign_ed25519_ref_sc25519_from64bytes #define sc25519_from_shortsc crypto_sign_ed25519_ref_sc25519_from_shortsc #define sc25519_to32bytes crypto_sign_ed25519_ref_sc25519_to32bytes #define sc25519_iszero_vartime crypto_sign_ed25519_ref_sc25519_iszero_vartime #define sc25519_isshort_vartime crypto_sign_ed25519_ref_sc25519_isshort_vartime #define sc25519_lt_vartime crypto_sign_ed25519_ref_sc25519_lt_vartime #define sc25519_add crypto_sign_ed25519_ref_sc25519_add #define sc25519_sub_nored crypto_sign_ed25519_ref_sc25519_sub_nored #define sc25519_mul crypto_sign_ed25519_ref_sc25519_mul #define sc25519_mul_shortsc crypto_sign_ed25519_ref_sc25519_mul_shortsc #define sc25519_window3 crypto_sign_ed25519_ref_sc25519_window3 #define sc25519_window5 crypto_sign_ed25519_ref_sc25519_window5 #define sc25519_2interleave2 crypto_sign_ed25519_ref_sc25519_2interleave2 typedef struct { uint32_t v[32]; } sc25519; typedef struct { uint32_t v[16]; } shortsc25519; void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]); void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]); void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]); void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x); void sc25519_to32bytes(unsigned char r[32], const sc25519 *x); int sc25519_iszero_vartime(const sc25519 *x); int sc25519_isshort_vartime(const sc25519 *x); int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y); void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y); void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y); void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y); void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y); /* Convert s into a representation of the form \sum_{i=0}^{84}r[i]2^3 * with r[i] in {-4,...,3} */ void sc25519_window3(signed char r[85], const sc25519 *s); /* Convert s into a representation of the form \sum_{i=0}^{50}r[i]2^5 * with r[i] in {-16,...,15} */ void sc25519_window5(signed char r[51], const sc25519 *s); void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2); #endif ================================================ FILE: src/libssh/include/libssh/scp.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SCP_H #define _SCP_H enum ssh_scp_states { SSH_SCP_NEW, //Data structure just created SSH_SCP_WRITE_INITED, //Gave our intention to write SSH_SCP_WRITE_WRITING,//File was opened and currently writing SSH_SCP_READ_INITED, //Gave our intention to read SSH_SCP_READ_REQUESTED, //We got a read request SSH_SCP_READ_READING, //File is opened and reading SSH_SCP_ERROR, //Something bad happened SSH_SCP_TERMINATED //Transfer finished }; struct ssh_scp_struct { ssh_session session; int mode; int recursive; ssh_channel channel; char *location; enum ssh_scp_states state; uint64_t filelen; uint64_t processed; enum ssh_scp_request_types request_type; char *request_name; char *warning; int request_mode; }; int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len); int ssh_scp_integer_mode(const char *mode); char *ssh_scp_string_mode(int mode); int ssh_scp_response(ssh_scp scp, char **response); #endif ================================================ FILE: src/libssh/include/libssh/server.h ================================================ /* Public include file for server support */ /* * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @defgroup libssh_server The libssh server API * * @{ */ #ifndef SERVER_H #define SERVER_H #include "libssh/libssh.h" #define SERVERBANNER CLIENTBANNER #ifdef __cplusplus extern "C" { #endif enum ssh_bind_options_e { SSH_BIND_OPTIONS_BINDADDR, SSH_BIND_OPTIONS_BINDPORT, SSH_BIND_OPTIONS_BINDPORT_STR, SSH_BIND_OPTIONS_HOSTKEY, SSH_BIND_OPTIONS_DSAKEY, SSH_BIND_OPTIONS_RSAKEY, SSH_BIND_OPTIONS_BANNER, SSH_BIND_OPTIONS_LOG_VERBOSITY, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, SSH_BIND_OPTIONS_ECDSAKEY, SSH_BIND_OPTIONS_IMPORT_KEY, SSH_BIND_OPTIONS_KEY_EXCHANGE, SSH_BIND_OPTIONS_CIPHERS_C_S, SSH_BIND_OPTIONS_CIPHERS_S_C, SSH_BIND_OPTIONS_HMAC_C_S, SSH_BIND_OPTIONS_HMAC_S_C, SSH_BIND_OPTIONS_CONFIG_DIR, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, SSH_BIND_OPTIONS_PROCESS_CONFIG, }; typedef struct ssh_bind_struct* ssh_bind; /* Callback functions */ /** * @brief Incoming connection callback. This callback is called when a ssh_bind * has a new incoming connection. * @param sshbind Current sshbind session handler * @param userdata Userdata to be passed to the callback function. */ typedef void (*ssh_bind_incoming_connection_callback) (ssh_bind sshbind, void *userdata); /** * @brief These are the callbacks exported by the ssh_bind structure. * * They are called by the server module when events appear on the network. */ struct ssh_bind_callbacks_struct { /** DON'T SET THIS use ssh_callbacks_init() instead. */ size_t size; /** A new connection is available. */ ssh_bind_incoming_connection_callback incoming_connection; }; typedef struct ssh_bind_callbacks_struct *ssh_bind_callbacks; /** * @brief Creates a new SSH server bind. * * @return A newly allocated ssh_bind session pointer. */ LIBSSH_API ssh_bind ssh_bind_new(void); LIBSSH_API int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, const void *value); LIBSSH_API int ssh_bind_options_parse_config(ssh_bind sshbind, const char *filename); /** * @brief Start listening to the socket. * * @param ssh_bind_o The ssh server bind to use. * * @return 0 on success, < 0 on error. */ LIBSSH_API int ssh_bind_listen(ssh_bind ssh_bind_o); /** * @brief Set the callback for this bind. * * @param[in] sshbind The bind to set the callback on. * * @param[in] callbacks An already set up ssh_bind_callbacks instance. * * @param[in] userdata A pointer to private data to pass to the callbacks. * * @return SSH_OK on success, SSH_ERROR if an error occured. * * @code * struct ssh_callbacks_struct cb = { * .userdata = data, * .auth_function = my_auth_function * }; * ssh_callbacks_init(&cb); * ssh_bind_set_callbacks(session, &cb); * @endcode */ LIBSSH_API int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata); /** * @brief Set the session to blocking/nonblocking mode. * * @param ssh_bind_o The ssh server bind to use. * * @param blocking Zero for nonblocking mode. */ LIBSSH_API void ssh_bind_set_blocking(ssh_bind ssh_bind_o, int blocking); /** * @brief Recover the file descriptor from the session. * * @param ssh_bind_o The ssh server bind to get the fd from. * * @return The file descriptor. */ LIBSSH_API socket_t ssh_bind_get_fd(ssh_bind ssh_bind_o); /** * @brief Set the file descriptor for a session. * * @param ssh_bind_o The ssh server bind to set the fd. * * @param fd The file descriptssh_bind B */ LIBSSH_API void ssh_bind_set_fd(ssh_bind ssh_bind_o, socket_t fd); /** * @brief Allow the file descriptor to accept new sessions. * * @param ssh_bind_o The ssh server bind to use. */ LIBSSH_API void ssh_bind_fd_toaccept(ssh_bind ssh_bind_o); /** * @brief Accept an incoming ssh connection and initialize the session. * * @param ssh_bind_o The ssh server bind to accept a connection. * @param session A preallocated ssh session * @see ssh_new * @return SSH_OK when a connection is established */ LIBSSH_API int ssh_bind_accept(ssh_bind ssh_bind_o, ssh_session session); /** * @brief Accept an incoming ssh connection on the given file descriptor * and initialize the session. * * @param ssh_bind_o The ssh server bind to accept a connection. * @param session A preallocated ssh session * @param fd A file descriptor of an already established TCP * inbound connection * @see ssh_new * @see ssh_bind_accept * @return SSH_OK when a connection is established */ LIBSSH_API int ssh_bind_accept_fd(ssh_bind ssh_bind_o, ssh_session session, socket_t fd); LIBSSH_API ssh_gssapi_creds ssh_gssapi_get_creds(ssh_session session); /** * @brief Handles the key exchange and set up encryption * * @param session A connected ssh session * @see ssh_bind_accept * @return SSH_OK if the key exchange was successful */ LIBSSH_API int ssh_handle_key_exchange(ssh_session session); /** * @brief Initialize the set of key exchange, hostkey, ciphers, MACs, and * compression algorithms for the given ssh_session. * * The selection of algorithms and keys used are determined by the * options that are currently set in the given ssh_session structure. * May only be called before the initial key exchange has begun. * * @param session The session structure to initialize. * * @see ssh_handle_key_exchange * @see ssh_options_set * * @return SSH_OK if initialization succeeds. */ LIBSSH_API int ssh_server_init_kex(ssh_session session); /** * @brief Free a ssh servers bind. * * @param ssh_bind_o The ssh server bind to free. */ LIBSSH_API void ssh_bind_free(ssh_bind ssh_bind_o); /** * @brief Set the acceptable authentication methods to be sent to the client. * * * @param[in] session The server session * * @param[in] auth_methods The authentication methods we will support, which * can be bitwise-or'd. * * Supported methods are: * * SSH_AUTH_METHOD_PASSWORD * SSH_AUTH_METHOD_PUBLICKEY * SSH_AUTH_METHOD_HOSTBASED * SSH_AUTH_METHOD_INTERACTIVE * SSH_AUTH_METHOD_GSSAPI_MIC */ LIBSSH_API void ssh_set_auth_methods(ssh_session session, int auth_methods); /********************************************************** * SERVER MESSAGING **********************************************************/ /** * @brief Reply with a standard reject message. * * Use this function if you don't know what to respond or if you want to reject * a request. * * @param[in] msg The message to use for the reply. * * @return 0 on success, -1 on error. * * @see ssh_message_get() */ LIBSSH_API int ssh_message_reply_default(ssh_message msg); /** * @brief Get the name of the authenticated user. * * @param[in] msg The message to get the username from. * * @return The username or NULL if an error occured. * * @see ssh_message_get() * @see ssh_message_type() */ LIBSSH_API const char *ssh_message_auth_user(ssh_message msg); /** * @brief Get the password of the authenticated user. * * @param[in] msg The message to get the password from. * * @return The username or NULL if an error occured. * * @see ssh_message_get() * @see ssh_message_type() */ LIBSSH_API const char *ssh_message_auth_password(ssh_message msg); /** * @brief Get the publickey of the authenticated user. * * If you need the key for later user you should duplicate it. * * @param[in] msg The message to get the public key from. * * @return The public key or NULL. * * @see ssh_key_dup() * @see ssh_key_cmp() * @see ssh_message_get() * @see ssh_message_type() */ LIBSSH_API ssh_key ssh_message_auth_pubkey(ssh_message msg); LIBSSH_API int ssh_message_auth_kbdint_is_response(ssh_message msg); LIBSSH_API enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg); LIBSSH_API int ssh_message_auth_reply_success(ssh_message msg,int partial); LIBSSH_API int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey); LIBSSH_API int ssh_message_auth_reply_pk_ok_simple(ssh_message msg); LIBSSH_API int ssh_message_auth_set_methods(ssh_message msg, int methods); LIBSSH_API int ssh_message_auth_interactive_request(ssh_message msg, const char *name, const char *instruction, unsigned int num_prompts, const char **prompts, char *echo); LIBSSH_API int ssh_message_service_reply_success(ssh_message msg); LIBSSH_API const char *ssh_message_service_service(ssh_message msg); LIBSSH_API int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port); LIBSSH_API void ssh_set_message_callback(ssh_session session, int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data), void *data); LIBSSH_API int ssh_execute_message_callbacks(ssh_session session); LIBSSH_API const char *ssh_message_channel_request_open_originator(ssh_message msg); LIBSSH_API int ssh_message_channel_request_open_originator_port(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_open_destination(ssh_message msg); LIBSSH_API int ssh_message_channel_request_open_destination_port(ssh_message msg); LIBSSH_API ssh_channel ssh_message_channel_request_channel(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_pty_term(ssh_message msg); LIBSSH_API int ssh_message_channel_request_pty_width(ssh_message msg); LIBSSH_API int ssh_message_channel_request_pty_height(ssh_message msg); LIBSSH_API int ssh_message_channel_request_pty_pxwidth(ssh_message msg); LIBSSH_API int ssh_message_channel_request_pty_pxheight(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_env_name(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_env_value(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_command(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_subsystem(ssh_message msg); LIBSSH_API int ssh_message_channel_request_x11_single_connection(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg); LIBSSH_API const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg); LIBSSH_API int ssh_message_channel_request_x11_screen_number(ssh_message msg); LIBSSH_API const char *ssh_message_global_request_address(ssh_message msg); LIBSSH_API int ssh_message_global_request_port(ssh_message msg); LIBSSH_API int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport); LIBSSH_API int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port); LIBSSH_API int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status); LIBSSH_API int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *signum, int core, const char *errmsg, const char *lang); LIBSSH_API int ssh_send_keepalive(ssh_session session); /* deprecated functions */ SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session); SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* SERVER_H */ /** @} */ ================================================ FILE: src/libssh/include/libssh/session.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SESSION_H_ #define SESSION_H_ #include #include "libssh/priv.h" #include "libssh/kex.h" #include "libssh/packet.h" #include "libssh/pcap.h" #include "libssh/auth.h" #include "libssh/channels.h" #include "libssh/poll.h" #include "libssh/config.h" #include "libssh/misc.h" /* These are the different states a SSH session can be into its life */ enum ssh_session_state_e { SSH_SESSION_STATE_NONE=0, SSH_SESSION_STATE_CONNECTING, SSH_SESSION_STATE_SOCKET_CONNECTED, SSH_SESSION_STATE_BANNER_RECEIVED, SSH_SESSION_STATE_INITIAL_KEX, SSH_SESSION_STATE_KEXINIT_RECEIVED, SSH_SESSION_STATE_DH, SSH_SESSION_STATE_AUTHENTICATING, SSH_SESSION_STATE_AUTHENTICATED, SSH_SESSION_STATE_ERROR, SSH_SESSION_STATE_DISCONNECTED }; enum ssh_dh_state_e { DH_STATE_INIT=0, DH_STATE_GROUP_SENT, DH_STATE_REQUEST_SENT, DH_STATE_INIT_SENT, DH_STATE_NEWKEYS_SENT, DH_STATE_FINISHED }; enum ssh_pending_call_e { SSH_PENDING_CALL_NONE = 0, SSH_PENDING_CALL_CONNECT, SSH_PENDING_CALL_AUTH_NONE, SSH_PENDING_CALL_AUTH_PASSWORD, SSH_PENDING_CALL_AUTH_OFFER_PUBKEY, SSH_PENDING_CALL_AUTH_PUBKEY, SSH_PENDING_CALL_AUTH_AGENT, SSH_PENDING_CALL_AUTH_KBDINT_INIT, SSH_PENDING_CALL_AUTH_KBDINT_SEND, SSH_PENDING_CALL_AUTH_GSSAPI_MIC }; /* libssh calls may block an undefined amount of time */ #define SSH_SESSION_FLAG_BLOCKING 1 /* Client successfully authenticated */ #define SSH_SESSION_FLAG_AUTHENTICATED 2 /* codes to use with ssh_handle_packets*() */ /* Infinite timeout */ #define SSH_TIMEOUT_INFINITE -1 /* Use the timeout defined by user if any. Mostly used with new connections */ #define SSH_TIMEOUT_USER -2 /* Use the default timeout, depending on ssh_is_blocking() */ #define SSH_TIMEOUT_DEFAULT -3 /* Don't block at all */ #define SSH_TIMEOUT_NONBLOCKING 0 /* options flags */ /* Authentication with *** allowed */ #define SSH_OPT_FLAG_PASSWORD_AUTH 0x1 #define SSH_OPT_FLAG_PUBKEY_AUTH 0x2 #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 /* extensions flags */ /* negotiation enabled */ #define SSH_EXT_NEGOTIATION 0x01 /* server-sig-algs extension */ #define SSH_EXT_SIG_RSA_SHA256 0x02 #define SSH_EXT_SIG_RSA_SHA512 0x04 /* members that are common to ssh_session and ssh_bind */ struct ssh_common_struct { struct error_struct error; ssh_callbacks callbacks; /* Callbacks to user functions */ int log_verbosity; /* verbosity of the log functions */ }; struct ssh_session_struct { struct ssh_common_struct common; struct ssh_socket_struct *socket; char *serverbanner; char *clientbanner; int protoversion; int server; int client; int openssh; uint32_t send_seq; uint32_t recv_seq; struct ssh_timestamp last_rekey_time; int connected; /* !=0 when the user got a session handle */ int alive; /* two previous are deprecated */ /* int auth_service_asked; */ /* session flags (SSH_SESSION_FLAG_*) */ int flags; /* Extensions negotiated using RFC 8308 */ uint32_t extensions; ssh_string banner; /* that's the issue banner from the server */ char *discon_msg; /* disconnect message from the remote host */ ssh_buffer in_buffer; PACKET in_packet; ssh_buffer out_buffer; struct ssh_list *out_queue; /* This list is used for delaying packets when rekeying is required */ /* the states are used by the nonblocking stuff to remember */ /* where it was before being interrupted */ enum ssh_pending_call_e pending_call_state; enum ssh_session_state_e session_state; enum ssh_packet_state_e packet_state; enum ssh_dh_state_e dh_handshake_state; enum ssh_channel_request_state_e global_req_state; struct ssh_agent_state_struct *agent_state; struct { struct ssh_auth_auto_state_struct *auto_state; enum ssh_auth_service_state_e service_state; enum ssh_auth_state_e state; uint32_t supported_methods; uint32_t current_method; } auth; /* * RFC 4253, 7.1: if the first_kex_packet_follows flag was set in * the received SSH_MSG_KEXINIT, but the guess was wrong, this * field will be set such that the following guessed packet will * be ignored. Once that packet has been received and ignored, * this field is cleared. */ int first_kex_follows_guess_wrong; ssh_buffer in_hashbuf; ssh_buffer out_hashbuf; struct ssh_crypto_struct *current_crypto; struct ssh_crypto_struct *next_crypto; /* next_crypto is going to be used after a SSH2_MSG_NEWKEYS */ struct ssh_list *channels; /* linked list of channels */ int maxchannel; ssh_agent agent; /* ssh agent */ /* keyb interactive data */ struct ssh_kbdint_struct *kbdint; struct ssh_gssapi_struct *gssapi; /* server host keys */ struct { ssh_key rsa_key; ssh_key dsa_key; ssh_key ecdsa_key; ssh_key ed25519_key; /* The type of host key wanted by client */ enum ssh_keytypes_e hostkey; enum ssh_digest_e hostkey_digest; } srv; /* auths accepted by server */ struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata); void *ssh_message_callback_data; ssh_server_callbacks server_callbacks; void (*ssh_connection_callback)( struct ssh_session_struct *session); struct ssh_packet_callbacks_struct default_packet_callbacks; struct ssh_list *packet_callbacks; struct ssh_socket_callbacks_struct socket_callbacks; struct ssh_socket_external_callbacks_struct socket_external_callbacks; ssh_poll_ctx default_poll_ctx; /* options */ #ifdef WITH_PCAP ssh_pcap_context pcap_ctx; /* pcap debugging context */ #endif struct { struct ssh_list *identity; char *username; char *host; char *proxy_host; char *bindaddr; /* bind the client to an ip addr */ char *sshdir; char *knownhosts; char *global_knownhosts; char *wanted_methods[SSH_KEX_METHODS]; char *pubkey_accepted_types; char *ProxyCommand; char *custombanner; unsigned long timeout; /* seconds */ unsigned long timeout_usec; unsigned int port; unsigned int proxy_port; socket_t fd; int StrictHostKeyChecking; char compressionlevel; char *gss_server_identity; char *gss_client_identity; int gss_delegate_creds; int flags; int nodelay; bool config_processed; uint8_t options_seen[SOC_MAX]; uint64_t rekey_data; uint32_t rekey_time; } opts; /* counters */ ssh_counter socket_counter; ssh_counter raw_counter; }; /** @internal * @brief a termination function evaluates the status of an object * @param user[in] object to evaluate * @returns 1 if the polling routine should terminate, 0 instead */ typedef int (*ssh_termination_function)(void *user); int ssh_handle_packets(ssh_session session, int timeout); int ssh_handle_packets_termination(ssh_session session, long timeout, ssh_termination_function fct, void *user); void ssh_socket_exception_callback(int code, int errno_code, void *user); #endif /* SESSION_H_ */ ================================================ FILE: src/libssh/include/libssh/sftp.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @defgroup libssh_sftp The libssh SFTP API * * @brief SFTP handling functions * * SFTP commands are channeled by the ssh sftp subsystem. Every packet is * sent/read using a sftp_packet type structure. Related to these packets, * most of the server answers are messages having an ID and a message * specific part. It is described by sftp_message when reading a message, * the sftp system puts it into the queue, so the process having asked for * it can fetch it, while continuing to read for other messages (it is * unspecified in which order messages may be sent back to the client * * @{ */ #ifndef SFTP_H #define SFTP_H #include #include "libssh.h" #ifdef __cplusplus extern "C" { #endif #ifdef _WIN32 #ifndef uid_t typedef uint32_t uid_t; #endif /* uid_t */ #ifndef gid_t typedef uint32_t gid_t; #endif /* gid_t */ #ifdef _MSC_VER # ifndef _SSIZE_T_DEFINED # undef ssize_t # include typedef _W64 SSIZE_T ssize_t; # define _SSIZE_T_DEFINED # endif /* _SSIZE_T_DEFINED */ #endif /* _MSC_VER */ #endif /* _WIN32 */ #define LIBSFTP_VERSION 3 typedef struct sftp_attributes_struct* sftp_attributes; typedef struct sftp_client_message_struct* sftp_client_message; typedef struct sftp_dir_struct* sftp_dir; typedef struct sftp_ext_struct *sftp_ext; typedef struct sftp_file_struct* sftp_file; typedef struct sftp_message_struct* sftp_message; typedef struct sftp_packet_struct* sftp_packet; typedef struct sftp_request_queue_struct* sftp_request_queue; typedef struct sftp_session_struct* sftp_session; typedef struct sftp_status_message_struct* sftp_status_message; typedef struct sftp_statvfs_struct* sftp_statvfs_t; struct sftp_session_struct { ssh_session session; ssh_channel channel; int server_version; int client_version; int version; sftp_request_queue queue; uint32_t id_counter; int errnum; void **handles; sftp_ext ext; sftp_packet read_packet; }; struct sftp_packet_struct { sftp_session sftp; uint8_t type; ssh_buffer payload; }; /* file handler */ struct sftp_file_struct { sftp_session sftp; char *name; uint64_t offset; ssh_string handle; int eof; int nonblocking; }; struct sftp_dir_struct { sftp_session sftp; char *name; ssh_string handle; /* handle to directory */ ssh_buffer buffer; /* contains raw attributes from server which haven't been parsed */ uint32_t count; /* counts the number of following attributes structures into buffer */ int eof; /* end of directory listing */ }; struct sftp_message_struct { sftp_session sftp; uint8_t packet_type; ssh_buffer payload; uint32_t id; }; /* this is a bunch of all data that could be into a message */ struct sftp_client_message_struct { sftp_session sftp; uint8_t type; uint32_t id; char *filename; /* can be "path" */ uint32_t flags; sftp_attributes attr; ssh_string handle; uint64_t offset; uint32_t len; int attr_num; ssh_buffer attrbuf; /* used by sftp_reply_attrs */ ssh_string data; /* can be newpath of rename() */ ssh_buffer complete_message; /* complete message in case of retransmission*/ char *str_data; /* cstring version of data */ char *submessage; /* for extended messages */ }; struct sftp_request_queue_struct { sftp_request_queue next; sftp_message message; }; /* SSH_FXP_MESSAGE described into .7 page 26 */ struct sftp_status_message_struct { uint32_t id; uint32_t status; ssh_string error_unused; /* not used anymore */ ssh_string lang_unused; /* not used anymore */ char *errormsg; char *langmsg; }; struct sftp_attributes_struct { char *name; char *longname; /* ls -l output on openssh, not reliable else */ uint32_t flags; uint8_t type; uint64_t size; uint32_t uid; uint32_t gid; char *owner; /* set if openssh and version 4 */ char *group; /* set if openssh and version 4 */ uint32_t permissions; uint64_t atime64; uint32_t atime; uint32_t atime_nseconds; uint64_t createtime; uint32_t createtime_nseconds; uint64_t mtime64; uint32_t mtime; uint32_t mtime_nseconds; ssh_string acl; uint32_t extended_count; ssh_string extended_type; ssh_string extended_data; }; /** * @brief SFTP statvfs structure. */ struct sftp_statvfs_struct { uint64_t f_bsize; /** file system block size */ uint64_t f_frsize; /** fundamental fs block size */ uint64_t f_blocks; /** number of blocks (unit f_frsize) */ uint64_t f_bfree; /** free blocks in file system */ uint64_t f_bavail; /** free blocks for non-root */ uint64_t f_files; /** total file inodes */ uint64_t f_ffree; /** free file inodes */ uint64_t f_favail; /** free file inodes for to non-root */ uint64_t f_fsid; /** file system id */ uint64_t f_flag; /** bit mask of f_flag values */ uint64_t f_namemax; /** maximum filename length */ }; /** * @brief Creates a new sftp session. * * This function creates a new sftp session and allocates a new sftp channel * with the server inside of the provided ssh session. This function call is * usually followed by the sftp_init(), which initializes SFTP protocol itself. * * @param session The ssh session to use. * * @return A new sftp session or NULL on error. * * @see sftp_free() * @see sftp_init() */ LIBSSH_API sftp_session sftp_new(ssh_session session); /** * @brief Start a new sftp session with an existing channel. * * @param session The ssh session to use. * @param channel An open session channel with subsystem already allocated * * @return A new sftp session or NULL on error. * * @see sftp_free() */ LIBSSH_API sftp_session sftp_new_channel(ssh_session session, ssh_channel channel); /** * @brief Close and deallocate a sftp session. * * @param sftp The sftp session handle to free. */ LIBSSH_API void sftp_free(sftp_session sftp); /** * @brief Initialize the sftp protocol with the server. * * This function involves the SFTP protocol initialization (as described * in the SFTP specification), including the version and extensions negotiation. * * @param sftp The sftp session to initialize. * * @return 0 on success, < 0 on error with ssh error set. * * @see sftp_new() */ LIBSSH_API int sftp_init(sftp_session sftp); /** * @brief Get the last sftp error. * * Use this function to get the latest error set by a posix like sftp function. * * @param sftp The sftp session where the error is saved. * * @return The saved error (see server responses), < 0 if an error * in the function occured. * * @see Server responses */ LIBSSH_API int sftp_get_error(sftp_session sftp); /** * @brief Get the count of extensions provided by the server. * * @param sftp The sftp session to use. * * @return The count of extensions provided by the server, 0 on error or * not available. */ LIBSSH_API unsigned int sftp_extensions_get_count(sftp_session sftp); /** * @brief Get the name of the extension provided by the server. * * @param sftp The sftp session to use. * * @param indexn The index number of the extension name you want. * * @return The name of the extension. */ LIBSSH_API const char *sftp_extensions_get_name(sftp_session sftp, unsigned int indexn); /** * @brief Get the data of the extension provided by the server. * * This is normally the version number of the extension. * * @param sftp The sftp session to use. * * @param indexn The index number of the extension data you want. * * @return The data of the extension. */ LIBSSH_API const char *sftp_extensions_get_data(sftp_session sftp, unsigned int indexn); /** * @brief Check if the given extension is supported. * * @param sftp The sftp session to use. * * @param name The name of the extension. * * @param data The data of the extension. * * @return 1 if supported, 0 if not. * * Example: * * @code * sftp_extension_supported(sftp, "statvfs@openssh.com", "2"); * @endcode */ LIBSSH_API int sftp_extension_supported(sftp_session sftp, const char *name, const char *data); /** * @brief Open a directory used to obtain directory entries. * * @param session The sftp session handle to open the directory. * @param path The path of the directory to open. * * @return A sftp directory handle or NULL on error with ssh and * sftp error set. * * @see sftp_readdir * @see sftp_closedir */ LIBSSH_API sftp_dir sftp_opendir(sftp_session session, const char *path); /** * @brief Get a single file attributes structure of a directory. * * @param session The sftp session handle to read the directory entry. * @param dir The opened sftp directory handle to read from. * * @return A file attribute structure or NULL at the end of the * directory. * * @see sftp_opendir() * @see sftp_attribute_free() * @see sftp_closedir() */ LIBSSH_API sftp_attributes sftp_readdir(sftp_session session, sftp_dir dir); /** * @brief Tell if the directory has reached EOF (End Of File). * * @param dir The sftp directory handle. * * @return 1 if the directory is EOF, 0 if not. * * @see sftp_readdir() */ LIBSSH_API int sftp_dir_eof(sftp_dir dir); /** * @brief Get information about a file or directory. * * @param session The sftp session handle. * @param path The path to the file or directory to obtain the * information. * * @return The sftp attributes structure of the file or directory, * NULL on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API sftp_attributes sftp_stat(sftp_session session, const char *path); /** * @brief Get information about a file or directory. * * Identical to sftp_stat, but if the file or directory is a symbolic link, * then the link itself is stated, not the file that it refers to. * * @param session The sftp session handle. * @param path The path to the file or directory to obtain the * information. * * @return The sftp attributes structure of the file or directory, * NULL on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API sftp_attributes sftp_lstat(sftp_session session, const char *path); /** * @brief Get information about a file or directory from a file handle. * * @param file The sftp file handle to get the stat information. * * @return The sftp attributes structure of the file or directory, * NULL on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API sftp_attributes sftp_fstat(sftp_file file); /** * @brief Free a sftp attribute structure. * * @param file The sftp attribute structure to free. */ LIBSSH_API void sftp_attributes_free(sftp_attributes file); /** * @brief Close a directory handle opened by sftp_opendir(). * * @param dir The sftp directory handle to close. * * @return Returns SSH_NO_ERROR or SSH_ERROR if an error occured. */ LIBSSH_API int sftp_closedir(sftp_dir dir); /** * @brief Close an open file handle. * * @param file The open sftp file handle to close. * * @return Returns SSH_NO_ERROR or SSH_ERROR if an error occured. * * @see sftp_open() */ LIBSSH_API int sftp_close(sftp_file file); /** * @brief Open a file on the server. * * @param session The sftp session handle. * * @param file The file to be opened. * * @param accesstype Is one of O_RDONLY, O_WRONLY or O_RDWR which request * opening the file read-only,write-only or read/write. * Acesss may also be bitwise-or'd with one or more of * the following: * O_CREAT - If the file does not exist it will be * created. * O_EXCL - When used with O_CREAT, if the file already * exists it is an error and the open will fail. * O_TRUNC - If the file already exists it will be * truncated. * * @param mode Mode specifies the permissions to use if a new file is * created. It is modified by the process's umask in * the usual way: The permissions of the created file are * (mode & ~umask) * * @return A sftp file handle, NULL on error with ssh and sftp * error set. * * @see sftp_get_error() */ LIBSSH_API sftp_file sftp_open(sftp_session session, const char *file, int accesstype, mode_t mode); /** * @brief Make the sftp communication for this file handle non blocking. * * @param[in] handle The file handle to set non blocking. */ LIBSSH_API void sftp_file_set_nonblocking(sftp_file handle); /** * @brief Make the sftp communication for this file handle blocking. * * @param[in] handle The file handle to set blocking. */ LIBSSH_API void sftp_file_set_blocking(sftp_file handle); /** * @brief Read from a file using an opened sftp file handle. * * @param file The opened sftp file handle to be read from. * * @param buf Pointer to buffer to recieve read data. * * @param count Size of the buffer in bytes. * * @return Number of bytes written, < 0 on error with ssh and sftp * error set. * * @see sftp_get_error() */ LIBSSH_API ssize_t sftp_read(sftp_file file, void *buf, size_t count); /** * @brief Start an asynchronous read from a file using an opened sftp file handle. * * Its goal is to avoid the slowdowns related to the request/response pattern * of a synchronous read. To do so, you must call 2 functions: * * sftp_async_read_begin() and sftp_async_read(). * * The first step is to call sftp_async_read_begin(). This function returns a * request identifier. The second step is to call sftp_async_read() using the * returned identifier. * * @param file The opened sftp file handle to be read from. * * @param len Size to read in bytes. * * @return An identifier corresponding to the sent request, < 0 on * error. * * @warning When calling this function, the internal offset is * updated corresponding to the len parameter. * * @warning A call to sftp_async_read_begin() sends a request to * the server. When the server answers, libssh allocates * memory to store it until sftp_async_read() is called. * Not calling sftp_async_read() will lead to memory * leaks. * * @see sftp_async_read() * @see sftp_open() */ LIBSSH_API int sftp_async_read_begin(sftp_file file, uint32_t len); /** * @brief Wait for an asynchronous read to complete and save the data. * * @param file The opened sftp file handle to be read from. * * @param data Pointer to buffer to recieve read data. * * @param len Size of the buffer in bytes. It should be bigger or * equal to the length parameter of the * sftp_async_read_begin() call. * * @param id The identifier returned by the sftp_async_read_begin() * function. * * @return Number of bytes read, 0 on EOF, SSH_ERROR if an error * occured, SSH_AGAIN if the file is opened in nonblocking * mode and the request hasn't been executed yet. * * @warning A call to this function with an invalid identifier * will never return. * * @see sftp_async_read_begin() */ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_t id); /** * @brief Write to a file using an opened sftp file handle. * * @param file Open sftp file handle to write to. * * @param buf Pointer to buffer to write data. * * @param count Size of buffer in bytes. * * @return Number of bytes written, < 0 on error with ssh and sftp * error set. * * @see sftp_open() * @see sftp_read() * @see sftp_close() */ LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count); /** * @brief Seek to a specific location in a file. * * @param file Open sftp file handle to seek in. * * @param new_offset Offset in bytes to seek. * * @return 0 on success, < 0 on error. */ LIBSSH_API int sftp_seek(sftp_file file, uint32_t new_offset); /** * @brief Seek to a specific location in a file. This is the * 64bit version. * * @param file Open sftp file handle to seek in. * * @param new_offset Offset in bytes to seek. * * @return 0 on success, < 0 on error. */ LIBSSH_API int sftp_seek64(sftp_file file, uint64_t new_offset); /** * @brief Report current byte position in file. * * @param file Open sftp file handle. * * @return The offset of the current byte relative to the beginning * of the file associated with the file descriptor. < 0 on * error. */ LIBSSH_API unsigned long sftp_tell(sftp_file file); /** * @brief Report current byte position in file. * * @param file Open sftp file handle. * * @return The offset of the current byte relative to the beginning * of the file associated with the file descriptor. < 0 on * error. */ LIBSSH_API uint64_t sftp_tell64(sftp_file file); /** * @brief Rewinds the position of the file pointer to the beginning of the * file. * * @param file Open sftp file handle. */ LIBSSH_API void sftp_rewind(sftp_file file); /** * @brief Unlink (delete) a file. * * @param sftp The sftp session handle. * * @param file The file to unlink/delete. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_unlink(sftp_session sftp, const char *file); /** * @brief Remove a directoy. * * @param sftp The sftp session handle. * * @param directory The directory to remove. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_rmdir(sftp_session sftp, const char *directory); /** * @brief Create a directory. * * @param sftp The sftp session handle. * * @param directory The directory to create. * * @param mode Specifies the permissions to use. It is modified by the * process's umask in the usual way: * The permissions of the created file are (mode & ~umask) * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode); /** * @brief Rename or move a file or directory. * * @param sftp The sftp session handle. * * @param original The original url (source url) of file or directory to * be moved. * * @param newname The new url (destination url) of the file or directory * after the move. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_rename(sftp_session sftp, const char *original, const char *newname); /** * @brief Set file attributes on a file, directory or symbolic link. * * @param sftp The sftp session handle. * * @param file The file which attributes should be changed. * * @param attr The file attributes structure with the attributes set * which should be changed. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr); /** * @brief Change the file owner and group * * @param sftp The sftp session handle. * * @param file The file which owner and group should be changed. * * @param owner The new owner which should be set. * * @param group The new group which should be set. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t group); /** * @brief Change permissions of a file * * @param sftp The sftp session handle. * * @param file The file which owner and group should be changed. * * @param mode Specifies the permissions to use. It is modified by the * process's umask in the usual way: * The permissions of the created file are (mode & ~umask) * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_chmod(sftp_session sftp, const char *file, mode_t mode); /** * @brief Change the last modification and access time of a file. * * @param sftp The sftp session handle. * * @param file The file which owner and group should be changed. * * @param times A timeval structure which contains the desired access * and modification time. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_utimes(sftp_session sftp, const char *file, const struct timeval *times); /** * @brief Create a symbolic link. * * @param sftp The sftp session handle. * * @param target Specifies the target of the symlink. * * @param dest Specifies the path name of the symlink to be created. * * @return 0 on success, < 0 on error with ssh and sftp error set. * * @see sftp_get_error() */ LIBSSH_API int sftp_symlink(sftp_session sftp, const char *target, const char *dest); /** * @brief Read the value of a symbolic link. * * @param sftp The sftp session handle. * * @param path Specifies the path name of the symlink to be read. * * @return The target of the link, NULL on error. * * @see sftp_get_error() */ LIBSSH_API char *sftp_readlink(sftp_session sftp, const char *path); /** * @brief Get information about a mounted file system. * * @param sftp The sftp session handle. * * @param path The pathname of any file within the mounted file system. * * @return A statvfs structure or NULL on error. * * @see sftp_get_error() */ LIBSSH_API sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path); /** * @brief Get information about a mounted file system. * * @param file An opened file. * * @return A statvfs structure or NULL on error. * * @see sftp_get_error() */ LIBSSH_API sftp_statvfs_t sftp_fstatvfs(sftp_file file); /** * @brief Free the memory of an allocated statvfs. * * @param statvfs_o The statvfs to free. */ LIBSSH_API void sftp_statvfs_free(sftp_statvfs_t statvfs_o); /** * @brief Synchronize a file's in-core state with storage device * * This calls the "fsync@openssh.com" extention. You should check if the * extensions is supported using: * * @code * int supported = sftp_extension_supported(sftp, "fsync@openssh.com", "1"); * @endcode * * @param file The opened sftp file handle to sync * * @return 0 on success, < 0 on error with ssh and sftp error set. */ LIBSSH_API int sftp_fsync(sftp_file file); /** * @brief Canonicalize a sftp path. * * @param sftp The sftp session handle. * * @param path The path to be canonicalized. * * @return A pointer to the newly allocated canonicalized path, * NULL on error. The caller needs to free the memory * using ssh_string_free_char(). */ LIBSSH_API char *sftp_canonicalize_path(sftp_session sftp, const char *path); /** * @brief Get the version of the SFTP protocol supported by the server * * @param sftp The sftp session handle. * * @return The server version. */ LIBSSH_API int sftp_server_version(sftp_session sftp); #ifdef WITH_SERVER /** * @brief Create a new sftp server session. * * @param session The ssh session to use. * * @param chan The ssh channel to use. * * @return A new sftp server session. */ LIBSSH_API sftp_session sftp_server_new(ssh_session session, ssh_channel chan); /** * @brief Intialize the sftp server. * * @param sftp The sftp session to init. * * @return 0 on success, < 0 on error. */ LIBSSH_API int sftp_server_init(sftp_session sftp); /** * @brief Close and deallocate a sftp server session. * * @param sftp The sftp session handle to free. */ LIBSSH_API void sftp_server_free(sftp_session sftp); #endif /* WITH_SERVER */ /* sftpserver.c */ LIBSSH_API sftp_client_message sftp_get_client_message(sftp_session sftp); LIBSSH_API void sftp_client_message_free(sftp_client_message msg); LIBSSH_API uint8_t sftp_client_message_get_type(sftp_client_message msg); LIBSSH_API const char *sftp_client_message_get_filename(sftp_client_message msg); LIBSSH_API void sftp_client_message_set_filename(sftp_client_message msg, const char *newname); LIBSSH_API const char *sftp_client_message_get_data(sftp_client_message msg); LIBSSH_API uint32_t sftp_client_message_get_flags(sftp_client_message msg); LIBSSH_API const char *sftp_client_message_get_submessage(sftp_client_message msg); LIBSSH_API int sftp_send_client_message(sftp_session sftp, sftp_client_message msg); LIBSSH_API int sftp_reply_name(sftp_client_message msg, const char *name, sftp_attributes attr); LIBSSH_API int sftp_reply_handle(sftp_client_message msg, ssh_string handle); LIBSSH_API ssh_string sftp_handle_alloc(sftp_session sftp, void *info); LIBSSH_API int sftp_reply_attr(sftp_client_message msg, sftp_attributes attr); LIBSSH_API void *sftp_handle(sftp_session sftp, ssh_string handle); LIBSSH_API int sftp_reply_status(sftp_client_message msg, uint32_t status, const char *message); LIBSSH_API int sftp_reply_names_add(sftp_client_message msg, const char *file, const char *longname, sftp_attributes attr); LIBSSH_API int sftp_reply_names(sftp_client_message msg); LIBSSH_API int sftp_reply_data(sftp_client_message msg, const void *data, int len); LIBSSH_API void sftp_handle_remove(sftp_session sftp, void *handle); /* SFTP commands and constants */ #define SSH_FXP_INIT 1 #define SSH_FXP_VERSION 2 #define SSH_FXP_OPEN 3 #define SSH_FXP_CLOSE 4 #define SSH_FXP_READ 5 #define SSH_FXP_WRITE 6 #define SSH_FXP_LSTAT 7 #define SSH_FXP_FSTAT 8 #define SSH_FXP_SETSTAT 9 #define SSH_FXP_FSETSTAT 10 #define SSH_FXP_OPENDIR 11 #define SSH_FXP_READDIR 12 #define SSH_FXP_REMOVE 13 #define SSH_FXP_MKDIR 14 #define SSH_FXP_RMDIR 15 #define SSH_FXP_REALPATH 16 #define SSH_FXP_STAT 17 #define SSH_FXP_RENAME 18 #define SSH_FXP_READLINK 19 #define SSH_FXP_SYMLINK 20 #define SSH_FXP_STATUS 101 #define SSH_FXP_HANDLE 102 #define SSH_FXP_DATA 103 #define SSH_FXP_NAME 104 #define SSH_FXP_ATTRS 105 #define SSH_FXP_EXTENDED 200 #define SSH_FXP_EXTENDED_REPLY 201 /* attributes */ /* sftp draft is completely braindead : version 3 and 4 have different flags for same constants */ /* and even worst, version 4 has same flag for 2 different constants */ /* follow up : i won't develop any sftp4 compliant library before having a clarification */ #define SSH_FILEXFER_ATTR_SIZE 0x00000001 #define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 #define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008 #define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008 #define SSH_FILEXFER_ATTR_CREATETIME 0x00000010 #define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020 #define SSH_FILEXFER_ATTR_ACL 0x00000040 #define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080 #define SSH_FILEXFER_ATTR_SUBSECOND_TIMES 0x00000100 #define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 #define SSH_FILEXFER_ATTR_UIDGID 0x00000002 /* types */ #define SSH_FILEXFER_TYPE_REGULAR 1 #define SSH_FILEXFER_TYPE_DIRECTORY 2 #define SSH_FILEXFER_TYPE_SYMLINK 3 #define SSH_FILEXFER_TYPE_SPECIAL 4 #define SSH_FILEXFER_TYPE_UNKNOWN 5 /** * @name Server responses * * @brief Responses returned by the sftp server. * @{ */ /** No error */ #define SSH_FX_OK 0 /** End-of-file encountered */ #define SSH_FX_EOF 1 /** File doesn't exist */ #define SSH_FX_NO_SUCH_FILE 2 /** Permission denied */ #define SSH_FX_PERMISSION_DENIED 3 /** Generic failure */ #define SSH_FX_FAILURE 4 /** Garbage received from server */ #define SSH_FX_BAD_MESSAGE 5 /** No connection has been set up */ #define SSH_FX_NO_CONNECTION 6 /** There was a connection, but we lost it */ #define SSH_FX_CONNECTION_LOST 7 /** Operation not supported by the server */ #define SSH_FX_OP_UNSUPPORTED 8 /** Invalid file handle */ #define SSH_FX_INVALID_HANDLE 9 /** No such file or directory path exists */ #define SSH_FX_NO_SUCH_PATH 10 /** An attempt to create an already existing file or directory has been made */ #define SSH_FX_FILE_ALREADY_EXISTS 11 /** We are trying to write on a write-protected filesystem */ #define SSH_FX_WRITE_PROTECT 12 /** No media in remote drive */ #define SSH_FX_NO_MEDIA 13 /** @} */ /* file flags */ #define SSH_FXF_READ 0x01 #define SSH_FXF_WRITE 0x02 #define SSH_FXF_APPEND 0x04 #define SSH_FXF_CREAT 0x08 #define SSH_FXF_TRUNC 0x10 #define SSH_FXF_EXCL 0x20 #define SSH_FXF_TEXT 0x40 /* file type flags */ #define SSH_S_IFMT 00170000 #define SSH_S_IFSOCK 0140000 #define SSH_S_IFLNK 0120000 #define SSH_S_IFREG 0100000 #define SSH_S_IFBLK 0060000 #define SSH_S_IFDIR 0040000 #define SSH_S_IFCHR 0020000 #define SSH_S_IFIFO 0010000 /* rename flags */ #define SSH_FXF_RENAME_OVERWRITE 0x00000001 #define SSH_FXF_RENAME_ATOMIC 0x00000002 #define SSH_FXF_RENAME_NATIVE 0x00000004 #define SFTP_OPEN SSH_FXP_OPEN #define SFTP_CLOSE SSH_FXP_CLOSE #define SFTP_READ SSH_FXP_READ #define SFTP_WRITE SSH_FXP_WRITE #define SFTP_LSTAT SSH_FXP_LSTAT #define SFTP_FSTAT SSH_FXP_FSTAT #define SFTP_SETSTAT SSH_FXP_SETSTAT #define SFTP_FSETSTAT SSH_FXP_FSETSTAT #define SFTP_OPENDIR SSH_FXP_OPENDIR #define SFTP_READDIR SSH_FXP_READDIR #define SFTP_REMOVE SSH_FXP_REMOVE #define SFTP_MKDIR SSH_FXP_MKDIR #define SFTP_RMDIR SSH_FXP_RMDIR #define SFTP_REALPATH SSH_FXP_REALPATH #define SFTP_STAT SSH_FXP_STAT #define SFTP_RENAME SSH_FXP_RENAME #define SFTP_READLINK SSH_FXP_READLINK #define SFTP_SYMLINK SSH_FXP_SYMLINK #define SFTP_EXTENDED SSH_FXP_EXTENDED /* openssh flags */ #define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */ #define SSH_FXE_STATVFS_ST_NOSUID 0x2 /* no setuid */ #ifdef __cplusplus } #endif #endif /* SFTP_H */ /** @} */ ================================================ FILE: src/libssh/include/libssh/sftp_priv.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SFTP_PRIV_H #define SFTP_PRIV_H sftp_packet sftp_packet_read(sftp_session sftp); ssize_t sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload); void sftp_packet_free(sftp_packet packet); int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr); sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf, int expectname); #endif /* SFTP_PRIV_H */ ================================================ FILE: src/libssh/include/libssh/socket.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SOCKET_H_ #define SOCKET_H_ #include "libssh/callbacks.h" struct ssh_poll_handle_struct; /* socket.c */ struct ssh_socket_struct; typedef struct ssh_socket_struct* ssh_socket; int ssh_socket_init(void); void ssh_socket_cleanup(void); ssh_socket ssh_socket_new(ssh_session session); void ssh_socket_reset(ssh_socket s); void ssh_socket_free(ssh_socket s); void ssh_socket_set_fd(ssh_socket s, socket_t fd); socket_t ssh_socket_get_fd(ssh_socket s); #ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path); void ssh_execute_command(const char *command, socket_t in, socket_t out); int ssh_socket_connect_proxycommand(ssh_socket s, const char *command); #endif void ssh_socket_close(ssh_socket s); int ssh_socket_write(ssh_socket s,const void *buffer, int len); int ssh_socket_is_open(ssh_socket s); int ssh_socket_fd_isset(ssh_socket s, fd_set *set); void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd); void ssh_socket_set_fd_in(ssh_socket s, socket_t fd); void ssh_socket_set_fd_out(ssh_socket s, socket_t fd); int ssh_socket_nonblocking_flush(ssh_socket s); void ssh_socket_set_write_wontblock(ssh_socket s); void ssh_socket_set_read_wontblock(ssh_socket s); void ssh_socket_set_except(ssh_socket s); int ssh_socket_get_status(ssh_socket s); int ssh_socket_get_poll_flags(ssh_socket s); int ssh_socket_buffered_write_bytes(ssh_socket s); int ssh_socket_data_available(ssh_socket s); int ssh_socket_data_writable(ssh_socket s); int ssh_socket_set_nonblocking(socket_t fd); int ssh_socket_set_blocking(socket_t fd); void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks); void ssh_socket_set_external_callbacks(ssh_socket s, ssh_socket_external_callbacks external_callbacks); int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s); struct ssh_poll_handle_struct * ssh_socket_get_poll_handle(ssh_socket s); int ssh_socket_connect(ssh_socket s, const char *host, uint16_t port, const char *bind_addr); #endif /* SOCKET_H_ */ ================================================ FILE: src/libssh/include/libssh/ssh2.h ================================================ #ifndef __SSH2_H #define __SSH2_H #define SSH2_MSG_DISCONNECT 1 #define SSH2_MSG_IGNORE 2 #define SSH2_MSG_UNIMPLEMENTED 3 #define SSH2_MSG_DEBUG 4 #define SSH2_MSG_SERVICE_REQUEST 5 #define SSH2_MSG_SERVICE_ACCEPT 6 #define SSH2_MSG_EXT_INFO 7 #define SSH2_MSG_KEXINIT 20 #define SSH2_MSG_NEWKEYS 21 #define SSH2_MSG_KEXDH_INIT 30 #define SSH2_MSG_KEXDH_REPLY 31 #define SSH2_MSG_KEX_ECDH_INIT 30 #define SSH2_MSG_KEX_ECDH_REPLY 31 #define SSH2_MSG_ECMQV_INIT 30 #define SSH2_MSG_ECMQV_REPLY 31 #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 #define SSH2_MSG_KEX_DH_GEX_GROUP 31 #define SSH2_MSG_KEX_DH_GEX_INIT 32 #define SSH2_MSG_KEX_DH_GEX_REPLY 33 #define SSH2_MSG_KEX_DH_GEX_REQUEST 34 #define SSH2_MSG_USERAUTH_REQUEST 50 #define SSH2_MSG_USERAUTH_FAILURE 51 #define SSH2_MSG_USERAUTH_SUCCESS 52 #define SSH2_MSG_USERAUTH_BANNER 53 #define SSH2_MSG_USERAUTH_PK_OK 60 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 #define SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 #define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 #define SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 #define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 #define SSH2_MSG_USERAUTH_GSSAPI_MIC 66 #define SSH2_MSG_GLOBAL_REQUEST 80 #define SSH2_MSG_REQUEST_SUCCESS 81 #define SSH2_MSG_REQUEST_FAILURE 82 #define SSH2_MSG_CHANNEL_OPEN 90 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 #define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 #define SSH2_MSG_CHANNEL_DATA 94 #define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 #define SSH2_MSG_CHANNEL_EOF 96 #define SSH2_MSG_CHANNEL_CLOSE 97 #define SSH2_MSG_CHANNEL_REQUEST 98 #define SSH2_MSG_CHANNEL_SUCCESS 99 #define SSH2_MSG_CHANNEL_FAILURE 100 #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 #define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 #define SSH2_DISCONNECT_RESERVED 4 #define SSH2_DISCONNECT_MAC_ERROR 5 #define SSH2_DISCONNECT_COMPRESSION_ERROR 6 #define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 #define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 #define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 #define SSH2_DISCONNECT_CONNECTION_LOST 10 #define SSH2_DISCONNECT_BY_APPLICATION 11 #define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 #define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 #define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 #define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH2_OPEN_CONNECT_FAILED 2 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 #define SSH2_OPEN_RESOURCE_SHORTAGE 4 #define SSH2_EXTENDED_DATA_STDERR 1 #endif ================================================ FILE: src/libssh/include/libssh/string.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef STRING_H_ #define STRING_H_ #include "libssh/priv.h" /* must be 32 bits number + immediately our data */ #ifdef _MSC_VER #pragma pack(1) #endif struct ssh_string_struct { uint32_t size; unsigned char data[1]; } #if defined(__GNUC__) __attribute__ ((packed)) #endif #ifdef _MSC_VER #pragma pack() #endif ; #endif /* STRING_H_ */ ================================================ FILE: src/libssh/include/libssh/threads.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef THREADS_H_ #define THREADS_H_ #include #include #if HAVE_PTHREAD #include #define SSH_MUTEX pthread_mutex_t #if defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) #define SSH_MUTEX_STATIC_INIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #else #define SSH_MUTEX_STATIC_INIT PTHREAD_MUTEX_INITIALIZER #endif #elif (defined _WIN32) || (defined _WIN64) #include #include #define SSH_MUTEX CRITICAL_SECTION * #define SSH_MUTEX_STATIC_INIT NULL #else # define SSH_MUTEX void * #define SSH_MUTEX_STATIC_INIT NULL #endif int ssh_threads_init(void); void ssh_threads_finalize(void); const char *ssh_threads_get_type(void); void ssh_mutex_lock(SSH_MUTEX *mutex); void ssh_mutex_unlock(SSH_MUTEX *mutex); struct ssh_threads_callbacks_struct *ssh_threads_get_default(void); int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks); void crypto_thread_finalize(void); #endif /* THREADS_H_ */ ================================================ FILE: src/libssh/include/libssh/token.h ================================================ /* * token.h - Tokens list handling * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef TOKEN_H_ #define TOKEN_H_ struct ssh_tokens_st { char *buffer; char **tokens; }; struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator); void ssh_tokens_free(struct ssh_tokens_st *tokens); char *ssh_find_matching(const char *available_d, const char *preferred_d); char *ssh_find_all_matching(const char *available_d, const char *preferred_d); char *ssh_remove_duplicates(const char *list); char *ssh_append_without_duplicates(const char *list, const char *appended_list); #endif /* TOKEN_H_ */ ================================================ FILE: src/libssh/include/libssh/wrapper.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef WRAPPER_H_ #define WRAPPER_H_ #include #include "config.h" #include "libssh/libssh.h" #include "libssh/libcrypto.h" #include "libssh/libgcrypt.h" #include "libssh/libmbedcrypto.h" enum ssh_kdf_digest { SSH_KDF_SHA1=1, SSH_KDF_SHA256, SSH_KDF_SHA384, SSH_KDF_SHA512 }; enum ssh_hmac_e { SSH_HMAC_SHA1 = 1, SSH_HMAC_SHA1_96, SSH_HMAC_SHA256, SSH_HMAC_SHA512, SSH_HMAC_MD5, SSH_HMAC_MD5_96, SSH_HMAC_AEAD_POLY1305, SSH_HMAC_AEAD_GCM }; enum ssh_des_e { SSH_3DES, SSH_DES }; struct ssh_hmac_struct { const char* name; enum ssh_hmac_e hmac_type; bool etm; }; enum ssh_crypto_direction_e { SSH_DIRECTION_IN = 1, SSH_DIRECTION_OUT = 2, SSH_DIRECTION_BOTH = 3, }; struct ssh_cipher_struct; struct ssh_crypto_struct; typedef struct ssh_mac_ctx_struct *ssh_mac_ctx; MD5CTX md5_init(void); void md5_update(MD5CTX c, const void *data, unsigned long len); void md5_final(unsigned char *md,MD5CTX c); SHACTX sha1_init(void); void sha1_update(SHACTX c, const void *data, unsigned long len); void sha1_final(unsigned char *md,SHACTX c); void sha1(const unsigned char *digest,int len,unsigned char *hash); SHA256CTX sha256_init(void); void sha256_update(SHA256CTX c, const void *data, unsigned long len); void sha256_final(unsigned char *md,SHA256CTX c); void sha256(const unsigned char *digest, int len, unsigned char *hash); SHA384CTX sha384_init(void); void sha384_update(SHA384CTX c, const void *data, unsigned long len); void sha384_final(unsigned char *md,SHA384CTX c); void sha384(const unsigned char *digest, int len, unsigned char *hash); SHA512CTX sha512_init(void); void sha512_update(SHA512CTX c, const void *data, unsigned long len); void sha512_final(unsigned char *md,SHA512CTX c); void sha512(const unsigned char *digest, int len, unsigned char *hash); void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen); EVPCTX evp_init(int nid); void evp_update(EVPCTX ctx, const void *data, unsigned long len); void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen); HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type); void hmac_update(HMACCTX c, const void *data, unsigned long len); void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len, enum ssh_hmac_e type); size_t hmac_digest_len(enum ssh_hmac_e type); size_t hmac_key_len(enum ssh_hmac_e type); int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len); int crypt_set_algorithms_client(ssh_session session); int crypt_set_algorithms_server(ssh_session session); struct ssh_crypto_struct *crypto_new(void); void crypto_free(struct ssh_crypto_struct *crypto); void ssh_reseed(void); int ssh_crypto_init(void); void ssh_crypto_finalize(void); void ssh_cipher_clear(struct ssh_cipher_struct *cipher); struct ssh_hmac_struct *ssh_get_hmactab(void); struct ssh_cipher_struct *ssh_get_ciphertab(void); const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm); #endif /* WRAPPER_H_ */ ================================================ FILE: src/libssh/libssh.pc.cmake ================================================ Name: ${PROJECT_NAME} Description: The SSH Library Version: ${PROJECT_VERSION} Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -lssh Cflags: -I${CMAKE_INSTALL_FULL_INCLUDEDIR} ================================================ FILE: src/libssh/src/ABI/current ================================================ 4.8.6 ================================================ FILE: src/libssh/src/ABI/libssh-4.5.0.symbols ================================================ ssh_set_server_callbacks ssh_set_callbacks ssh_set_channel_callbacks ssh_add_channel_callbacks ssh_remove_channel_callbacks ssh_threads_set_callbacks ssh_threads_get_pthread ssh_threads_get_noop ssh_set_log_callback ssh_get_log_callback ssh_auth_list ssh_userauth_offer_pubkey ssh_userauth_pubkey ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_privatekey_file buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_forward_accept channel_close channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_shell channel_request_send_signal channel_request_sftp channel_request_subsystem channel_request_x11 channel_send_eof channel_select channel_set_blocking channel_write privatekey_free privatekey_from_file publickey_free ssh_publickey_to_file publickey_from_file publickey_from_privatekey publickey_to_string ssh_try_publickey_from_file ssh_privatekey_type ssh_get_pubkey ssh_message_retrieve ssh_message_auth_publickey string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ssh_blocking_flush ssh_channel_accept_x11 ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_timeout ssh_channel_read_nonblocking ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_shell ssh_channel_request_send_signal ssh_channel_request_send_break ssh_channel_request_sftp ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_request_auth_agent ssh_channel_send_eof ssh_channel_select ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_write ssh_channel_write_stderr ssh_channel_window_size ssh_basename ssh_clean_pubkey_hash ssh_connect ssh_connector_new ssh_connector_free ssh_connector_set_in_channel ssh_connector_set_out_channel ssh_connector_set_in_fd ssh_connector_set_out_fd ssh_copyright ssh_disconnect ssh_dirname ssh_finalize ssh_channel_accept_forward ssh_channel_cancel_forward ssh_channel_listen_forward ssh_free ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_hexa ssh_get_issue_banner ssh_get_openssh_version ssh_get_server_publickey ssh_get_publickey_hash ssh_get_pubkey_hash ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_get_publickey ssh_get_random ssh_get_version ssh_get_status ssh_get_poll_flags ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_knownhosts_entry_free ssh_known_hosts_parse_line ssh_session_has_known_hosts_entry ssh_session_export_known_hosts_entry ssh_session_update_known_hosts ssh_session_is_known_server ssh_set_log_level ssh_get_log_level ssh_get_log_userdata ssh_set_log_userdata _ssh_log ssh_log ssh_message_channel_request_open_reply_accept ssh_message_channel_request_reply_success ssh_message_free ssh_message_get ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_options_get ssh_options_get_port ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_key_new ssh_key_free ssh_key_type ssh_key_type_to_char ssh_key_type_from_name ssh_key_is_public ssh_key_is_private ssh_key_cmp ssh_pki_generate ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_export_privkey_file ssh_pki_copy_cert_to_privkey ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hexa ssh_send_ignore ssh_send_debug ssh_gssapi_set_creds ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_service_request ssh_set_agent_channel ssh_set_agent_socket ssh_set_blocking ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_silent_disconnect ssh_set_pcap_file ssh_userauth_none ssh_userauth_list ssh_userauth_try_publickey ssh_userauth_publickey ssh_userauth_agent ssh_userauth_publickey_auto ssh_userauth_password ssh_userauth_kbdint ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_setanswer ssh_userauth_gssapi ssh_version ssh_write_knownhost ssh_dump_knownhost ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_from_char ssh_string_len ssh_string_new ssh_string_get_char ssh_string_to_char ssh_string_free_char ssh_getpass ssh_event_new ssh_event_add_fd ssh_event_add_session ssh_event_add_connector ssh_event_dopoll ssh_event_remove_fd ssh_event_remove_session ssh_event_remove_connector ssh_event_free ssh_get_clientbanner ssh_get_serverbanner ssh_get_kex_algo ssh_get_cipher_in ssh_get_cipher_out ssh_get_hmac_in ssh_get_hmac_out ssh_buffer_new ssh_buffer_free ssh_buffer_reinit ssh_buffer_add_data ssh_buffer_get_data ssh_buffer_get ssh_buffer_get_len ssh_bind_new ssh_bind_options_set ssh_bind_listen ssh_bind_set_callbacks ssh_bind_set_blocking ssh_bind_get_fd ssh_bind_set_fd ssh_bind_fd_toaccept ssh_bind_accept ssh_bind_accept_fd ssh_gssapi_get_creds ssh_handle_key_exchange ssh_server_init_kex ssh_bind_free ssh_set_auth_methods ssh_message_reply_default ssh_message_auth_user ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_kbdint_is_response ssh_message_auth_publickey_state ssh_message_auth_reply_success ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_set_methods ssh_message_auth_interactive_request ssh_message_service_reply_success ssh_message_service_service ssh_message_global_request_reply_success ssh_set_message_callback ssh_execute_message_callbacks ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_channel ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_pxheight ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_command ssh_message_channel_request_subsystem ssh_message_channel_request_x11_single_connection ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_screen_number ssh_message_global_request_address ssh_message_global_request_port ssh_channel_open_reverse_forward ssh_channel_request_send_exit_status ssh_channel_request_send_exit_signal ssh_send_keepalive ssh_accept channel_write_stderr sftp_new sftp_new_channel sftp_free sftp_init sftp_get_error sftp_extensions_get_count sftp_extensions_get_name sftp_extensions_get_data sftp_extension_supported sftp_opendir sftp_readdir sftp_dir_eof sftp_stat sftp_lstat sftp_fstat sftp_attributes_free sftp_closedir sftp_close sftp_open sftp_file_set_nonblocking sftp_file_set_blocking sftp_read sftp_async_read_begin sftp_async_read sftp_write sftp_seek sftp_seek64 sftp_tell sftp_tell64 sftp_rewind sftp_unlink sftp_rmdir sftp_mkdir sftp_rename sftp_setstat sftp_chown sftp_chmod sftp_utimes sftp_symlink sftp_readlink sftp_statvfs sftp_fstatvfs sftp_statvfs_free sftp_fsync sftp_canonicalize_path sftp_server_version sftp_server_new sftp_server_init sftp_get_client_message sftp_client_message_free sftp_client_message_get_type sftp_client_message_get_filename sftp_client_message_set_filename sftp_client_message_get_data sftp_client_message_get_flags sftp_send_client_message sftp_reply_name sftp_reply_handle sftp_handle_alloc sftp_reply_attr sftp_handle sftp_reply_status sftp_reply_names_add sftp_reply_names sftp_reply_data sftp_handle_remove ================================================ FILE: src/libssh/src/ABI/libssh-4.5.1.symbols ================================================ ================================================ FILE: src/libssh/src/ABI/libssh-4.6.0.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.7.0.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.7.1.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.7.2.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.7.3.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.7.4.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.0.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.1.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.2.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.3.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.4.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.5.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/ABI/libssh-4.8.6.symbols ================================================ _ssh_log buffer_free buffer_get buffer_get_len buffer_new channel_accept_x11 channel_change_pty_size channel_close channel_forward_accept channel_forward_cancel channel_forward_listen channel_free channel_get_exit_status channel_get_session channel_is_closed channel_is_eof channel_is_open channel_new channel_open_forward channel_open_session channel_poll channel_read channel_read_buffer channel_read_nonblocking channel_request_env channel_request_exec channel_request_pty channel_request_pty_size channel_request_send_signal channel_request_sftp channel_request_shell channel_request_subsystem channel_request_x11 channel_select channel_send_eof channel_set_blocking channel_write channel_write_stderr privatekey_free privatekey_from_file publickey_free publickey_from_file publickey_from_privatekey publickey_to_string sftp_async_read sftp_async_read_begin sftp_attributes_free sftp_canonicalize_path sftp_chmod sftp_chown sftp_client_message_free sftp_client_message_get_data sftp_client_message_get_filename sftp_client_message_get_flags sftp_client_message_get_submessage sftp_client_message_get_type sftp_client_message_set_filename sftp_close sftp_closedir sftp_dir_eof sftp_extension_supported sftp_extensions_get_count sftp_extensions_get_data sftp_extensions_get_name sftp_file_set_blocking sftp_file_set_nonblocking sftp_free sftp_fstat sftp_fstatvfs sftp_fsync sftp_get_client_message sftp_get_error sftp_handle sftp_handle_alloc sftp_handle_remove sftp_init sftp_lstat sftp_mkdir sftp_new sftp_new_channel sftp_open sftp_opendir sftp_read sftp_readdir sftp_readlink sftp_rename sftp_reply_attr sftp_reply_data sftp_reply_handle sftp_reply_name sftp_reply_names sftp_reply_names_add sftp_reply_status sftp_rewind sftp_rmdir sftp_seek sftp_seek64 sftp_send_client_message sftp_server_free sftp_server_init sftp_server_new sftp_server_version sftp_setstat sftp_stat sftp_statvfs sftp_statvfs_free sftp_symlink sftp_tell sftp_tell64 sftp_unlink sftp_utimes sftp_write ssh_accept ssh_add_channel_callbacks ssh_auth_list ssh_basename ssh_bind_accept ssh_bind_accept_fd ssh_bind_fd_toaccept ssh_bind_free ssh_bind_get_fd ssh_bind_listen ssh_bind_new ssh_bind_options_parse_config ssh_bind_options_set ssh_bind_set_blocking ssh_bind_set_callbacks ssh_bind_set_fd ssh_blocking_flush ssh_buffer_add_data ssh_buffer_free ssh_buffer_get ssh_buffer_get_data ssh_buffer_get_len ssh_buffer_new ssh_buffer_reinit ssh_channel_accept_forward ssh_channel_accept_x11 ssh_channel_cancel_forward ssh_channel_change_pty_size ssh_channel_close ssh_channel_free ssh_channel_get_exit_status ssh_channel_get_session ssh_channel_is_closed ssh_channel_is_eof ssh_channel_is_open ssh_channel_listen_forward ssh_channel_new ssh_channel_open_auth_agent ssh_channel_open_forward ssh_channel_open_forward_unix ssh_channel_open_reverse_forward ssh_channel_open_session ssh_channel_open_x11 ssh_channel_poll ssh_channel_poll_timeout ssh_channel_read ssh_channel_read_nonblocking ssh_channel_read_timeout ssh_channel_request_auth_agent ssh_channel_request_env ssh_channel_request_exec ssh_channel_request_pty ssh_channel_request_pty_size ssh_channel_request_send_break ssh_channel_request_send_exit_signal ssh_channel_request_send_exit_status ssh_channel_request_send_signal ssh_channel_request_sftp ssh_channel_request_shell ssh_channel_request_subsystem ssh_channel_request_x11 ssh_channel_select ssh_channel_send_eof ssh_channel_set_blocking ssh_channel_set_counter ssh_channel_window_size ssh_channel_write ssh_channel_write_stderr ssh_clean_pubkey_hash ssh_connect ssh_connector_free ssh_connector_new ssh_connector_set_in_channel ssh_connector_set_in_fd ssh_connector_set_out_channel ssh_connector_set_out_fd ssh_copyright ssh_dirname ssh_disconnect ssh_dump_knownhost ssh_event_add_connector ssh_event_add_fd ssh_event_add_session ssh_event_dopoll ssh_event_free ssh_event_new ssh_event_remove_connector ssh_event_remove_fd ssh_event_remove_session ssh_execute_message_callbacks ssh_finalize ssh_forward_accept ssh_forward_cancel ssh_forward_listen ssh_free ssh_get_cipher_in ssh_get_cipher_out ssh_get_clientbanner ssh_get_disconnect_message ssh_get_error ssh_get_error_code ssh_get_fd ssh_get_fingerprint_hash ssh_get_hexa ssh_get_hmac_in ssh_get_hmac_out ssh_get_issue_banner ssh_get_kex_algo ssh_get_log_callback ssh_get_log_level ssh_get_log_userdata ssh_get_openssh_version ssh_get_poll_flags ssh_get_pubkey ssh_get_pubkey_hash ssh_get_publickey ssh_get_publickey_hash ssh_get_random ssh_get_server_publickey ssh_get_serverbanner ssh_get_status ssh_get_version ssh_getpass ssh_gssapi_get_creds ssh_gssapi_set_creds ssh_handle_key_exchange ssh_init ssh_is_blocking ssh_is_connected ssh_is_server_known ssh_key_cmp ssh_key_free ssh_key_is_private ssh_key_is_public ssh_key_new ssh_key_type ssh_key_type_from_name ssh_key_type_to_char ssh_known_hosts_parse_line ssh_knownhosts_entry_free ssh_log ssh_message_auth_interactive_request ssh_message_auth_kbdint_is_response ssh_message_auth_password ssh_message_auth_pubkey ssh_message_auth_publickey ssh_message_auth_publickey_state ssh_message_auth_reply_pk_ok ssh_message_auth_reply_pk_ok_simple ssh_message_auth_reply_success ssh_message_auth_set_methods ssh_message_auth_user ssh_message_channel_request_channel ssh_message_channel_request_command ssh_message_channel_request_env_name ssh_message_channel_request_env_value ssh_message_channel_request_open_destination ssh_message_channel_request_open_destination_port ssh_message_channel_request_open_originator ssh_message_channel_request_open_originator_port ssh_message_channel_request_open_reply_accept ssh_message_channel_request_open_reply_accept_channel ssh_message_channel_request_pty_height ssh_message_channel_request_pty_pxheight ssh_message_channel_request_pty_pxwidth ssh_message_channel_request_pty_term ssh_message_channel_request_pty_width ssh_message_channel_request_reply_success ssh_message_channel_request_subsystem ssh_message_channel_request_x11_auth_cookie ssh_message_channel_request_x11_auth_protocol ssh_message_channel_request_x11_screen_number ssh_message_channel_request_x11_single_connection ssh_message_free ssh_message_get ssh_message_global_request_address ssh_message_global_request_port ssh_message_global_request_reply_success ssh_message_reply_default ssh_message_retrieve ssh_message_service_reply_success ssh_message_service_service ssh_message_subtype ssh_message_type ssh_mkdir ssh_new ssh_options_copy ssh_options_get ssh_options_get_port ssh_options_getopt ssh_options_parse_config ssh_options_set ssh_pcap_file_close ssh_pcap_file_free ssh_pcap_file_new ssh_pcap_file_open ssh_pki_copy_cert_to_privkey ssh_pki_export_privkey_base64 ssh_pki_export_privkey_file ssh_pki_export_privkey_to_pubkey ssh_pki_export_pubkey_base64 ssh_pki_export_pubkey_file ssh_pki_generate ssh_pki_import_cert_base64 ssh_pki_import_cert_file ssh_pki_import_privkey_base64 ssh_pki_import_privkey_file ssh_pki_import_pubkey_base64 ssh_pki_import_pubkey_file ssh_pki_key_ecdsa_name ssh_print_hash ssh_print_hexa ssh_privatekey_type ssh_publickey_to_file ssh_remove_channel_callbacks ssh_scp_accept_request ssh_scp_close ssh_scp_deny_request ssh_scp_free ssh_scp_init ssh_scp_leave_directory ssh_scp_new ssh_scp_pull_request ssh_scp_push_directory ssh_scp_push_file ssh_scp_push_file64 ssh_scp_read ssh_scp_request_get_filename ssh_scp_request_get_permissions ssh_scp_request_get_size ssh_scp_request_get_size64 ssh_scp_request_get_warning ssh_scp_write ssh_select ssh_send_debug ssh_send_ignore ssh_send_keepalive ssh_server_init_kex ssh_service_request ssh_session_export_known_hosts_entry ssh_session_get_known_hosts_entry ssh_session_has_known_hosts_entry ssh_session_is_known_server ssh_session_update_known_hosts ssh_set_agent_channel ssh_set_agent_socket ssh_set_auth_methods ssh_set_blocking ssh_set_callbacks ssh_set_channel_callbacks ssh_set_counters ssh_set_fd_except ssh_set_fd_toread ssh_set_fd_towrite ssh_set_log_callback ssh_set_log_level ssh_set_log_userdata ssh_set_message_callback ssh_set_pcap_file ssh_set_server_callbacks ssh_silent_disconnect ssh_string_burn ssh_string_copy ssh_string_data ssh_string_fill ssh_string_free ssh_string_free_char ssh_string_from_char ssh_string_get_char ssh_string_len ssh_string_new ssh_string_to_char ssh_threads_get_default ssh_threads_get_noop ssh_threads_get_pthread ssh_threads_set_callbacks ssh_try_publickey_from_file ssh_userauth_agent ssh_userauth_agent_pubkey ssh_userauth_autopubkey ssh_userauth_gssapi ssh_userauth_kbdint ssh_userauth_kbdint_getanswer ssh_userauth_kbdint_getinstruction ssh_userauth_kbdint_getname ssh_userauth_kbdint_getnanswers ssh_userauth_kbdint_getnprompts ssh_userauth_kbdint_getprompt ssh_userauth_kbdint_setanswer ssh_userauth_list ssh_userauth_none ssh_userauth_offer_pubkey ssh_userauth_password ssh_userauth_privatekey_file ssh_userauth_pubkey ssh_userauth_publickey ssh_userauth_publickey_auto ssh_userauth_try_publickey ssh_version ssh_write_knownhost string_burn string_copy string_data string_fill string_free string_from_char string_len string_new string_to_char ================================================ FILE: src/libssh/src/CMakeLists.txt ================================================ set(LIBSSH_PUBLIC_INCLUDE_DIRS ${libssh_SOURCE_DIR}/include) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_REQUIRED_LIBRARIES} ) if (WIN32) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ws2_32 ) endif (WIN32) if (OPENSSL_CRYPTO_LIBRARY) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARY} ) endif (OPENSSL_CRYPTO_LIBRARY) if (MBEDTLS_CRYPTO_LIBRARY) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${MBEDTLS_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${MBEDTLS_CRYPTO_LIBRARY} ) endif (MBEDTLS_CRYPTO_LIBRARY) if (GCRYPT_LIBRARIES) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${GCRYPT_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${GCRYPT_LIBRARIES}) endif() if (WITH_ZLIB) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${ZLIB_LIBRARY} ) endif (WITH_ZLIB) if (WITH_GSSAPI AND GSSAPI_FOUND) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${GSSAPI_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${GSSAPI_LIBRARIES} ) endif (WITH_GSSAPI AND GSSAPI_FOUND) if (WITH_NACL AND NACL_FOUND) set(LIBSSH_PRIVATE_INCLUDE_DIRS ${LIBSSH_PRIVATE_INCLUDE_DIRS} ${NACL_INCLUDE_DIR} ) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} ${NACL_LIBRARY} ) endif (WITH_NACL AND NACL_FOUND) if (MINGW AND Threads_FOUND) set(LIBSSH_LINK_LIBRARIES ${LIBSSH_LINK_LIBRARIES} Threads::Threads ) endif() if (BUILD_STATIC_LIB) set(LIBSSH_STATIC_LIBRARY ssh_static CACHE INTERNAL "libssh static library" ) endif (BUILD_STATIC_LIB) set(libssh_SRCS agent.c auth.c base64.c bignum.c buffer.c callbacks.c channels.c client.c config.c connect.c connector.c curve25519.c dh.c ecdh.c error.c getpass.c init.c kdf.c kex.c known_hosts.c knownhosts.c legacy.c log.c match.c messages.c misc.c options.c packet.c packet_cb.c packet_crypt.c pcap.c pki.c pki_container_openssh.c poll.c session.c scp.c socket.c string.c threads.c wrapper.c external/bcrypt_pbkdf.c external/blowfish.c external/chacha.c external/poly1305.c chachapoly.c config_parser.c token.c pki_ed25519_common.c ) if (DEFAULT_C_NO_DEPRECATION_FLAGS) set_source_files_properties(known_hosts.c PROPERTIES COMPILE_FLAGS ${DEFAULT_C_NO_DEPRECATION_FLAGS}) endif() if (CMAKE_USE_PTHREADS_INIT) set(libssh_SRCS ${libssh_SRCS} threads/noop.c threads/pthread.c ) elseif (CMAKE_USE_WIN32_THREADS_INIT) set(libssh_SRCS ${libssh_SRCS} threads/noop.c threads/winlocks.c ) else() set(libssh_SRCS ${libssh_SRCS} threads/noop.c ) endif() if (WITH_GCRYPT) set(libssh_SRCS ${libssh_SRCS} threads/libgcrypt.c libgcrypt.c gcrypt_missing.c pki_gcrypt.c ecdh_gcrypt.c dh_key.c pki_ed25519.c external/ed25519.c external/fe25519.c external/ge25519.c external/sc25519.c ) elseif (WITH_MBEDTLS) set(libssh_SRCS ${libssh_SRCS} threads/mbedtls.c libmbedcrypto.c mbedcrypto_missing.c pki_mbedcrypto.c ecdh_mbedcrypto.c dh_key.c pki_ed25519.c external/ed25519.c external/fe25519.c external/ge25519.c external/sc25519.c ) else (WITH_GCRYPT) set(libssh_SRCS ${libssh_SRCS} threads/libcrypto.c pki_crypto.c ecdh_crypto.c libcrypto.c dh_crypto.c ) if (NOT HAVE_OPENSSL_ED25519) set(libssh_SRCS ${libssh_SRCS} pki_ed25519.c external/ed25519.c external/fe25519.c external/ge25519.c external/sc25519.c ) endif (NOT HAVE_OPENSSL_ED25519) if(OPENSSL_VERSION VERSION_LESS "1.1.0") set(libssh_SRCS ${libssh_SRCS} libcrypto-compat.c) endif() endif (WITH_GCRYPT) if (WITH_SFTP) set(libssh_SRCS ${libssh_SRCS} sftp.c ) if (WITH_SERVER) set(libssh_SRCS ${libssh_SRCS} sftpserver.c ) endif (WITH_SERVER) endif (WITH_SFTP) if (WITH_SERVER) set(libssh_SRCS ${libssh_SRCS} server.c bind.c bind_config.c ) endif (WITH_SERVER) if (WITH_GEX) set(libssh_SRCS ${libssh_SRCS} dh-gex.c ) endif (WITH_GEX) if (WITH_ZLIB) set(libssh_SRCS ${libssh_SRCS} gzip.c ) endif(WITH_ZLIB) if (WITH_GSSAPI AND GSSAPI_FOUND) set(libssh_SRCS ${libssh_SRCS} gssapi.c ) endif (WITH_GSSAPI AND GSSAPI_FOUND) if (NOT WITH_NACL) if (NOT HAVE_OPENSSL_ED25519) set(libssh_SRCS ${libssh_SRCS} external/curve25519_ref.c ) endif (NOT HAVE_OPENSSL_ED25519) endif (NOT WITH_NACL) # Set the path to the default map file set(MAP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.map") if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND) # Get the list of header files get_file_list(dev_header_list DIRECTORIES "${LIBSSH_PUBLIC_INCLUDE_DIRS}/libssh" FILES_PATTERNS "*.h") # Extract the symbols marked as "LIBSSH_API" from the header files extract_symbols("${PROJECT_NAME}_dev.symbols" HEADERS_LIST dev_header_list FILTER_PATTERN "LIBSSH_API") if (WITH_ABI_BREAK) set(ALLOW_ABI_BREAK "BREAK_ABI") endif() # Generate the symbol version map file generate_map_file("${PROJECT_NAME}_dev.map" SYMBOLS "${PROJECT_NAME}_dev.symbols" RELEASE_NAME_VERSION ${PROJECT_NAME}_AFTER_${LIBRARY_VERSION} CURRENT_MAP ${MAP_PATH} ${ALLOW_ABI_BREAK}) set(libssh_SRCS ${libssh_SRCS} ${PROJECT_NAME}_dev.map ) endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND) # This gets built as a static library, if -DBUILD_SHARED_LIBS=OFF is passed to # cmake. add_library(ssh ${libssh_SRCS}) target_compile_options(ssh PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -D_GNU_SOURCE) target_include_directories(ssh PUBLIC $ $ PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS}) target_link_libraries(ssh PRIVATE ${LIBSSH_LINK_LIBRARIES}) if (WIN32 AND NOT BUILD_SHARED_LIBS) set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC") endif () add_library(ssh::ssh ALIAS ssh) if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT) if (ABIMAP_FOUND) # Change path to devel map file set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map") endif (ABIMAP_FOUND) set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${MAP_PATH}\"") endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT) set_target_properties(ssh PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} DEFINE_SYMBOL LIBSSH_EXPORTS ) if (WITH_VISIBILITY_HIDDEN) set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-fvisibility=hidden") endif (WITH_VISIBILITY_HIDDEN) if (MINGW) set_target_properties(ssh PROPERTIES LINK_FLAGS "-Wl,--enable-stdcall-fixup") set_target_properties(ssh PROPERTIES COMPILE_FLAGS "-D_POSIX_SOURCE") endif () install(TARGETS ssh EXPORT libssh-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) install(EXPORT libssh-config DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) if (BUILD_STATIC_LIB) add_library(ssh-static STATIC ${libssh_SRCS}) target_compile_options(ssh-static PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -D_GNU_SOURCE) target_include_directories(ssh-static PUBLIC $ $ PRIVATE ${LIBSSH_PRIVATE_INCLUDE_DIRS}) target_link_libraries(ssh-static PUBLIC ${LIBSSH_LINK_LIBRARIES}) add_library(ssh::static ALIAS ssh-static) if (MSVC) set(OUTPUT_SUFFIX static) else (MSVC) set(OUTPUT_SUFFIX ) endif (MSVC) set_target_properties( ssh-static PROPERTIES VERSION ${LIBRARY_VERSION} SOVERSION ${LIBRARY_SOVERSION} OUTPUT_NAME ssh ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_SUFFIX} ) if (WIN32) set_target_properties( ssh-static PROPERTIES COMPILE_FLAGS "-DLIBSSH_STATIC" ) endif (WIN32) endif (BUILD_STATIC_LIB) message(STATUS "Threads_FOUND=${Threads_FOUND}") ================================================ FILE: src/libssh/src/agent.c ================================================ /* * agent.c - ssh agent functions * * This file is part of the SSH Library * * Copyright (c) 2008-2013 by Andreas Schneider * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* This file is based on authfd.c from OpenSSH */ /* * How does the ssh-agent work? * * a) client sends a request to get a list of all keys * the agent returns the count and all public keys * b) iterate over them to check if the server likes one * c) the client sends a sign request to the agent * type, pubkey as blob, data to sign, flags * the agent returns the signed data */ #include "config.h" #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "libssh/agent.h" #include "libssh/priv.h" #include "libssh/socket.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/poll.h" #include "libssh/pki.h" #include "libssh/bytearray.h" #ifndef _WIN32 #include #include #else #include #endif #define AGENT_MSG_MAXLEN 256 * 1024 /* macro to check for "agent failure" message */ #define agent_failed(x) \ (((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \ ((x) == SSH2_AGENT_FAILURE)) #ifndef _WIN32 static size_t atomicio(struct ssh_agent_struct *agent, void *buf, size_t n, int do_read) { char *b = buf; size_t pos = 0; ssize_t res; ssh_pollfd_t pfd; ssh_channel channel = agent->channel; socket_t fd; /* Using a socket ? */ if (channel == NULL) { fd = ssh_socket_get_fd(agent->sock); pfd.fd = fd; pfd.events = do_read ? POLLIN : POLLOUT; while (n > pos) { if (do_read) { res = read(fd, b + pos, n - pos); } else { res = write(fd, b + pos, n - pos); } switch (res) { case -1: if (errno == EINTR) { continue; } #ifdef EWOULDBLOCK if (errno == EAGAIN || errno == EWOULDBLOCK) { #else if (errno == EAGAIN) { #endif (void) ssh_poll(&pfd, 1, -1); continue; } return 0; case 0: /* read returns 0 on end-of-file */ errno = do_read ? 0 : EPIPE; return pos; default: pos += (size_t) res; } } return pos; } else { /* using an SSH channel */ while (n > pos){ if (do_read) res = ssh_channel_read(channel,b + pos, n-pos, 0); else res = ssh_channel_write(channel, b+pos, n-pos); if (res == SSH_AGAIN) continue; if (res == SSH_ERROR) return 0; pos += (size_t)res; } return pos; } } #endif ssh_agent ssh_agent_new(struct ssh_session_struct *session) { ssh_agent agent = NULL; agent = malloc(sizeof(struct ssh_agent_struct)); if (agent == NULL) { return NULL; } ZERO_STRUCTP(agent); agent->count = 0; #ifndef _WIN32 agent->sock = ssh_socket_new(session); if (agent->sock == NULL) { SAFE_FREE(agent); return NULL; } agent->channel = NULL; #endif return agent; } static void agent_set_channel(struct ssh_agent_struct *agent, ssh_channel channel){ agent->channel = channel; } /** @brief sets the SSH agent channel. * The SSH agent channel will be used to authenticate this client using * an agent through a channel, from another session. The most likely use * is to implement SSH Agent forwarding into a SSH proxy. * @param[in] channel a SSH channel from another session. * @returns SSH_OK in case of success * SSH_ERROR in case of an error */ int ssh_set_agent_channel(ssh_session session, ssh_channel channel){ if (!session) return SSH_ERROR; if (!session->agent){ ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent"); return SSH_ERROR; } agent_set_channel(session->agent, channel); return SSH_OK; } #ifndef _WIN32 /** @brief sets the SSH agent socket. * The SSH agent will be used to authenticate this client using * the given socket to communicate with the ssh-agent. The caller * is responsible for connecting to the socket prior to calling * this function. * @returns SSH_OK in case of success * SSH_ERROR in case of an error */ int ssh_set_agent_socket(ssh_session session, socket_t fd){ if (!session) return SSH_ERROR; if (!session->agent){ ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent"); return SSH_ERROR; } ssh_socket_set_fd(session->agent->sock, fd); return SSH_OK; } void ssh_agent_close(struct ssh_agent_struct *agent) { if (agent == NULL) { return; } ssh_socket_close(agent->sock); } #endif void ssh_agent_free(ssh_agent agent) { if (agent) { if (agent->ident) { SSH_BUFFER_FREE(agent->ident); } #ifndef _WIN32 if (agent->sock) { ssh_agent_close(agent); ssh_socket_free(agent->sock); } #endif SAFE_FREE(agent); } } #ifndef _WIN32 static int agent_connect(ssh_session session) { const char *auth_sock = NULL; if (session == NULL || session->agent == NULL) { return -1; } if (session->agent->channel != NULL) return 0; auth_sock = getenv("SSH_AUTH_SOCK"); if (auth_sock && *auth_sock) { if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) { return -1; } return 0; } return -1; } #endif #if 0 static int agent_decode_reply(struct ssh_session_struct *session, int type) { switch (type) { case SSH_AGENT_FAILURE: case SSH2_AGENT_FAILURE: case SSH_COM_AGENT2_FAILURE: ssh_log(session, SSH_LOG_RARE, "SSH_AGENT_FAILURE"); return 0; case SSH_AGENT_SUCCESS: return 1; default: ssh_set_error(session, SSH_FATAL, "Bad response from authentication agent: %d", type); break; } return -1; } #endif #ifndef _WIN32 static int agent_talk(struct ssh_session_struct *session, struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) { uint32_t len = 0; uint8_t payload[1024] = {0}; len = ssh_buffer_get_len(request); SSH_LOG(SSH_LOG_TRACE, "Request length: %u", len); PUSH_BE_U32(payload, 0, len); /* send length and then the request packet */ if (atomicio(session->agent, payload, 4, 0) == 4) { if (atomicio(session->agent, ssh_buffer_get(request), len, 0) != len) { SSH_LOG(SSH_LOG_WARN, "atomicio sending request failed: %s", strerror(errno)); return -1; } } else { SSH_LOG(SSH_LOG_WARN, "atomicio sending request length failed: %s", strerror(errno)); return -1; } /* wait for response, read the length of the response packet */ if (atomicio(session->agent, payload, 4, 1) != 4) { SSH_LOG(SSH_LOG_WARN, "atomicio read response length failed: %s", strerror(errno)); return -1; } len = PULL_BE_U32(payload, 0); if (len > AGENT_MSG_MAXLEN) { ssh_set_error(session, SSH_FATAL, "Authentication response too long: %u", len); return -1; } SSH_LOG(SSH_LOG_TRACE, "Response length: %u", len); while (len > 0) { size_t n = len; if (n > sizeof(payload)) { n = sizeof(payload); } if (atomicio(session->agent, payload, n, 1) != n) { SSH_LOG(SSH_LOG_WARN, "Error reading response from authentication socket."); return -1; } if (ssh_buffer_add_data(reply, payload, n) < 0) { SSH_LOG(SSH_LOG_WARN, "Not enough space"); return -1; } len -= n; } return 0; } #else #define AGENT_COPYDATA_ID 0x804e50ba; static int agent_talk(struct ssh_session_struct *session, struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) { HWND hwnd = FindWindow("Pageant", "Pageant"); if (hwnd == NULL) { ssh_set_error(session, SSH_FATAL, "Pageant message window not found: %u", GetLastError()); return -1; } char map_name[39]; sprintf(map_name, "libssh_agent_%08x_%016zx", GetCurrentProcessId(), (size_t)session->agent); HANDLE hmap = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, AGENT_MSG_MAXLEN + sizeof(uint32_t), map_name); if (hmap == NULL) { ssh_set_error(session, SSH_FATAL, "Failed to create file mapping: %u", GetLastError()); return -1; } char *buf = MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (buf == NULL) { ssh_set_error(session, SSH_FATAL, "Failed to map the file mapping into memory: %u", GetLastError()); CloseHandle(hmap); return -1; } uint32_t len = ssh_buffer_get_len(request); SSH_LOG(SSH_LOG_TRACE, "Request length: %u", len); PUSH_BE_U32(buf, 0, len); memcpy(buf + sizeof(uint32_t), ssh_buffer_get(request), len); COPYDATASTRUCT data; data.dwData = AGENT_COPYDATA_ID; data.cbData = strlen(map_name) + 1; data.lpData = map_name; if (SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data) < 0) { ssh_set_error(session, SSH_FATAL, "Pageant returned an error"); UnmapViewOfFile(buf); CloseHandle(hmap); return -1; } len = PULL_BE_U32(buf, 0); if (len > AGENT_MSG_MAXLEN) { ssh_set_error(session, SSH_FATAL, "Authentication response too long: %u", len); UnmapViewOfFile(buf); CloseHandle(hmap); return -1; } SSH_LOG(SSH_LOG_TRACE, "Response length: %u", len); int rc = ssh_buffer_add_data(reply, buf + sizeof(uint32_t), len); UnmapViewOfFile(buf); CloseHandle(hmap); if (rc < 0) { SSH_LOG(SSH_LOG_WARN, "Not enough space"); return -1; } return 0; } #endif /* _WIN32 */ uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session) { ssh_buffer request = NULL; ssh_buffer reply = NULL; unsigned int type = 0; uint32_t count = 0; int rc; /* send message to the agent requesting the list of identities */ request = ssh_buffer_new(); if (request == NULL) { ssh_set_error_oom(session); return 0; } if (ssh_buffer_add_u8(request, SSH2_AGENTC_REQUEST_IDENTITIES) < 0) { ssh_set_error_oom(session); SSH_BUFFER_FREE(request); return 0; } reply = ssh_buffer_new(); if (reply == NULL) { SSH_BUFFER_FREE(request); ssh_set_error(session, SSH_FATAL, "Not enough space"); return 0; } if (agent_talk(session, request, reply) < 0) { SSH_BUFFER_FREE(request); SSH_BUFFER_FREE(reply); return 0; } SSH_BUFFER_FREE(request); /* get message type and verify the answer */ rc = ssh_buffer_get_u8(reply, (uint8_t *) &type); if (rc != sizeof(uint8_t)) { ssh_set_error(session, SSH_FATAL, "Bad authentication reply size: %d", rc); SSH_BUFFER_FREE(reply); return 0; } #ifdef WORDS_BIGENDIAN type = bswap_32(type); #endif SSH_LOG(SSH_LOG_WARN, "Answer type: %d, expected answer: %d", type, SSH2_AGENT_IDENTITIES_ANSWER); if (agent_failed(type)) { SSH_BUFFER_FREE(reply); return 0; } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) { ssh_set_error(session, SSH_FATAL, "Bad authentication reply message type: %u", type); SSH_BUFFER_FREE(reply); return 0; } rc = ssh_buffer_get_u32(reply, &count); if (rc != 4) { ssh_set_error(session, SSH_FATAL, "Failed to read count"); SSH_BUFFER_FREE(reply); return 0; } session->agent->count = ntohl(count); SSH_LOG(SSH_LOG_DEBUG, "Agent count: %d", session->agent->count); if (session->agent->count > 1024) { ssh_set_error(session, SSH_FATAL, "Too many identities in authentication reply: %d", session->agent->count); SSH_BUFFER_FREE(reply); return 0; } if (session->agent->ident) { ssh_buffer_reinit(session->agent->ident); } session->agent->ident = reply; return session->agent->count; } /* caller has to free commment */ ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session, char **comment) { if (ssh_agent_get_ident_count(session) > 0) { return ssh_agent_get_next_ident(session, comment); } return NULL; } /* caller has to free commment */ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session, char **comment) { struct ssh_key_struct *key; struct ssh_string_struct *blob = NULL; struct ssh_string_struct *tmp = NULL; int rc; if (session->agent->count == 0) { return NULL; } /* get the blob */ blob = ssh_buffer_get_ssh_string(session->agent->ident); if (blob == NULL) { return NULL; } /* get the comment */ tmp = ssh_buffer_get_ssh_string(session->agent->ident); if (tmp == NULL) { SSH_STRING_FREE(blob); return NULL; } if (comment) { *comment = ssh_string_to_char(tmp); } else { SSH_STRING_FREE(blob); SSH_STRING_FREE(tmp); return NULL; } SSH_STRING_FREE(tmp); /* get key from blob */ rc = ssh_pki_import_pubkey_blob(blob, &key); if (rc == SSH_ERROR) { /* Try again as a cert. */ rc = ssh_pki_import_cert_blob(blob, &key); } SSH_STRING_FREE(blob); if (rc == SSH_ERROR) { return NULL; } return key; } int ssh_agent_is_running(ssh_session session) { if (session == NULL || session->agent == NULL) { return 0; } #ifndef _WIN32 if (ssh_socket_is_open(session->agent->sock)) { return 1; } else { if (agent_connect(session) < 0) { return 0; } else { return 1; } } return 0; #else HWND hwnd = FindWindow("Pageant", "Pageant"); return hwnd != NULL; #endif } ssh_string ssh_agent_sign_data(ssh_session session, const ssh_key pubkey, struct ssh_buffer_struct *data) { ssh_buffer request; ssh_buffer reply; ssh_string key_blob; ssh_string sig_blob; unsigned int type = 0; unsigned int flags = 0; uint32_t dlen; int rc; request = ssh_buffer_new(); if (request == NULL) { return NULL; } /* create request */ if (ssh_buffer_add_u8(request, SSH2_AGENTC_SIGN_REQUEST) < 0) { SSH_BUFFER_FREE(request); return NULL; } rc = ssh_pki_export_pubkey_blob(pubkey, &key_blob); if (rc < 0) { SSH_BUFFER_FREE(request); return NULL; } /* * make sure it already can contain all the expected content: * - 1 x uint8_t * - 2 x uint32_t * - 1 x ssh_string (uint8_t + data) */ rc = ssh_buffer_allocate_size(request, sizeof(uint8_t) * 2 + sizeof(uint32_t) * 2 + ssh_string_len(key_blob)); if (rc < 0) { SSH_BUFFER_FREE(request); return NULL; } /* adds len + blob */ rc = ssh_buffer_add_ssh_string(request, key_blob); SSH_STRING_FREE(key_blob); if (rc < 0) { SSH_BUFFER_FREE(request); return NULL; } /* Add data */ dlen = ssh_buffer_get_len(data); if (ssh_buffer_add_u32(request, htonl(dlen)) < 0) { SSH_BUFFER_FREE(request); return NULL; } if (ssh_buffer_add_data(request, ssh_buffer_get(data), dlen) < 0) { SSH_BUFFER_FREE(request); return NULL; } /* Add Flags: SHA2 extension (RFC 8332) if negotiated */ if (ssh_key_type_plain(pubkey->type) == SSH_KEYTYPE_RSA) { if (session->extensions & SSH_EXT_SIG_RSA_SHA512) { flags |= SSH_AGENT_RSA_SHA2_512; } else if (session->extensions & SSH_EXT_SIG_RSA_SHA256) { flags |= SSH_AGENT_RSA_SHA2_256; } } if (ssh_buffer_add_u32(request, htonl(flags)) < 0) { SSH_BUFFER_FREE(request); return NULL; } reply = ssh_buffer_new(); if (reply == NULL) { SSH_BUFFER_FREE(request); return NULL; } /* send the request */ if (agent_talk(session, request, reply) < 0) { SSH_BUFFER_FREE(request); SSH_BUFFER_FREE(reply); return NULL; } SSH_BUFFER_FREE(request); /* check if reply is valid */ if (ssh_buffer_get_u8(reply, (uint8_t *) &type) != sizeof(uint8_t)) { SSH_BUFFER_FREE(reply); return NULL; } #ifdef WORDS_BIGENDIAN type = bswap_32(type); #endif if (agent_failed(type)) { SSH_LOG(SSH_LOG_WARN, "Agent reports failure in signing the key"); SSH_BUFFER_FREE(reply); return NULL; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { ssh_set_error(session, SSH_FATAL, "Bad authentication response: %u", type); SSH_BUFFER_FREE(reply); return NULL; } sig_blob = ssh_buffer_get_ssh_string(reply); SSH_BUFFER_FREE(reply); return sig_blob; } ================================================ FILE: src/libssh/src/auth.c ================================================ /* * auth.c - Authentication with SSH protocols * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * Copyright (c) 2008-2013 Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/agent.h" #include "libssh/misc.h" #include "libssh/packet.h" #include "libssh/session.h" #include "libssh/keys.h" #include "libssh/auth.h" #include "libssh/pki.h" #include "libssh/gssapi.h" #include "libssh/legacy.h" /** * @defgroup libssh_auth The SSH authentication functions. * @ingroup libssh * * Functions to authenticate with a server. * * @{ */ /** * @internal * * @brief Ask access to the ssh-userauth service. * * @param[in] session The SSH session handle. * * @returns SSH_OK on success, SSH_ERROR on error. * @returns SSH_AGAIN on nonblocking mode, if calling that function * again is necessary */ static int ssh_userauth_request_service(ssh_session session) { int rc; rc = ssh_service_request(session, "ssh-userauth"); if ((rc != SSH_OK) && (rc != SSH_AGAIN)) { SSH_LOG(SSH_LOG_WARN, "Failed to request \"ssh-userauth\" service"); } return rc; } static int ssh_auth_response_termination(void *user) { ssh_session session = (ssh_session)user; switch (session->auth.state) { case SSH_AUTH_STATE_NONE: case SSH_AUTH_STATE_KBDINT_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_PUBKEY_AUTH_SENT: case SSH_AUTH_STATE_PUBKEY_OFFER_SENT: case SSH_AUTH_STATE_PASSWORD_AUTH_SENT: case SSH_AUTH_STATE_AUTH_NONE_SENT: return 0; default: return 1; } } static const char *ssh_auth_get_current_method(ssh_session session) { const char *method = "unknown"; switch (session->auth.current_method) { case SSH_AUTH_METHOD_NONE: method = "none"; break; case SSH_AUTH_METHOD_PASSWORD: method = "password"; break; case SSH_AUTH_METHOD_PUBLICKEY: method = "publickey"; break; case SSH_AUTH_METHOD_HOSTBASED: method = "hostbased"; break; case SSH_AUTH_METHOD_INTERACTIVE: method = "keyboard interactive"; break; case SSH_AUTH_METHOD_GSSAPI_MIC: method = "gssapi"; break; default: break; } return method; } /** * @internal * @brief Wait for a response of an authentication function. * * @param[in] session The SSH session. * * @returns SSH_AUTH_SUCCESS Authentication success, or pubkey accepted * SSH_AUTH_PARTIAL Authentication succeeded but another mean * of authentication is needed. * SSH_AUTH_INFO Data for keyboard-interactive * SSH_AUTH_AGAIN In nonblocking mode, call has to be made again * SSH_AUTH_ERROR Error during the process. */ static int ssh_userauth_get_response(ssh_session session) { int rc = SSH_AUTH_ERROR; rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, ssh_auth_response_termination, session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } if (!ssh_auth_response_termination(session)) { return SSH_AUTH_AGAIN; } switch(session->auth.state) { case SSH_AUTH_STATE_ERROR: rc = SSH_AUTH_ERROR; break; case SSH_AUTH_STATE_FAILED: rc = SSH_AUTH_DENIED; break; case SSH_AUTH_STATE_INFO: rc = SSH_AUTH_INFO; break; case SSH_AUTH_STATE_PARTIAL: rc = SSH_AUTH_PARTIAL; break; case SSH_AUTH_STATE_PK_OK: case SSH_AUTH_STATE_SUCCESS: rc = SSH_AUTH_SUCCESS; break; case SSH_AUTH_STATE_KBDINT_SENT: case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT: case SSH_AUTH_STATE_GSSAPI_TOKEN: case SSH_AUTH_STATE_GSSAPI_MIC_SENT: case SSH_AUTH_STATE_PUBKEY_OFFER_SENT: case SSH_AUTH_STATE_PUBKEY_AUTH_SENT: case SSH_AUTH_STATE_PASSWORD_AUTH_SENT: case SSH_AUTH_STATE_AUTH_NONE_SENT: case SSH_AUTH_STATE_NONE: /* not reached */ rc = SSH_AUTH_ERROR; break; } return rc; } /** * @internal * * @brief Handles a SSH_USERAUTH_BANNER packet. * * This banner should be shown to user prior to authentication */ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) { ssh_string banner; (void)type; (void)user; banner = ssh_buffer_get_ssh_string(packet); if (banner == NULL) { SSH_LOG(SSH_LOG_WARN, "Invalid SSH_USERAUTH_BANNER packet"); } else { SSH_LOG(SSH_LOG_DEBUG, "Received SSH_USERAUTH_BANNER packet"); if (session->banner != NULL) SSH_STRING_FREE(session->banner); session->banner = banner; } return SSH_PACKET_USED; } /** * @internal * * @brief Handles a SSH_USERAUTH_FAILURE packet. * * This handles the complete or partial authentication failure. */ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) { const char *current_method = ssh_auth_get_current_method(session); char *auth_methods = NULL; uint8_t partial = 0; int rc; (void) type; (void) user; rc = ssh_buffer_unpack(packet, "sb", &auth_methods, &partial); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_USERAUTH_FAILURE message"); session->auth.state = SSH_AUTH_STATE_ERROR; goto end; } if (partial) { session->auth.state = SSH_AUTH_STATE_PARTIAL; SSH_LOG(SSH_LOG_INFO, "Partial success for '%s'. Authentication that can continue: %s", current_method, auth_methods); } else { session->auth.state = SSH_AUTH_STATE_FAILED; ssh_set_error(session, SSH_REQUEST_DENIED, "Access denied for '%s'. Authentication that can continue: %s", current_method, auth_methods); SSH_LOG(SSH_LOG_INFO, "%s", ssh_get_error(session)); } session->auth.supported_methods = 0; if (strstr(auth_methods, "password") != NULL) { session->auth.supported_methods |= SSH_AUTH_METHOD_PASSWORD; } if (strstr(auth_methods, "keyboard-interactive") != NULL) { session->auth.supported_methods |= SSH_AUTH_METHOD_INTERACTIVE; } if (strstr(auth_methods, "publickey") != NULL) { session->auth.supported_methods |= SSH_AUTH_METHOD_PUBLICKEY; } if (strstr(auth_methods, "hostbased") != NULL) { session->auth.supported_methods |= SSH_AUTH_METHOD_HOSTBASED; } if (strstr(auth_methods, "gssapi-with-mic") != NULL) { session->auth.supported_methods |= SSH_AUTH_METHOD_GSSAPI_MIC; } end: session->auth.current_method = SSH_AUTH_METHOD_UNKNOWN; SAFE_FREE(auth_methods); return SSH_PACKET_USED; } /** * @internal * * @brief Handles a SSH_USERAUTH_SUCCESS packet. * * It is also used to communicate the new to the upper levels. */ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) { struct ssh_crypto_struct *crypto = NULL; (void)packet; (void)type; (void)user; SSH_LOG(SSH_LOG_DEBUG, "Authentication successful"); SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_SUCCESS"); session->auth.state = SSH_AUTH_STATE_SUCCESS; session->session_state = SSH_SESSION_STATE_AUTHENTICATED; session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); if (crypto != NULL && crypto->delayed_compress_out) { SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression OUT"); crypto->do_compress_out = 1; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto != NULL && crypto->delayed_compress_in) { SSH_LOG(SSH_LOG_DEBUG, "Enabling delayed compression IN"); crypto->do_compress_in = 1; } /* Reset errors by previous authentication methods. */ ssh_reset_error(session); session->auth.current_method = SSH_AUTH_METHOD_UNKNOWN; return SSH_PACKET_USED; } /** * @internal * * @brief Handles a SSH_USERAUTH_PK_OK or SSH_USERAUTH_INFO_REQUEST packet. * * Since the two types of packets share the same code, additional work is done * to understand if we are in a public key or keyboard-interactive context. */ SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) { int rc; SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE"); if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) { /* Assuming we are in keyboard-interactive context */ SSH_LOG(SSH_LOG_TRACE, "keyboard-interactive context, " "assuming SSH_USERAUTH_INFO_REQUEST"); rc = ssh_packet_userauth_info_request(session,type,packet,user); #ifdef WITH_GSSAPI } else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) { rc = ssh_packet_userauth_gssapi_response(session, type, packet, user); #endif } else if (session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT) { session->auth.state = SSH_AUTH_STATE_PK_OK; SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK"); rc = SSH_PACKET_USED; } else { session->auth.state = SSH_AUTH_STATE_ERROR; SSH_LOG(SSH_LOG_TRACE, "SSH_USERAUTH_PK_OK received in wrong state"); rc = SSH_PACKET_USED; } return rc; } /** * @brief Get available authentication methods from the server. * * This requires the function ssh_userauth_none() to be called before the * methods are available. The server MAY return a list of methods that may * continue. * * @param[in] session The SSH session. * * @param[in] username Deprecated, set to NULL. * * @returns A bitfield of the fllowing values: * - SSH_AUTH_METHOD_PASSWORD * - SSH_AUTH_METHOD_PUBLICKEY * - SSH_AUTH_METHOD_HOSTBASED * - SSH_AUTH_METHOD_INTERACTIVE * * @warning Other reserved flags may appear in future versions. * @see ssh_userauth_none() */ int ssh_userauth_list(ssh_session session, const char *username) { (void) username; /* unused */ if (session == NULL) { return 0; } return session->auth.supported_methods; } /** * @brief Try to authenticate through the "none" method. * * @param[in] session The ssh session to use. * * @param[in] username The username, this SHOULD be NULL. * * @returns SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: Authentication failed: use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. */ int ssh_userauth_none(ssh_session session, const char *username) { int rc; switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_NONE: goto pending; default: ssh_set_error(session, SSH_FATAL, "Wrong state (%d) during pending SSH call", session->pending_call_state); return SSH_AUTH_ERROR; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsss", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "none" ); if (rc < 0) { goto fail; } session->auth.current_method = SSH_AUTH_METHOD_NONE; session->auth.state = SSH_AUTH_STATE_AUTH_NONE_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } return rc; fail: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } /** * @brief Try to authenticate with the given public key. * * To avoid unnecessary processing and user interaction, the following method * is provided for querying whether authentication using the 'pubkey' would * be possible. * * @param[in] session The SSH session. * * @param[in] username The username, this SHOULD be NULL. * * @param[in] pubkey The public key to try. * * @return SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: The server doesn't accept that public key as an * authentication token. Try another key or another * method.\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method.\n * SSH_AUTH_SUCCESS: The public key is accepted, you want now to use * ssh_userauth_publickey().\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. */ int ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey) { ssh_string pubkey_s = NULL; const char *sig_type_c = NULL; int rc; if (session == NULL) { return SSH_AUTH_ERROR; } if (pubkey == NULL || !ssh_key_is_public(pubkey)) { ssh_set_error(session, SSH_FATAL, "Invalid pubkey"); return SSH_AUTH_ERROR; } switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY: goto pending; default: ssh_set_error(session, SSH_FATAL, "Wrong state (%d) during pending SSH call", session->pending_call_state); return SSH_ERROR; } /* Check if the given public key algorithm is allowed */ sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type); if (sig_type_c == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid key type (unknown)"); return SSH_AUTH_DENIED; } if (!ssh_key_algorithm_allowed(session, sig_type_c)) { ssh_set_error(session, SSH_REQUEST_DENIED, "The key algorithm '%s' is not allowed to be used by" " PUBLICKEY_ACCEPTED_TYPES configuration option", sig_type_c); return SSH_AUTH_DENIED; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } /* public key */ rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s); if (rc < 0) { goto fail; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsssbsS", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "publickey", 0, /* private key ? */ sig_type_c, /* algo */ pubkey_s /* public key */ ); if (rc < 0) { goto fail; } SSH_STRING_FREE(pubkey_s); session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY; session->auth.state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } return rc; fail: SSH_STRING_FREE(pubkey_s); ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } /** * @brief Authenticate with public/private key or certificate. * * @param[in] session The SSH session. * * @param[in] username The username, this SHOULD be NULL. * * @param[in] privkey The private key for authentication. * * @return SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: The server doesn't accept that public key as an * authentication token. Try another key or another * method.\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method.\n * SSH_AUTH_SUCCESS: The public key is accepted.\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. */ int ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey) { ssh_string str = NULL; int rc; const char *sig_type_c = NULL; enum ssh_keytypes_e key_type; enum ssh_digest_e hash_type; if (session == NULL) { return SSH_AUTH_ERROR; } if (privkey == NULL || !ssh_key_is_private(privkey)) { ssh_set_error(session, SSH_FATAL, "Invalid private key"); return SSH_AUTH_ERROR; } switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_PUBKEY: goto pending; default: ssh_set_error(session, SSH_FATAL, "Bad call during pending SSH call in ssh_userauth_try_publickey"); return SSH_AUTH_ERROR; } /* Cert auth requires presenting the cert type name (*-cert@openssh.com) */ key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type; /* Check if the given public key algorithm is allowed */ sig_type_c = ssh_key_get_signature_algorithm(session, key_type); if (sig_type_c == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid key type (unknown)"); return SSH_AUTH_DENIED; } if (!ssh_key_algorithm_allowed(session, sig_type_c)) { ssh_set_error(session, SSH_REQUEST_DENIED, "The key algorithm '%s' is not allowed to be used by" " PUBLICKEY_ACCEPTED_TYPES configuration option", sig_type_c); return SSH_AUTH_DENIED; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } /* get public key or cert */ rc = ssh_pki_export_pubkey_blob(privkey, &str); if (rc < 0) { goto fail; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsssbsS", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "publickey", 1, /* private key */ sig_type_c, /* algo */ str /* public key or cert */ ); if (rc < 0) { goto fail; } SSH_STRING_FREE(str); /* Get the hash type to be used in the signature based on the key type */ hash_type = ssh_key_type_to_hash(session, privkey->type); /* sign the buffer with the private key */ str = ssh_pki_do_sign(session, session->out_buffer, privkey, hash_type); if (str == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(session->out_buffer, str); SSH_STRING_FREE(str); str = NULL; if (rc < 0) { goto fail; } session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY; session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } return rc; fail: SSH_STRING_FREE(str); ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } static int ssh_userauth_agent_publickey(ssh_session session, const char *username, ssh_key pubkey) { ssh_string pubkey_s = NULL; ssh_string sig_blob = NULL; const char *sig_type_c = NULL; int rc; switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_AGENT: goto pending; default: ssh_set_error(session, SSH_FATAL, "Bad call during pending SSH call in ssh_userauth_try_publickey"); return SSH_ERROR; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } /* public key */ rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s); if (rc < 0) { goto fail; } /* Check if the given public key algorithm is allowed */ sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type); if (sig_type_c == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid key type (unknown)"); SSH_STRING_FREE(pubkey_s); return SSH_AUTH_DENIED; } if (!ssh_key_algorithm_allowed(session, sig_type_c)) { ssh_set_error(session, SSH_REQUEST_DENIED, "The key algorithm '%s' is not allowed to be used by" " PUBLICKEY_ACCEPTED_TYPES configuration option", sig_type_c); SSH_STRING_FREE(pubkey_s); return SSH_AUTH_DENIED; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsssbsS", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "publickey", 1, /* private key */ sig_type_c, /* algo */ pubkey_s /* public key */ ); SSH_STRING_FREE(pubkey_s); if (rc < 0) { goto fail; } /* sign the buffer with the private key */ sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey); if (sig_blob == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob); SSH_STRING_FREE(sig_blob); if (rc < 0) { goto fail; } session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY; session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } return rc; fail: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); SSH_STRING_FREE(pubkey_s); return SSH_AUTH_ERROR; } enum ssh_agent_state_e { SSH_AGENT_STATE_NONE = 0, SSH_AGENT_STATE_PUBKEY, SSH_AGENT_STATE_AUTH }; struct ssh_agent_state_struct { enum ssh_agent_state_e state; ssh_key pubkey; char *comment; }; /* Internal function */ void ssh_agent_state_free(void *data) { struct ssh_agent_state_struct *state = data; if (state) { SSH_STRING_FREE_CHAR(state->comment); ssh_key_free(state->pubkey); free (state); } } /** * @brief Try to do public key authentication with ssh agent. * * @param[in] session The ssh session to use. * * @param[in] username The username, this SHOULD be NULL. * * @return SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: The server doesn't accept that public key as an * authentication token. Try another key or another * method.\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method.\n * SSH_AUTH_SUCCESS: The public key is accepted, you want now to use * ssh_userauth_publickey().\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. */ int ssh_userauth_agent(ssh_session session, const char *username) { int rc = SSH_AUTH_ERROR; struct ssh_agent_state_struct *state; if (session == NULL) { return SSH_AUTH_ERROR; } if (!ssh_agent_is_running(session)) { return SSH_AUTH_DENIED; } if (!session->agent_state) { session->agent_state = malloc(sizeof(struct ssh_agent_state_struct)); if (!session->agent_state) { ssh_set_error_oom(session); return SSH_AUTH_ERROR; } ZERO_STRUCTP(session->agent_state); session->agent_state->state=SSH_AGENT_STATE_NONE; } state = session->agent_state; if (state->pubkey == NULL) { state->pubkey = ssh_agent_get_first_ident(session, &state->comment); } if (state->pubkey == NULL) { return SSH_AUTH_DENIED; } while (state->pubkey != NULL) { if (state->state == SSH_AGENT_STATE_NONE) { SSH_LOG(SSH_LOG_DEBUG, "Trying identity %s", state->comment); } if (state->state == SSH_AGENT_STATE_NONE || state->state == SSH_AGENT_STATE_PUBKEY) { rc = ssh_userauth_try_publickey(session, username, state->pubkey); if (rc == SSH_AUTH_ERROR) { ssh_agent_state_free (state); session->agent_state = NULL; return rc; } else if (rc == SSH_AUTH_AGAIN) { state->state = SSH_AGENT_STATE_PUBKEY; return rc; } else if (rc != SSH_AUTH_SUCCESS) { SSH_LOG(SSH_LOG_DEBUG, "Public key of %s refused by server", state->comment); SSH_STRING_FREE_CHAR(state->comment); state->comment = NULL; ssh_key_free(state->pubkey); state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->state = SSH_AGENT_STATE_NONE; continue; } SSH_LOG(SSH_LOG_DEBUG, "Public key of %s accepted by server", state->comment); state->state = SSH_AGENT_STATE_AUTH; } if (state->state == SSH_AGENT_STATE_AUTH) { rc = ssh_userauth_agent_publickey(session, username, state->pubkey); if (rc == SSH_AUTH_AGAIN) return rc; SSH_STRING_FREE_CHAR(state->comment); state->comment = NULL; if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_PARTIAL) { ssh_agent_state_free (session->agent_state); session->agent_state = NULL; return rc; } else if (rc != SSH_AUTH_SUCCESS) { SSH_LOG(SSH_LOG_INFO, "Server accepted public key but refused the signature"); ssh_key_free(state->pubkey); state->pubkey = ssh_agent_get_next_ident(session, &state->comment); state->state = SSH_AGENT_STATE_NONE; continue; } ssh_agent_state_free (session->agent_state); session->agent_state = NULL; return SSH_AUTH_SUCCESS; } } ssh_agent_state_free (session->agent_state); session->agent_state = NULL; return rc; } enum ssh_auth_auto_state_e { SSH_AUTH_AUTO_STATE_NONE = 0, SSH_AUTH_AUTO_STATE_PUBKEY, SSH_AUTH_AUTO_STATE_KEY_IMPORTED, SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED }; struct ssh_auth_auto_state_struct { enum ssh_auth_auto_state_e state; struct ssh_iterator *it; ssh_key privkey; ssh_key pubkey; }; /** * @brief Tries to automatically authenticate with public key and "none" * * It may fail, for instance it doesn't ask for a password and uses a default * asker for passphrases (in case the private key is encrypted). * * @param[in] session The SSH session. * * @param[in] username The username, this SHOULD be NULL. * * @param[in] passphrase Use this passphrase to unlock the privatekey. Use NULL * if you don't want to use a passphrase or the user * should be asked. * * @return SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: The server doesn't accept that public key as an * authentication token. Try another key or another * method.\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method.\n * SSH_AUTH_SUCCESS: The public key is accepted, you want now to use * ssh_userauth_publickey().\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. */ int ssh_userauth_publickey_auto(ssh_session session, const char *username, const char *passphrase) { ssh_auth_callback auth_fn = NULL; void *auth_data = NULL; struct ssh_auth_auto_state_struct *state; int rc; if (session == NULL) { return SSH_AUTH_ERROR; } if (! (session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH)) { session->auth.supported_methods &= ~SSH_AUTH_METHOD_PUBLICKEY; return SSH_AUTH_DENIED; } if (session->common.callbacks) { auth_fn = session->common.callbacks->auth_function; auth_data = session->common.callbacks->userdata; } if (!session->auth.auto_state) { session->auth.auto_state = calloc(1, sizeof(struct ssh_auth_auto_state_struct)); if (!session->auth.auto_state) { ssh_set_error_oom(session); return SSH_AUTH_ERROR; } /* Set state explicitly */ session->auth.auto_state->state = SSH_AUTH_AUTO_STATE_NONE; } state = session->auth.auto_state; if (state->state == SSH_AUTH_AUTO_STATE_NONE) { /* Try authentication with ssh-agent first */ rc = ssh_userauth_agent(session, username); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL || rc == SSH_AUTH_AGAIN ) { return rc; } state->state = SSH_AUTH_AUTO_STATE_PUBKEY; } if (state->it == NULL) { state->it = ssh_list_get_iterator(session->opts.identity); } while (state->it != NULL) { const char *privkey_file = state->it->data; char pubkey_file[1024] = {0}; if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY) { SSH_LOG(SSH_LOG_DEBUG, "Trying to authenticate with %s", privkey_file); state->privkey = NULL; state->pubkey = NULL; snprintf(pubkey_file, sizeof(pubkey_file), "%s.pub", privkey_file); rc = ssh_pki_import_pubkey_file(pubkey_file, &state->pubkey); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Failed to import public key: %s", pubkey_file); SAFE_FREE(session->auth.auto_state); return SSH_AUTH_ERROR; } else if (rc == SSH_EOF) { /* Read the private key and save the public key to file */ rc = ssh_pki_import_privkey_file(privkey_file, passphrase, auth_fn, auth_data, &state->privkey); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Failed to read private key: %s", privkey_file); state->it=state->it->next; continue; } else if (rc == SSH_EOF) { /* If the file doesn't exist, continue */ SSH_LOG(SSH_LOG_DEBUG, "Private key %s doesn't exist.", privkey_file); state->it=state->it->next; continue; } rc = ssh_pki_export_privkey_to_pubkey(state->privkey, &state->pubkey); if (rc == SSH_ERROR) { ssh_key_free(state->privkey); SAFE_FREE(session->auth.auto_state); return SSH_AUTH_ERROR; } rc = ssh_pki_export_pubkey_file(state->pubkey, pubkey_file); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Could not write public key to file: %s", pubkey_file); } } state->state = SSH_AUTH_AUTO_STATE_KEY_IMPORTED; } if (state->state == SSH_AUTH_AUTO_STATE_KEY_IMPORTED) { rc = ssh_userauth_try_publickey(session, username, state->pubkey); if (rc == SSH_AUTH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Public key authentication error for %s", privkey_file); ssh_key_free(state->privkey); state->privkey = NULL; ssh_key_free(state->pubkey); state->pubkey = NULL; SAFE_FREE(session->auth.auto_state); return rc; } else if (rc == SSH_AUTH_AGAIN) { return rc; } else if (rc != SSH_AUTH_SUCCESS) { SSH_LOG(SSH_LOG_DEBUG, "Public key for %s refused by server", privkey_file); ssh_key_free(state->privkey); state->privkey = NULL; ssh_key_free(state->pubkey); state->pubkey = NULL; state->it=state->it->next; state->state = SSH_AUTH_AUTO_STATE_PUBKEY; continue; } state->state = SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED; } if (state->state == SSH_AUTH_AUTO_STATE_PUBKEY_ACCEPTED) { /* Public key has been accepted by the server */ if (state->privkey == NULL) { rc = ssh_pki_import_privkey_file(privkey_file, passphrase, auth_fn, auth_data, &state->privkey); if (rc == SSH_ERROR) { ssh_key_free(state->pubkey); state->pubkey=NULL; ssh_set_error(session, SSH_FATAL, "Failed to read private key: %s", privkey_file); state->it=state->it->next; state->state = SSH_AUTH_AUTO_STATE_PUBKEY; continue; } else if (rc == SSH_EOF) { /* If the file doesn't exist, continue */ ssh_key_free(state->pubkey); state->pubkey = NULL; SSH_LOG(SSH_LOG_INFO, "Private key %s doesn't exist.", privkey_file); state->it = state->it->next; state->state = SSH_AUTH_AUTO_STATE_PUBKEY; continue; } } rc = ssh_userauth_publickey(session, username, state->privkey); if (rc != SSH_AUTH_AGAIN && rc != SSH_AUTH_DENIED) { ssh_key_free(state->privkey); ssh_key_free(state->pubkey); SAFE_FREE(session->auth.auto_state); if (rc == SSH_AUTH_SUCCESS) { SSH_LOG(SSH_LOG_INFO, "Successfully authenticated using %s", privkey_file); } return rc; } if (rc == SSH_AUTH_AGAIN) { return rc; } ssh_key_free(state->privkey); ssh_key_free(state->pubkey); SSH_LOG(SSH_LOG_WARN, "The server accepted the public key but refused the signature"); state->it = state->it->next; state->state = SSH_AUTH_AUTO_STATE_PUBKEY; /* continue */ } } SSH_LOG(SSH_LOG_INFO, "Tried every public key, none matched"); SAFE_FREE(session->auth.auto_state); return SSH_AUTH_DENIED; } /** * @brief Try to authenticate by password. * * This authentication method is normally disabled on SSHv2 server. You should * use keyboard-interactive mode. * * The 'password' value MUST be encoded UTF-8. It is up to the server how to * interpret the password and validate it against the password database. * However, if you read the password in some other encoding, you MUST convert * the password to UTF-8. * * @param[in] session The ssh session to use. * * @param[in] username The username, this SHOULD be NULL. * * @param[in] password The password to authenticate in UTF-8. * * @returns SSH_AUTH_ERROR: A serious error happened.\n * SSH_AUTH_DENIED: Authentication failed: use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @note Most server implementations do not permit changing the username during * authentication. The username should only be set with ssh_options_set() only * before you connect to the server. * * @see ssh_userauth_none() * @see ssh_userauth_kbdint() */ int ssh_userauth_password(ssh_session session, const char *username, const char *password) { int rc; switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_PASSWORD: goto pending; default: ssh_set_error(session, SSH_FATAL, "Wrong state (%d) during pending SSH call", session->pending_call_state); return SSH_ERROR; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsssbs", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "password", 0, /* false */ password ); if (rc < 0) { goto fail; } /* Set the buffer as secure to be explicitly zeroed when freed */ ssh_buffer_set_secure(session->out_buffer); session->auth.current_method = SSH_AUTH_METHOD_PASSWORD; session->auth.state = SSH_AUTH_STATE_PASSWORD_AUTH_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } return rc; fail: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } /* LEGACY */ int ssh_userauth_agent_pubkey(ssh_session session, const char *username, ssh_public_key publickey) { ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_AUTH_ERROR; } key->type = publickey->type; key->type_c = ssh_key_type_to_char(key->type); key->flags = SSH_KEY_FLAG_PUBLIC; key->dsa = publickey->dsa_pub; key->rsa = publickey->rsa_pub; rc = ssh_userauth_agent_publickey(session, username, key); key->dsa = NULL; key->rsa = NULL; ssh_key_free(key); return rc; } ssh_kbdint ssh_kbdint_new(void) { ssh_kbdint kbd; kbd = calloc(1, sizeof(struct ssh_kbdint_struct)); if (kbd == NULL) { return NULL; } return kbd; } void ssh_kbdint_free(ssh_kbdint kbd) { size_t i, n; if (kbd == NULL) { return; } SAFE_FREE(kbd->name); SAFE_FREE(kbd->instruction); SAFE_FREE(kbd->echo); n = kbd->nprompts; if (kbd->prompts) { for (i = 0; i < n; i++) { if (kbd->prompts[i] != NULL) { explicit_bzero(kbd->prompts[i], strlen(kbd->prompts[i])); } SAFE_FREE(kbd->prompts[i]); } SAFE_FREE(kbd->prompts); } n = kbd->nanswers; if (kbd->answers) { for (i = 0; i < n; i++) { if (kbd->answers[i] != NULL) { explicit_bzero(kbd->answers[i], strlen(kbd->answers[i])); } SAFE_FREE(kbd->answers[i]); } SAFE_FREE(kbd->answers); } SAFE_FREE(kbd); } void ssh_kbdint_clean(ssh_kbdint kbd) { size_t i, n; if (kbd == NULL) { return; } SAFE_FREE(kbd->name); SAFE_FREE(kbd->instruction); SAFE_FREE(kbd->echo); n = kbd->nprompts; if (kbd->prompts) { for (i = 0; i < n; i++) { explicit_bzero(kbd->prompts[i], strlen(kbd->prompts[i])); SAFE_FREE(kbd->prompts[i]); } SAFE_FREE(kbd->prompts); } n = kbd->nanswers; if (kbd->answers) { for (i = 0; i < n; i++) { explicit_bzero(kbd->answers[i], strlen(kbd->answers[i])); SAFE_FREE(kbd->answers[i]); } SAFE_FREE(kbd->answers); } kbd->nprompts = 0; kbd->nanswers = 0; } /* * This function sends the first packet as explained in RFC 3066 section 3.1. */ static int ssh_userauth_kbdint_init(ssh_session session, const char *username, const char *submethods) { int rc; if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT) { goto pending; } if (session->pending_call_state != SSH_PENDING_CALL_NONE) { ssh_set_error_invalid(session); return SSH_ERROR; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } if (rc != SSH_OK) { return SSH_AUTH_ERROR; } /* request */ rc = ssh_buffer_pack(session->out_buffer, "bsssss", SSH2_MSG_USERAUTH_REQUEST, username ? username : session->opts.username, "ssh-connection", "keyboard-interactive", "", /* lang (ignore it) */ submethods ? submethods : "" ); if (rc < 0) { goto fail; } session->auth.state = SSH_AUTH_STATE_KBDINT_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_INIT; SSH_LOG(SSH_LOG_DEBUG, "Sending keyboard-interactive init request"); rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) session->pending_call_state = SSH_PENDING_CALL_NONE; return rc; fail: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } /** * @internal * * @brief Send the current challenge response and wait for a reply from the * server. * * @returns SSH_AUTH_INFO if more info is needed * @returns SSH_AUTH_SUCCESS * @returns SSH_AUTH_FAILURE * @returns SSH_AUTH_PARTIAL */ static int ssh_userauth_kbdint_send(ssh_session session) { uint32_t i; int rc; if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND) goto pending; if (session->pending_call_state != SSH_PENDING_CALL_NONE) { ssh_set_error_invalid(session); return SSH_ERROR; } rc = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_USERAUTH_INFO_RESPONSE, session->kbdint->nprompts); if (rc < 0) { goto fail; } for (i = 0; i < session->kbdint->nprompts; i++) { rc = ssh_buffer_pack(session->out_buffer, "s", session->kbdint->answers && session->kbdint->answers[i] ? session->kbdint->answers[i]:""); if (rc < 0) { goto fail; } } session->auth.current_method = SSH_AUTH_METHOD_INTERACTIVE; session->auth.state = SSH_AUTH_STATE_KBDINT_SENT; session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_SEND; ssh_kbdint_free(session->kbdint); session->kbdint = NULL; SSH_LOG(SSH_LOG_DEBUG, "Sending keyboard-interactive response packet"); rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) session->pending_call_state = SSH_PENDING_CALL_NONE; return rc; fail: ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); return SSH_AUTH_ERROR; } /** * @internal * @brief handles a SSH_USERAUTH_INFO_REQUEST packet, as used in * keyboard-interactive authentication, and changes the * authentication state. */ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) { ssh_string tmp = NULL; uint32_t nprompts; uint32_t i; int rc; (void)user; (void)type; if (session->kbdint == NULL) { session->kbdint = ssh_kbdint_new(); if (session->kbdint == NULL) { ssh_set_error_oom(session); return SSH_PACKET_USED; } } else { ssh_kbdint_clean(session->kbdint); } rc = ssh_buffer_unpack(packet, "ssSd", &session->kbdint->name, /* name of the "asking" window shown to client */ &session->kbdint->instruction, &tmp, /* to ignore */ &nprompts ); /* We don't care about tmp */ SSH_STRING_FREE(tmp); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Invalid USERAUTH_INFO_REQUEST msg"); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_DEBUG, "%d keyboard-interactive prompts", nprompts); if (nprompts > KBDINT_MAX_PROMPT) { ssh_set_error(session, SSH_FATAL, "Too much prompts requested by the server: %u (0x%.4x)", nprompts, nprompts); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; return SSH_PACKET_USED; } session->kbdint->nprompts = nprompts; session->kbdint->nanswers = nprompts; session->kbdint->prompts = calloc(nprompts, sizeof(char *)); if (session->kbdint->prompts == NULL) { session->kbdint->nprompts = 0; ssh_set_error_oom(session); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; return SSH_PACKET_USED; } session->kbdint->echo = calloc(nprompts, sizeof(unsigned char)); if (session->kbdint->echo == NULL) { session->kbdint->nprompts = 0; ssh_set_error_oom(session); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; return SSH_PACKET_USED; } for (i = 0; i < nprompts; i++) { rc = ssh_buffer_unpack(packet, "sb", &session->kbdint->prompts[i], &session->kbdint->echo[i]); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Short INFO_REQUEST packet"); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; return SSH_PACKET_USED; } } session->auth.state=SSH_AUTH_STATE_INFO; return SSH_PACKET_USED; } /** * @brief Try to authenticate through the "keyboard-interactive" method. * * @param[in] session The ssh session to use. * * @param[in] user The username to authenticate. You can specify NULL if * ssh_option_set_username() has been used. You cannot try * two different logins in a row. * * @param[in] submethods Undocumented. Set it to NULL. * * @returns SSH_AUTH_ERROR: A serious error happened\n * SSH_AUTH_DENIED: Authentication failed : use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success\n * SSH_AUTH_INFO: The server asked some questions. Use * ssh_userauth_kbdint_getnprompts() and such.\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. * * @see ssh_userauth_kbdint_getnprompts() * @see ssh_userauth_kbdint_getname() * @see ssh_userauth_kbdint_getinstruction() * @see ssh_userauth_kbdint_getprompt() * @see ssh_userauth_kbdint_setanswer() */ int ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods) { int rc = SSH_AUTH_ERROR; if (session == NULL) { return SSH_AUTH_ERROR; } if ((session->pending_call_state == SSH_PENDING_CALL_NONE && session->kbdint == NULL) || session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_INIT) rc = ssh_userauth_kbdint_init(session, user, submethods); else if (session->pending_call_state == SSH_PENDING_CALL_AUTH_KBDINT_SEND || session->kbdint != NULL) { /* * If we are at this point, it is because session->kbdint exists. * It means the user has set some information there we need to send * the server and then we need to ack the status (new questions or ok * pass in). * It is possible that session->kbdint is NULL while we're waiting for * a reply, hence the test for the pending call. */ rc = ssh_userauth_kbdint_send(session); } else { /* We are here because session->kbdint == NULL & state != NONE. * This should not happen */ rc = SSH_AUTH_ERROR; ssh_set_error(session, SSH_FATAL, "Invalid state in %s", __func__); } return rc; } /** * @brief Get the number of prompts (questions) the server has given. * * Once you have called ssh_userauth_kbdint() and received SSH_AUTH_INFO return * code, this function can be used to retrieve information about the keyboard * interactive authentication questions sent by the remote host. * * @param[in] session The ssh session to use. * * @returns The number of prompts. */ int ssh_userauth_kbdint_getnprompts(ssh_session session) { if (session == NULL) { return SSH_ERROR; } if (session->kbdint == NULL) { ssh_set_error_invalid(session); return SSH_ERROR; } return session->kbdint->nprompts; } /** * @brief Get the "name" of the message block. * * Once you have called ssh_userauth_kbdint() and received SSH_AUTH_INFO return * code, this function can be used to retrieve information about the keyboard * interactive authentication questions sent by the remote host. * * @param[in] session The ssh session to use. * * @returns The name of the message block. Do not free it. */ const char *ssh_userauth_kbdint_getname(ssh_session session) { if (session == NULL) { return NULL; } if (session->kbdint == NULL) { ssh_set_error_invalid(session); return NULL; } return session->kbdint->name; } /** * @brief Get the "instruction" of the message block. * * Once you have called ssh_userauth_kbdint() and received SSH_AUTH_INFO return * code, this function can be used to retrieve information about the keyboard * interactive authentication questions sent by the remote host. * * @param[in] session The ssh session to use. * * @returns The instruction of the message block. */ const char *ssh_userauth_kbdint_getinstruction(ssh_session session) { if (session == NULL) return NULL; if (session->kbdint == NULL) { ssh_set_error_invalid(session); return NULL; } return session->kbdint->instruction; } /** * @brief Get a prompt from a message block. * * Once you have called ssh_userauth_kbdint() and received SSH_AUTH_INFO return * code, this function can be used to retrieve information about the keyboard * interactive authentication questions sent by the remote host. * * @param[in] session The ssh session to use. * * @param[in] i The index number of the i'th prompt. * * @param[out] echo This is an optional variable. You can obtain a * boolean if the user input should be echoed or * hidden. For passwords it is usually hidden. * * @returns A pointer to the prompt. Do not free it. * * @code * const char prompt; * char echo; * * prompt = ssh_userauth_kbdint_getprompt(session, 0, &echo); * if (echo) ... * @endcode */ const char *ssh_userauth_kbdint_getprompt(ssh_session session, unsigned int i, char *echo) { if (session == NULL) return NULL; if (session->kbdint == NULL) { ssh_set_error_invalid(session); return NULL; } if (i > session->kbdint->nprompts) { ssh_set_error_invalid(session); return NULL; } if (echo) { *echo = (char)session->kbdint->echo[i]; } return session->kbdint->prompts[i]; } #ifdef WITH_SERVER /** * @brief Get the number of answers the client has given. * * @param[in] session The ssh session to use. * * @returns The number of answers. */ int ssh_userauth_kbdint_getnanswers(ssh_session session) { if (session == NULL || session->kbdint == NULL) { return SSH_ERROR; } return session->kbdint->nanswers; } /** * @brief Get the answer for a question from a message block. * * @param[in] session The ssh session to use. * * @param[in] i index The number of the ith answer. * * @return 0 on success, < 0 on error. */ const char *ssh_userauth_kbdint_getanswer(ssh_session session, unsigned int i) { if (session == NULL || session->kbdint == NULL || session->kbdint->answers == NULL) { return NULL; } if (i >= session->kbdint->nanswers) { return NULL; } return session->kbdint->answers[i]; } #endif /** * @brief Set the answer for a question from a message block. * * If you have called ssh_userauth_kbdint() and got SSH_AUTH_INFO, this * function returns the questions from the server. * * @param[in] session The ssh session to use. * * @param[in] i index The number of the ith prompt. * * @param[in] answer The answer to give to the server. The answer MUST be * encoded UTF-8. It is up to the server how to interpret * the value and validate it. However, if you read the * answer in some other encoding, you MUST convert it to * UTF-8. * * @return 0 on success, < 0 on error. */ int ssh_userauth_kbdint_setanswer(ssh_session session, unsigned int i, const char *answer) { if (session == NULL) { return -1; } if (answer == NULL || session->kbdint == NULL || i >= session->kbdint->nprompts) { ssh_set_error_invalid(session); return -1; } if (session->kbdint->answers == NULL) { session->kbdint->answers = calloc(session->kbdint->nprompts, sizeof(char *)); if (session->kbdint->answers == NULL) { ssh_set_error_oom(session); return -1; } } if (session->kbdint->answers[i]) { explicit_bzero(session->kbdint->answers[i], strlen(session->kbdint->answers[i])); SAFE_FREE(session->kbdint->answers[i]); } session->kbdint->answers[i] = strdup(answer); if (session->kbdint->answers[i] == NULL) { ssh_set_error_oom(session); return -1; } return 0; } /** * @brief Try to authenticate through the "gssapi-with-mic" method. * * @param[in] session The ssh session to use. * * @returns SSH_AUTH_ERROR: A serious error happened\n * SSH_AUTH_DENIED: Authentication failed : use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. */ int ssh_userauth_gssapi(ssh_session session) { int rc = SSH_AUTH_DENIED; #ifdef WITH_GSSAPI switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_AUTH_GSSAPI_MIC: goto pending; default: ssh_set_error(session, SSH_FATAL, "Wrong state (%d) during pending SSH call", session->pending_call_state); return SSH_ERROR; } rc = ssh_userauth_request_service(session); if (rc == SSH_AGAIN) { return SSH_AUTH_AGAIN; } else if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic"); session->auth.current_method = SSH_AUTH_METHOD_GSSAPI_MIC; session->auth.state = SSH_AUTH_STATE_NONE; session->pending_call_state = SSH_PENDING_CALL_AUTH_GSSAPI_MIC; rc = ssh_gssapi_auth_mic(session); if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_DENIED) { session->auth.state = SSH_AUTH_STATE_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE; return rc; } pending: rc = ssh_userauth_get_response(session); if (rc != SSH_AUTH_AGAIN) { session->pending_call_state = SSH_PENDING_CALL_NONE; } #else (void) session; /* unused */ #endif return rc; } /** @} */ ================================================ FILE: src/libssh/src/base64.c ================================================ /* * base64.c - support for base64 alphabet system, described in RFC1521 * * This file is part of the SSH Library * * Copyright (c) 2005-2005 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* just the dirtiest part of code i ever made */ #include "config.h" #include #include "libssh/priv.h" #include "libssh/buffer.h" static const uint8_t alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; /* Transformations */ #define SET_A(n, i) do { (n) |= ((i) & 63) <<18; } while (0) #define SET_B(n, i) do { (n) |= ((i) & 63) <<12; } while (0) #define SET_C(n, i) do { (n) |= ((i) & 63) << 6; } while (0) #define SET_D(n, i) do { (n) |= ((i) & 63); } while (0) #define GET_A(n) (unsigned char) (((n) & 0xff0000) >> 16) #define GET_B(n) (unsigned char) (((n) & 0xff00) >> 8) #define GET_C(n) (unsigned char) ((n) & 0xff) static int _base64_to_bin(unsigned char dest[3], const char *source, int num); static int get_equals(char *string); /* First part: base64 to binary */ /** * @internal * * @brief Translates a base64 string into a binary one. * * @returns A buffer containing the decoded string, NULL if something went * wrong (e.g. incorrect char). */ ssh_buffer base64_to_bin(const char *source) { ssh_buffer buffer = NULL; unsigned char block[3]; char *base64; char *ptr; size_t len; int equals; base64 = strdup(source); if (base64 == NULL) { return NULL; } ptr = base64; /* Get the number of equals signs, which mirrors the padding */ equals = get_equals(ptr); if (equals > 2) { SAFE_FREE(base64); return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { SAFE_FREE(base64); return NULL; } /* * The base64 buffer often contains sensitive data. Make sure we don't leak * sensitive data */ ssh_buffer_set_secure(buffer); len = strlen(ptr); while (len > 4) { if (_base64_to_bin(block, ptr, 3) < 0) { goto error; } if (ssh_buffer_add_data(buffer, block, 3) < 0) { goto error; } len -= 4; ptr += 4; } /* * Depending on the number of bytes resting, there are 3 possibilities * from the RFC. */ switch (len) { /* * (1) The final quantum of encoding input is an integral multiple of * 24 bits. Here, the final unit of encoded output will be an integral * multiple of 4 characters with no "=" padding */ case 4: if (equals != 0) { goto error; } if (_base64_to_bin(block, ptr, 3) < 0) { goto error; } if (ssh_buffer_add_data(buffer, block, 3) < 0) { goto error; } SAFE_FREE(base64); return buffer; /* * (2) The final quantum of encoding input is exactly 8 bits; here, the * final unit of encoded output will be two characters followed by * two "=" padding characters. */ case 2: if (equals != 2){ goto error; } if (_base64_to_bin(block, ptr, 1) < 0) { goto error; } if (ssh_buffer_add_data(buffer, block, 1) < 0) { goto error; } SAFE_FREE(base64); return buffer; /* * The final quantum of encoding input is exactly 16 bits. Here, the final * unit of encoded output will be three characters followed by one "=" * padding character. */ case 3: if (equals != 1) { goto error; } if (_base64_to_bin(block, ptr, 2) < 0) { goto error; } if (ssh_buffer_add_data(buffer,block,2) < 0) { goto error; } SAFE_FREE(base64); return buffer; default: /* 4,3,2 are the only padding size allowed */ goto error; } error: SAFE_FREE(base64); SSH_BUFFER_FREE(buffer); return NULL; } #define BLOCK(letter, n) do {ptr = strchr((const char *)alphabet, source[n]); \ if(!ptr) return -1; \ i = ptr - (const char *)alphabet; \ SET_##letter(*block, i); \ } while(0) /* Returns 0 if ok, -1 if not (ie invalid char into the stuff) */ static int to_block4(unsigned long *block, const char *source, int num) { const char *ptr = NULL; unsigned int i; *block = 0; if (num < 1) { return 0; } BLOCK(A, 0); /* 6 bit */ BLOCK(B,1); /* 12 bit */ if (num < 2) { return 0; } BLOCK(C, 2); /* 18 bit */ if (num < 3) { return 0; } BLOCK(D, 3); /* 24 bit */ return 0; } /* num = numbers of final bytes to be decoded */ static int _base64_to_bin(unsigned char dest[3], const char *source, int num) { unsigned long block; if (to_block4(&block, source, num) < 0) { return -1; } dest[0] = GET_A(block); dest[1] = GET_B(block); dest[2] = GET_C(block); return 0; } /* Count the number of "=" signs and replace them by zeroes */ static int get_equals(char *string) { char *ptr = string; int num = 0; while ((ptr=strchr(ptr,'=')) != NULL) { num++; *ptr = '\0'; ptr++; } return num; } /* thanks sysk for debugging my mess :) */ static void _bin_to_base64(uint8_t *dest, const uint8_t source[3], size_t len) { #define BITS(n) ((1 << (n)) - 1) switch (len) { case 1: dest[0] = alphabet[(source[0] >> 2)]; dest[1] = alphabet[((source[0] & BITS(2)) << 4)]; dest[2] = '='; dest[3] = '='; break; case 2: dest[0] = alphabet[source[0] >> 2]; dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)]; dest[2] = alphabet[(source[1] & BITS(4)) << 2]; dest[3] = '='; break; case 3: dest[0] = alphabet[(source[0] >> 2)]; dest[1] = alphabet[(source[1] >> 4) | ((source[0] & BITS(2)) << 4)]; dest[2] = alphabet[(source[2] >> 6) | (source[1] & BITS(4)) << 2]; dest[3] = alphabet[source[2] & BITS(6)]; break; } #undef BITS } /** * @internal * * @brief Converts binary data to a base64 string. * * @returns the converted string */ uint8_t *bin_to_base64(const uint8_t *source, size_t len) { uint8_t *base64 = NULL; uint8_t *ptr = NULL; size_t flen = len + (3 - (len % 3)); /* round to upper 3 multiple */ flen = (4 * flen) / 3 + 1; base64 = malloc(flen); if (base64 == NULL) { return NULL; } ptr = base64; while(len > 0){ _bin_to_base64(ptr, source, len > 3 ? 3 : len); ptr += 4; if (len < 3) { break; } source += 3; len -= 3; } ptr[0] = '\0'; return base64; } ================================================ FILE: src/libssh/src/bignum.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2014 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include "libssh/priv.h" #include "libssh/bignum.h" #include "libssh/string.h" ssh_string ssh_make_bignum_string(bignum num) { ssh_string ptr = NULL; size_t pad = 0; size_t len = bignum_num_bytes(num); size_t bits = bignum_num_bits(num); if (len == 0) { return NULL; } /* If the first bit is set we have a negative number */ if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) { pad++; } #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_TRACE, "%zu bits, %zu bytes, %zu padding\n", bits, len, pad); #endif /* DEBUG_CRYPTO */ ptr = ssh_string_new(len + pad); if (ptr == NULL) { return NULL; } /* We have a negative number so we need a leading zero */ if (pad) { ptr->data[0] = 0; } bignum_bn2bin(num, len, ptr->data + pad); return ptr; } bignum ssh_make_string_bn(ssh_string string) { bignum bn = NULL; size_t len = ssh_string_len(string); #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_TRACE, "Importing a %zu bits, %zu bytes object ...\n", len * 8, len); #endif /* DEBUG_CRYPTO */ bignum_bin2bn(string->data, len, &bn); return bn; } /* prints the bignum on stderr */ void ssh_print_bignum(const char *name, const_bignum num) { unsigned char *hex = NULL; if (num != NULL) { bignum_bn2hex(num, &hex); } fprintf(stderr, "%s value: %s\n", name, (hex == NULL) ? "(null)" : (char *) hex); #ifdef HAVE_LIBGCRYPT SAFE_FREE(hex); #elif defined HAVE_LIBCRYPTO OPENSSL_free(hex); #elif defined HAVE_LIBMBEDCRYPTO SAFE_FREE(hex); #endif } ================================================ FILE: src/libssh/src/bind.c ================================================ /* * bind.c : all ssh_bind functions * * This file is part of the SSH Library * * Copyright (c) 2004-2005 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include "libssh/priv.h" #include "libssh/bind.h" #include "libssh/libssh.h" #include "libssh/server.h" #include "libssh/pki.h" #include "libssh/buffer.h" #include "libssh/socket.h" #include "libssh/session.h" #include "libssh/token.h" /** * @addtogroup libssh_server * * @{ */ #ifdef _WIN32 #include #include #include /* * is necessary for getaddrinfo before Windows XP, but it isn't * available on some platforms like MinGW. */ #ifdef HAVE_WSPIAPI_H # include #endif #define SOCKOPT_TYPE_ARG4 char #else /* _WIN32 */ #include #include #include #define SOCKOPT_TYPE_ARG4 int #endif /* _WIN32 */ static socket_t bind_socket(ssh_bind sshbind, const char *hostname, int port) { char port_c[6]; struct addrinfo *ai; struct addrinfo hints; int opt = 1; socket_t s; int rc; ZERO_STRUCT(hints); hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; snprintf(port_c, 6, "%d", port); rc = getaddrinfo(hostname, port_c, &hints, &ai); if (rc != 0) { ssh_set_error(sshbind, SSH_FATAL, "Resolving %s: %s", hostname, gai_strerror(rc)); return -1; } s = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s == SSH_INVALID_SOCKET) { ssh_set_error(sshbind, SSH_FATAL, "%s", strerror(errno)); freeaddrinfo (ai); return -1; } if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0) { ssh_set_error(sshbind, SSH_FATAL, "Setting socket options failed: %s", strerror(errno)); freeaddrinfo (ai); CLOSE_SOCKET(s); return -1; } if (bind(s, ai->ai_addr, ai->ai_addrlen) != 0) { ssh_set_error(sshbind, SSH_FATAL, "Binding to %s:%d: %s", hostname, port, strerror(errno)); freeaddrinfo (ai); CLOSE_SOCKET(s); return -1; } freeaddrinfo (ai); return s; } ssh_bind ssh_bind_new(void) { ssh_bind ptr; ptr = calloc(1, sizeof(struct ssh_bind_struct)); if (ptr == NULL) { return NULL; } ptr->bindfd = SSH_INVALID_SOCKET; ptr->bindport = 22; ptr->common.log_verbosity = 0; return ptr; } static int ssh_bind_import_keys(ssh_bind sshbind) { int rc; if (sshbind->ecdsakey == NULL && sshbind->dsakey == NULL && sshbind->rsakey == NULL && sshbind->ed25519key == NULL) { ssh_set_error(sshbind, SSH_FATAL, "ECDSA, ED25519, DSA, or RSA host key file must be set"); return SSH_ERROR; } #ifdef HAVE_ECC if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->ecdsakey, NULL, NULL, NULL, &sshbind->ecdsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private ECDSA host key"); return SSH_ERROR; } if (!is_ecdsa_key_type(ssh_key_type(sshbind->ecdsa))) { ssh_set_error(sshbind, SSH_FATAL, "The ECDSA host key has the wrong type"); ssh_key_free(sshbind->ecdsa); sshbind->ecdsa = NULL; return SSH_ERROR; } } #endif #ifdef HAVE_DSA if (sshbind->dsa == NULL && sshbind->dsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->dsakey, NULL, NULL, NULL, &sshbind->dsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private DSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) { ssh_set_error(sshbind, SSH_FATAL, "The DSA host key has the wrong type: %d", ssh_key_type(sshbind->dsa)); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; return SSH_ERROR; } } #endif if (sshbind->rsa == NULL && sshbind->rsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->rsakey, NULL, NULL, NULL, &sshbind->rsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private RSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA) { ssh_set_error(sshbind, SSH_FATAL, "The RSA host key has the wrong type"); ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; return SSH_ERROR; } } if (sshbind->ed25519 == NULL && sshbind->ed25519key != NULL) { rc = ssh_pki_import_privkey_file(sshbind->ed25519key, NULL, NULL, NULL, &sshbind->ed25519); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private ED25519 host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->ed25519) != SSH_KEYTYPE_ED25519) { ssh_set_error(sshbind, SSH_FATAL, "The ED25519 host key has the wrong type"); ssh_key_free(sshbind->ed25519); sshbind->ed25519 = NULL; return SSH_ERROR; } } return SSH_OK; } int ssh_bind_listen(ssh_bind sshbind) { const char *host; socket_t fd; int rc; if (sshbind->rsa == NULL && sshbind->dsa == NULL && sshbind->ecdsa == NULL && sshbind->ed25519 == NULL) { rc = ssh_bind_import_keys(sshbind); if (rc != SSH_OK) { return SSH_ERROR; } } if (sshbind->bindfd == SSH_INVALID_SOCKET) { host = sshbind->bindaddr; if (host == NULL) { host = "0.0.0.0"; } fd = bind_socket(sshbind, host, sshbind->bindport); if (fd == SSH_INVALID_SOCKET) { ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; /* XXX should this clear also other structures that were allocated */ return -1; } if (listen(fd, 10) < 0) { ssh_set_error(sshbind, SSH_FATAL, "Listening to socket %d: %s", fd, strerror(errno)); CLOSE_SOCKET(fd); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; /* XXX should this clear also other structures that were allocated */ return -1; } sshbind->bindfd = fd; } else { SSH_LOG(SSH_LOG_INFO, "Using app-provided bind socket"); } return 0; } int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata){ if (sshbind == NULL) { return SSH_ERROR; } if (callbacks == NULL) { ssh_set_error_invalid(sshbind); return SSH_ERROR; } if(callbacks->size <= 0 || callbacks->size > 1024 * sizeof(void *)){ ssh_set_error(sshbind,SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; } sshbind->bind_callbacks = callbacks; sshbind->bind_callbacks_userdata=userdata; return 0; } /** @internal * @brief callback being called by poll when an event happens * */ static int ssh_bind_poll_callback(ssh_poll_handle sshpoll, socket_t fd, int revents, void *user){ ssh_bind sshbind=(ssh_bind)user; (void)sshpoll; (void)fd; if(revents & POLLIN){ /* new incoming connection */ if(ssh_callbacks_exists(sshbind->bind_callbacks,incoming_connection)){ sshbind->bind_callbacks->incoming_connection(sshbind, sshbind->bind_callbacks_userdata); } } return 0; } /** @internal * @brief returns the current poll handle, or create it * @param sshbind the ssh_bind object * @returns a ssh_poll handle suitable for operation */ ssh_poll_handle ssh_bind_get_poll(ssh_bind sshbind) { short events = POLLIN; if (sshbind->poll) { return sshbind->poll; } #ifdef POLLRDHUP events |= POLLRDHUP; #endif /* POLLRDHUP */ sshbind->poll = ssh_poll_new(sshbind->bindfd, events, ssh_bind_poll_callback, sshbind); return sshbind->poll; } void ssh_bind_set_blocking(ssh_bind sshbind, int blocking) { sshbind->blocking = blocking ? 1 : 0; } socket_t ssh_bind_get_fd(ssh_bind sshbind) { return sshbind->bindfd; } void ssh_bind_set_fd(ssh_bind sshbind, socket_t fd) { sshbind->bindfd = fd; } void ssh_bind_fd_toaccept(ssh_bind sshbind) { sshbind->toaccept = 1; } void ssh_bind_free(ssh_bind sshbind){ int i; if (sshbind == NULL) { return; } if (sshbind->bindfd >= 0) { CLOSE_SOCKET(sshbind->bindfd); } sshbind->bindfd = SSH_INVALID_SOCKET; /* options */ SAFE_FREE(sshbind->banner); SAFE_FREE(sshbind->bindaddr); SAFE_FREE(sshbind->config_dir); SAFE_FREE(sshbind->pubkey_accepted_key_types); SAFE_FREE(sshbind->dsakey); SAFE_FREE(sshbind->rsakey); SAFE_FREE(sshbind->ecdsakey); SAFE_FREE(sshbind->ed25519key); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; ssh_key_free(sshbind->ecdsa); sshbind->ecdsa = NULL; ssh_key_free(sshbind->ed25519); sshbind->ed25519 = NULL; for (i = 0; i < SSH_KEX_METHODS; i++) { if (sshbind->wanted_methods[i]) { SAFE_FREE(sshbind->wanted_methods[i]); } } SAFE_FREE(sshbind); } int ssh_bind_accept_fd(ssh_bind sshbind, ssh_session session, socket_t fd){ int i, rc; if (sshbind == NULL) { return SSH_ERROR; } if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } /* Apply global bind configurations, if it hasn't been applied before */ rc = ssh_bind_options_parse_config(sshbind, NULL); if (rc != 0) { ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config"); return SSH_ERROR; } session->server = 1; /* Copy options from bind to session */ for (i = 0; i < SSH_KEX_METHODS; i++) { if (sshbind->wanted_methods[i]) { session->opts.wanted_methods[i] = strdup(sshbind->wanted_methods[i]); if (session->opts.wanted_methods[i] == NULL) { return SSH_ERROR; } } } if (sshbind->bindaddr == NULL) session->opts.bindaddr = NULL; else { SAFE_FREE(session->opts.bindaddr); session->opts.bindaddr = strdup(sshbind->bindaddr); if (session->opts.bindaddr == NULL) { return SSH_ERROR; } } if (sshbind->pubkey_accepted_key_types != NULL) { if (session->opts.pubkey_accepted_types == NULL) { session->opts.pubkey_accepted_types = strdup(sshbind->pubkey_accepted_key_types); if (session->opts.pubkey_accepted_types == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } else { char *p; /* If something was set to the session prior to calling this * function, keep only what is allowed by the options set in * sshbind */ p = ssh_find_all_matching(sshbind->pubkey_accepted_key_types, session->opts.pubkey_accepted_types); if (p == NULL) { return SSH_ERROR; } SAFE_FREE(session->opts.pubkey_accepted_types); session->opts.pubkey_accepted_types = p; } } session->common.log_verbosity = sshbind->common.log_verbosity; if(sshbind->banner != NULL) session->opts.custombanner = strdup(sshbind->banner); ssh_socket_free(session->socket); session->socket = ssh_socket_new(session); if (session->socket == NULL) { /* perhaps it may be better to copy the error from session to sshbind */ ssh_set_error_oom(sshbind); return SSH_ERROR; } ssh_socket_set_fd(session->socket, fd); ssh_socket_get_poll_handle(session->socket); /* We must try to import any keys that could be imported in case * we are not using ssh_bind_listen (which is the other place * where keys can be imported) on this ssh_bind and are instead * only using ssh_bind_accept_fd to manage sockets ourselves. */ if (sshbind->rsa == NULL && sshbind->dsa == NULL && sshbind->ecdsa == NULL && sshbind->ed25519 == NULL) { rc = ssh_bind_import_keys(sshbind); if (rc != SSH_OK) { return SSH_ERROR; } } #ifdef HAVE_ECC if (sshbind->ecdsa) { session->srv.ecdsa_key = ssh_key_dup(sshbind->ecdsa); if (session->srv.ecdsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } #endif #ifdef HAVE_DSA if (sshbind->dsa) { session->srv.dsa_key = ssh_key_dup(sshbind->dsa); if (session->srv.dsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } #endif if (sshbind->rsa) { session->srv.rsa_key = ssh_key_dup(sshbind->rsa); if (session->srv.rsa_key == NULL) { ssh_set_error_oom(sshbind); return SSH_ERROR; } } if (sshbind->ed25519 != NULL) { session->srv.ed25519_key = ssh_key_dup(sshbind->ed25519); if (session->srv.ed25519_key == NULL){ ssh_set_error_oom(sshbind); return SSH_ERROR; } } /* force PRNG to change state in case we fork after ssh_bind_accept */ ssh_reseed(); return SSH_OK; } int ssh_bind_accept(ssh_bind sshbind, ssh_session session) { socket_t fd = SSH_INVALID_SOCKET; int rc; if (sshbind->bindfd == SSH_INVALID_SOCKET) { ssh_set_error(sshbind, SSH_FATAL, "Can't accept new clients on a not bound socket."); return SSH_ERROR; } if (session == NULL){ ssh_set_error(sshbind, SSH_FATAL,"session is null"); return SSH_ERROR; } fd = accept(sshbind->bindfd, NULL, NULL); if (fd == SSH_INVALID_SOCKET) { ssh_set_error(sshbind, SSH_FATAL, "Accepting a new connection: %s", strerror(errno)); return SSH_ERROR; } rc = ssh_bind_accept_fd(sshbind, session, fd); if(rc == SSH_ERROR){ CLOSE_SOCKET(fd); ssh_socket_free(session->socket); } return rc; } /** * @} */ ================================================ FILE: src/libssh/src/bind_config.c ================================================ /* * bind_config.c - Parse the SSH server configuration file * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifdef HAVE_GLOB_H # include #endif #include "libssh/bind.h" #include "libssh/bind_config.h" #include "libssh/config_parser.h" #include "libssh/priv.h" #include "libssh/server.h" #include "libssh/options.h" #define MAX_LINE_SIZE 1024 /* Flags used for the parser state */ #define PARSING 1 #define IN_MATCH (1<<1) struct ssh_bind_config_keyword_table_s { const char *name; enum ssh_bind_config_opcode_e opcode; bool allowed_in_match; }; static struct ssh_bind_config_keyword_table_s ssh_bind_config_keyword_table[] = { { .name = "include", .opcode = BIND_CFG_INCLUDE }, { .name = "hostkey", .opcode = BIND_CFG_HOSTKEY }, { .name = "listenaddress", .opcode = BIND_CFG_LISTENADDRESS }, { .name = "port", .opcode = BIND_CFG_PORT }, { .name = "loglevel", .opcode = BIND_CFG_LOGLEVEL, .allowed_in_match = true, }, { .name = "ciphers", .opcode = BIND_CFG_CIPHERS }, { .name = "macs", .opcode = BIND_CFG_MACS }, { .name = "kexalgorithms", .opcode = BIND_CFG_KEXALGORITHMS }, { .name = "match", .opcode = BIND_CFG_MATCH, .allowed_in_match = true }, { .name = "pubkeyacceptedkeytypes", .opcode = BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES, .allowed_in_match = true }, { .name = "hostkeyalgorithms", .opcode = BIND_CFG_HOSTKEY_ALGORITHMS, .allowed_in_match = true }, { .opcode = BIND_CFG_UNKNOWN, } }; enum ssh_bind_config_match_e { BIND_MATCH_UNKNOWN = -1, BIND_MATCH_ALL, BIND_MATCH_USER, BIND_MATCH_GROUP, BIND_MATCH_HOST, BIND_MATCH_LOCALADDRESS, BIND_MATCH_LOCALPORT, BIND_MATCH_RDOMAIN, BIND_MATCH_ADDRESS, }; struct ssh_bind_config_match_keyword_table_s { const char *name; enum ssh_bind_config_match_e opcode; }; static struct ssh_bind_config_match_keyword_table_s ssh_bind_config_match_keyword_table[] = { { .name = "all", .opcode = BIND_MATCH_ALL }, { .name = "user", .opcode = BIND_MATCH_USER }, { .name = "group", .opcode = BIND_MATCH_GROUP }, { .name = "host", .opcode = BIND_MATCH_HOST }, { .name = "localaddress", .opcode = BIND_MATCH_LOCALADDRESS }, { .name = "localport", .opcode = BIND_MATCH_LOCALPORT }, { .name = "rdomain", .opcode = BIND_MATCH_RDOMAIN }, { .name = "address", .opcode = BIND_MATCH_ADDRESS }, { .opcode = BIND_MATCH_UNKNOWN }, }; static enum ssh_bind_config_opcode_e ssh_bind_config_get_opcode(char *keyword, uint32_t *parser_flags) { int i; for (i = 0; ssh_bind_config_keyword_table[i].name != NULL; i++) { if (strcasecmp(keyword, ssh_bind_config_keyword_table[i].name) == 0) { if ((*parser_flags & IN_MATCH) && !(ssh_bind_config_keyword_table[i].allowed_in_match)) { return BIND_CFG_NOT_ALLOWED_IN_MATCH; } return ssh_bind_config_keyword_table[i].opcode; } } return BIND_CFG_UNKNOWN; } static int ssh_bind_config_parse_line(ssh_bind bind, const char *line, unsigned int count, uint32_t *parser_flags, uint8_t *seen); static void local_parse_file(ssh_bind bind, const char *filename, uint32_t *parser_flags, uint8_t *seen) { FILE *f; char line[MAX_LINE_SIZE] = {0}; unsigned int count = 0; int rv; f = fopen(filename, "r"); if (f == NULL) { SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load", filename); return; } SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename); while (fgets(line, sizeof(line), f)) { count++; rv = ssh_bind_config_parse_line(bind, line, count, parser_flags, seen); if (rv < 0) { fclose(f); return; } } fclose(f); return; } #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) static void local_parse_glob(ssh_bind bind, const char *fileglob, uint32_t *parser_flags, uint8_t *seen) { glob_t globbuf = { .gl_flags = 0, }; int rt; u_int i; rt = glob(fileglob, GLOB_TILDE, NULL, &globbuf); if (rt == GLOB_NOMATCH) { globfree(&globbuf); return; } else if (rt != 0) { SSH_LOG(SSH_LOG_RARE, "Glob error: %s", fileglob); globfree(&globbuf); return; } for (i = 0; i < globbuf.gl_pathc; i++) { local_parse_file(bind, globbuf.gl_pathv[i], parser_flags, seen); } globfree(&globbuf); } #endif /* HAVE_GLOB HAVE_GLOB_GL_FLAGS_MEMBER */ static enum ssh_bind_config_match_e ssh_bind_config_get_match_opcode(const char *keyword) { size_t i; for (i = 0; ssh_bind_config_match_keyword_table[i].name != NULL; i++) { if (strcasecmp(keyword, ssh_bind_config_match_keyword_table[i].name) == 0) { return ssh_bind_config_match_keyword_table[i].opcode; } } return BIND_MATCH_UNKNOWN; } static int ssh_bind_config_parse_line(ssh_bind bind, const char *line, unsigned int count, uint32_t *parser_flags, uint8_t *seen) { enum ssh_bind_config_opcode_e opcode; const char *p = NULL; char *s = NULL, *x = NULL; char *keyword = NULL; size_t len; int rc = 0; if (bind == NULL) { return -1; } if ((line == NULL) || (parser_flags == NULL)) { ssh_set_error_invalid(bind); return -1; } x = s = strdup(line); if (s == NULL) { ssh_set_error_oom(bind); return -1; } /* Remove trailing spaces */ for (len = strlen(s) - 1; len > 0; len--) { if (! isspace(s[len])) { break; } s[len] = '\0'; } keyword = ssh_config_get_token(&s); if (keyword == NULL || *keyword == '#' || *keyword == '\0' || *keyword == '\n') { SAFE_FREE(x); return 0; } opcode = ssh_bind_config_get_opcode(keyword, parser_flags); if ((*parser_flags & PARSING) && opcode != BIND_CFG_HOSTKEY && opcode != BIND_CFG_INCLUDE && opcode != BIND_CFG_MATCH && opcode > BIND_CFG_UNSUPPORTED) { /* Ignore all unknown types here */ /* Skip all the options that were already applied */ if (seen[opcode] != 0) { SAFE_FREE(x); return 0; } seen[opcode] = 1; } switch (opcode) { case BIND_CFG_INCLUDE: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) local_parse_glob(bind, p, parser_flags, seen); #else local_parse_file(bind, p, parser_flags, seen); #endif /* HAVE_GLOB */ } break; case BIND_CFG_HOSTKEY: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set Hostkey value '%s'", count, p); } } break; case BIND_CFG_LISTENADDRESS: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set ListenAddress value '%s'", count, p); } } break; case BIND_CFG_PORT: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set Port value '%s'", count, p); } } break; case BIND_CFG_CIPHERS: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set C->S Ciphers value '%s'", count, p); break; } rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set S->C Ciphers value '%s'", count, p); } } break; case BIND_CFG_MACS: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set C->S MAC value '%s'", count, p); break; } rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set S->C MAC value '%s'", count, p); } } break; case BIND_CFG_LOGLEVEL: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { int value = -1; if (strcasecmp(p, "quiet") == 0) { value = SSH_LOG_NONE; } else if (strcasecmp(p, "fatal") == 0 || strcasecmp(p, "error")== 0 || strcasecmp(p, "info") == 0) { value = SSH_LOG_WARN; } else if (strcasecmp(p, "verbose") == 0) { value = SSH_LOG_INFO; } else if (strcasecmp(p, "DEBUG") == 0 || strcasecmp(p, "DEBUG1") == 0) { value = SSH_LOG_DEBUG; } else if (strcasecmp(p, "DEBUG2") == 0 || strcasecmp(p, "DEBUG3") == 0) { value = SSH_LOG_TRACE; } if (value != -1) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &value); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set LogLevel value '%s'", count, p); } } } break; case BIND_CFG_KEXALGORITHMS: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set KexAlgorithms value '%s'", count, p); } } break; case BIND_CFG_MATCH: { bool negate; int result = PARSING; size_t args = 0; enum ssh_bind_config_match_e opt; const char *p2 = NULL; /* The options set in Match blocks should be applied when a connection * is accepted, and not right away when parsing the file (as it is * currently done). This means the configuration files should be parsed * again or the options set in the Match blocks should be stored and * applied as necessary. */ /* If this is the first Match block, erase the seen table to allow * options to be overridden. Erasing the seen table was the easiest way * to allow overriding an option, but only for the first occurrence of * an option in a Match block. This is sufficient for the current * implementation which supports only the 'All' criterion, meaning the * options can be applied right away. */ if (!(*parser_flags & IN_MATCH)) { memset(seen, 0x00, BIND_CFG_MAX * sizeof(uint8_t)); } /* In this line the PARSING bit is cleared from the flags */ *parser_flags = IN_MATCH; do { p = p2 = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { break; } args++; SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'", count, p); /* If the option is prefixed with ! the result should be negated */ negate = false; if (p[0] == '!') { negate = true; p++; } opt = ssh_bind_config_get_match_opcode(p); switch (opt) { case BIND_MATCH_ALL: p = ssh_config_get_str_tok(&s, NULL); if ((args == 1) && (p == NULL || p[0] == '\0')) { /* The "all" keyword does not accept arguments or modifiers */ if (negate == true) { result = 0; } break; } ssh_set_error(bind, SSH_FATAL, "line %d: ERROR - Match all cannot be combined with " "other Match attributes", count); SAFE_FREE(x); return -1; case BIND_MATCH_USER: case BIND_MATCH_GROUP: case BIND_MATCH_HOST: case BIND_MATCH_LOCALADDRESS: case BIND_MATCH_LOCALPORT: case BIND_MATCH_RDOMAIN: case BIND_MATCH_ADDRESS: /* Only "All" is supported for now */ /* Skip one argument */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " "'%s' requires argument\n", count, p2); SAFE_FREE(x); return -1; } args++; SSH_LOG(SSH_LOG_WARN, "line %d: Unsupported Match keyword '%s', ignoring\n", count, p2); result = 0; break; case BIND_MATCH_UNKNOWN: default: ssh_set_error(bind, SSH_FATAL, "ERROR - Unknown argument '%s' for Match keyword", p); SAFE_FREE(x); return -1; } } while (p != NULL && p[0] != '\0'); if (args == 0) { ssh_set_error(bind, SSH_FATAL, "ERROR - Match keyword requires an argument"); SAFE_FREE(x); return -1; } /* This line only sets the PARSING flag if all checks passed */ *parser_flags |= result; break; } case BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set PubKeyAcceptedKeyTypes value '%s'", count, p); } } break; case BIND_CFG_HOSTKEY_ALGORITHMS: p = ssh_config_get_str_tok(&s, NULL); if (p && (*parser_flags & PARSING)) { rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, p); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "line %d: Failed to set HostkeyAlgorithms value '%s'", count, p); } } break; case BIND_CFG_NOT_ALLOWED_IN_MATCH: SSH_LOG(SSH_LOG_WARN, "Option not allowed in Match block: %s, line: %d", keyword, count); break; case BIND_CFG_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d", keyword, count); break; case BIND_CFG_UNSUPPORTED: SSH_LOG(SSH_LOG_WARN, "Unsupported option: %s, line: %d", keyword, count); break; case BIND_CFG_NA: SSH_LOG(SSH_LOG_WARN, "Option not applicable: %s, line: %d", keyword, count); break; default: ssh_set_error(bind, SSH_FATAL, "ERROR - unimplemented opcode: %d", opcode); SAFE_FREE(x); return -1; break; } SAFE_FREE(x); return rc; } int ssh_bind_config_parse_file(ssh_bind bind, const char *filename) { char line[MAX_LINE_SIZE] = {0}; unsigned int count = 0; FILE *f; uint32_t parser_flags; int rv; /* This local table is used during the parsing of the current file (and * files included recursively in this file) to prevent an option to be * redefined, i.e. the first value set is kept. But this DO NOT prevent the * option to be redefined later by another file. */ uint8_t seen[BIND_CFG_MAX] = {0}; f = fopen(filename, "r"); if (f == NULL) { return 0; } SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename); parser_flags = PARSING; while (fgets(line, sizeof(line), f)) { count++; rv = ssh_bind_config_parse_line(bind, line, count, &parser_flags, seen); if (rv) { fclose(f); return -1; } } fclose(f); return 0; } ================================================ FILE: src/libssh/src/buffer.c ================================================ /* * buffer.c - buffer functions * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/misc.h" #include "libssh/bignum.h" /* * Describes a buffer state * [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX] * ^ ^ ^ ^] * \_data points\_pos points here \_used points here | / * here Allocated */ struct ssh_buffer_struct { bool secure; size_t used; size_t allocated; size_t pos; uint8_t *data; }; /* Buffer size maximum is 256M */ #define BUFFER_SIZE_MAX 0x10000000 /** * @defgroup libssh_buffer The SSH buffer functions. * @ingroup libssh * * Functions to handle SSH buffers. * * @{ */ #ifdef DEBUG_BUFFER /** * @internal * * @brief Check that preconditions and postconditions are valid. * * @param[in] buf The buffer to check. */ static void buffer_verify(ssh_buffer buf) { bool do_abort = false; if (buf->data == NULL) { return; } if (buf->used > buf->allocated) { fprintf(stderr, "BUFFER ERROR: allocated %zu, used %zu\n", buf->allocated, buf->used); do_abort = true; } if (buf->pos > buf->used) { fprintf(stderr, "BUFFER ERROR: position %zu, used %zu\n", buf->pos, buf->used); do_abort = true; } if (buf->pos > buf->allocated) { fprintf(stderr, "BUFFER ERROR: position %zu, allocated %zu\n", buf->pos, buf->allocated); do_abort = true; } if (do_abort) { abort(); } } #else #define buffer_verify(x) #endif /** * @brief Create a new SSH buffer. * * @return A newly initialized SSH buffer, NULL on error. */ struct ssh_buffer_struct *ssh_buffer_new(void) { struct ssh_buffer_struct *buf = NULL; int rc; buf = calloc(1, sizeof(struct ssh_buffer_struct)); if (buf == NULL) { return NULL; } /* * Always preallocate 64 bytes. * * -1 for ralloc_buffer magic. */ rc = ssh_buffer_allocate_size(buf, 64 - 1); if (rc != 0) { SAFE_FREE(buf); return NULL; } buffer_verify(buf); return buf; } /** * @brief Deallocate a SSH buffer. * * \param[in] buffer The buffer to free. */ void ssh_buffer_free(struct ssh_buffer_struct *buffer) { if (buffer == NULL) { return; } buffer_verify(buffer); if (buffer->secure && buffer->allocated > 0) { /* burn the data */ explicit_bzero(buffer->data, buffer->allocated); SAFE_FREE(buffer->data); explicit_bzero(buffer, sizeof(struct ssh_buffer_struct)); } else { SAFE_FREE(buffer->data); } SAFE_FREE(buffer); } /** * @brief Sets the buffer as secure. * * A secure buffer will never leave cleartext data in the heap * after being reallocated or freed. * * @param[in] buffer buffer to set secure. */ void ssh_buffer_set_secure(ssh_buffer buffer) { buffer->secure = true; } static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) { size_t smallest = 1; uint8_t *new = NULL; buffer_verify(buffer); /* Find the smallest power of two which is greater or equal to needed */ while(smallest <= needed) { if (smallest == 0) { return -1; } smallest <<= 1; } needed = smallest; if (needed > BUFFER_SIZE_MAX) { return -1; } if (buffer->secure) { new = malloc(needed); if (new == NULL) { return -1; } memcpy(new, buffer->data, buffer->used); explicit_bzero(buffer->data, buffer->used); SAFE_FREE(buffer->data); } else { new = realloc(buffer->data, needed); if (new == NULL) { return -1; } } buffer->data = new; buffer->allocated = needed; buffer_verify(buffer); return 0; } /** @internal * @brief shifts a buffer to remove unused data in the beginning * @param buffer SSH buffer */ static void buffer_shift(ssh_buffer buffer) { size_t burn_pos = buffer->pos; buffer_verify(buffer); if (buffer->pos == 0) { return; } memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos); buffer->used -= buffer->pos; buffer->pos = 0; if (buffer->secure) { void *ptr = buffer->data + buffer->used; explicit_bzero(ptr, burn_pos); } buffer_verify(buffer); } /** * @brief Reinitialize a SSH buffer. * * In case the buffer has exceeded 64K in size, the buffer will be reallocated * to 64K. * * @param[in] buffer The buffer to reinitialize. * * @return 0 on success, < 0 on error. */ int ssh_buffer_reinit(struct ssh_buffer_struct *buffer) { if (buffer == NULL) { return -1; } buffer_verify(buffer); if (buffer->secure && buffer->allocated > 0) { explicit_bzero(buffer->data, buffer->allocated); } buffer->used = 0; buffer->pos = 0; /* If the buffer is bigger then 64K, reset it to 64K */ if (buffer->allocated > 65536) { int rc; /* -1 for realloc_buffer magic */ rc = realloc_buffer(buffer, 65536 - 1); if (rc != 0) { return -1; } } buffer_verify(buffer); return 0; } /** * @brief Add data at the tail of a buffer. * * @param[in] buffer The buffer to add the data. * * @param[in] data A pointer to the data to add. * * @param[in] len The length of the data to add. * * @return 0 on success, < 0 on error. */ int ssh_buffer_add_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) { if (buffer == NULL) { return -1; } buffer_verify(buffer); if (data == NULL) { return -1; } if (buffer->used + len < len) { return -1; } if (buffer->allocated < (buffer->used + len)) { if (buffer->pos > 0) { buffer_shift(buffer); } if (realloc_buffer(buffer, buffer->used + len) < 0) { return -1; } } memcpy(buffer->data + buffer->used, data, len); buffer->used += len; buffer_verify(buffer); return 0; } /** * @brief Ensure the buffer has at least a certain preallocated size. * * @param[in] buffer The buffer to enlarge. * * @param[in] len The length to ensure as allocated. * * @return 0 on success, < 0 on error. */ int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer, uint32_t len) { buffer_verify(buffer); if (buffer->allocated < len) { if (buffer->pos > 0) { buffer_shift(buffer); } if (realloc_buffer(buffer, len) < 0) { return -1; } } buffer_verify(buffer); return 0; } /** * @internal * * @brief Allocate space for data at the tail of a buffer. * * @param[in] buffer The buffer to add the data. * * @param[in] len The length of the data to add. * * @return Pointer on the allocated space * NULL on error. */ void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len) { void *ptr; buffer_verify(buffer); if (buffer->used + len < len) { return NULL; } if (buffer->allocated < (buffer->used + len)) { if (buffer->pos > 0) { buffer_shift(buffer); } if (realloc_buffer(buffer, buffer->used + len) < 0) { return NULL; } } ptr = buffer->data + buffer->used; buffer->used+=len; buffer_verify(buffer); return ptr; } /** * @internal * * @brief Add a SSH string to the tail of a buffer. * * @param[in] buffer The buffer to add the string. * * @param[in] string The SSH String to add. * * @return 0 on success, < 0 on error. */ int ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer, struct ssh_string_struct *string) { uint32_t len = 0; if (string == NULL) { return -1; } len = ssh_string_len(string); if (ssh_buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) { return -1; } return 0; } /** * @internal * * @brief Add a 32 bits unsigned integer to the tail of a buffer. * * @param[in] buffer The buffer to add the integer. * * @param[in] data The 32 bits integer to add. * * @return 0 on success, -1 on error. */ int ssh_buffer_add_u32(struct ssh_buffer_struct *buffer,uint32_t data) { int rc; rc = ssh_buffer_add_data(buffer, &data, sizeof(data)); if (rc < 0) { return -1; } return 0; } /** * @internal * * @brief Add a 16 bits unsigned integer to the tail of a buffer. * * @param[in] buffer The buffer to add the integer. * * @param[in] data The 16 bits integer to add. * * @return 0 on success, -1 on error. */ int ssh_buffer_add_u16(struct ssh_buffer_struct *buffer,uint16_t data) { int rc; rc = ssh_buffer_add_data(buffer, &data, sizeof(data)); if (rc < 0) { return -1; } return 0; } /** * @internal * * @brief Add a 64 bits unsigned integer to the tail of a buffer. * * @param[in] buffer The buffer to add the integer. * * @param[in] data The 64 bits integer to add. * * @return 0 on success, -1 on error. */ int ssh_buffer_add_u64(struct ssh_buffer_struct *buffer, uint64_t data) { int rc; rc = ssh_buffer_add_data(buffer, &data, sizeof(data)); if (rc < 0) { return -1; } return 0; } /** * @internal * * @brief Add a 8 bits unsigned integer to the tail of a buffer. * * @param[in] buffer The buffer to add the integer. * * @param[in] data The 8 bits integer to add. * * @return 0 on success, -1 on error. */ int ssh_buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data) { int rc; rc = ssh_buffer_add_data(buffer, &data, sizeof(uint8_t)); if (rc < 0) { return -1; } return 0; } /** * @internal * * @brief Add data at the head of a buffer. * * @param[in] buffer The buffer to add the data. * * @param[in] data The data to prepend. * * @param[in] len The length of data to prepend. * * @return 0 on success, -1 on error. */ int ssh_buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data, uint32_t len) { buffer_verify(buffer); if(len <= buffer->pos){ /* It's possible to insert data between begin and pos */ memcpy(buffer->data + (buffer->pos - len), data, len); buffer->pos -= len; buffer_verify(buffer); return 0; } /* pos isn't high enough */ if (buffer->used - buffer->pos + len < len) { return -1; } if (buffer->allocated < (buffer->used - buffer->pos + len)) { if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) { return -1; } } memmove(buffer->data + len, buffer->data + buffer->pos, buffer->used - buffer->pos); memcpy(buffer->data, data, len); buffer->used += len - buffer->pos; buffer->pos = 0; buffer_verify(buffer); return 0; } /** * @internal * * @brief Append data from a buffer to the tail of another buffer. * * @param[in] buffer The destination buffer. * * @param[in] source The source buffer to append. It doesn't take the * position of the buffer into account. * * @return 0 on success, -1 on error. */ int ssh_buffer_add_buffer(struct ssh_buffer_struct *buffer, struct ssh_buffer_struct *source) { int rc; rc = ssh_buffer_add_data(buffer, ssh_buffer_get(source), ssh_buffer_get_len(source)); if (rc < 0) { return -1; } return 0; } /** * @brief Get a pointer to the head of a buffer at the current position. * * @param[in] buffer The buffer to get the head pointer. * * @return A pointer to the data from current position. * * @see ssh_buffer_get_len() */ void *ssh_buffer_get(struct ssh_buffer_struct *buffer){ return buffer->data + buffer->pos; } /** * @brief Get the length of the buffer from the current position. * * @param[in] buffer The buffer to get the length from. * * @return The length of the buffer. * * @see ssh_buffer_get() */ uint32_t ssh_buffer_get_len(struct ssh_buffer_struct *buffer){ buffer_verify(buffer); return buffer->used - buffer->pos; } /** * @internal * * @brief Advance the position in the buffer. * * This has effect to "eat" bytes at head of the buffer. * * @param[in] buffer The buffer to advance the position. * * @param[in] len The number of bytes to eat. * * @return The new size of the buffer. */ uint32_t ssh_buffer_pass_bytes(struct ssh_buffer_struct *buffer, uint32_t len){ buffer_verify(buffer); if (buffer->pos + len < len || buffer->used < buffer->pos + len) { return 0; } buffer->pos+=len; /* if the buffer is empty after having passed the whole bytes into it, we can clean it */ if(buffer->pos==buffer->used){ buffer->pos=0; buffer->used=0; } buffer_verify(buffer); return len; } /** * @internal * * @brief Cut the end of the buffer. * * @param[in] buffer The buffer to cut. * * @param[in] len The number of bytes to remove from the tail. * * @return The new size of the buffer. */ uint32_t ssh_buffer_pass_bytes_end(struct ssh_buffer_struct *buffer, uint32_t len){ buffer_verify(buffer); if (buffer->used < len) { return 0; } buffer->used-=len; buffer_verify(buffer); return len; } /** * @brief Get the remaining data out of the buffer and adjust the read pointer. * * @param[in] buffer The buffer to read. * * @param[in] data The data buffer where to store the data. * * @param[in] len The length to read from the buffer. * * @returns 0 if there is not enough data in buffer, len otherwise. */ uint32_t ssh_buffer_get_data(struct ssh_buffer_struct *buffer, void *data, uint32_t len) { int rc; /* * Check for a integer overflow first, then check if not enough data is in * the buffer. */ rc = ssh_buffer_validate_length(buffer, len); if (rc != SSH_OK) { return 0; } memcpy(data,buffer->data+buffer->pos,len); buffer->pos+=len; return len; /* no yet support for partial reads (is it really needed ?? ) */ } /** * @internal * * @brief Get a 8 bits unsigned int out of the buffer and adjusts the read * pointer. * * @param[in] buffer The buffer to read. * * @param[in] data A pointer to a uint8_t where to store the data. * * @returns 0 if there is not enough data in buffer, 1 otherwise. */ int ssh_buffer_get_u8(struct ssh_buffer_struct *buffer, uint8_t *data){ return ssh_buffer_get_data(buffer,data,sizeof(uint8_t)); } /** * @internal * * @brief gets a 32 bits unsigned int out of the buffer. Adjusts the read pointer. * * @param[in] buffer The buffer to read. * * @param[in] data A pointer to a uint32_t where to store the data. * * @returns 0 if there is not enough data in buffer, 4 otherwise. */ int ssh_buffer_get_u32(struct ssh_buffer_struct *buffer, uint32_t *data){ return ssh_buffer_get_data(buffer,data,sizeof(uint32_t)); } /** * @internal * * @brief Get a 64 bits unsigned int out of the buffer and adjusts the read * pointer. * * @param[in] buffer The buffer to read. * * @param[in] data A pointer to a uint64_t where to store the data. * * @returns 0 if there is not enough data in buffer, 8 otherwise. */ int ssh_buffer_get_u64(struct ssh_buffer_struct *buffer, uint64_t *data){ return ssh_buffer_get_data(buffer,data,sizeof(uint64_t)); } /** * @brief Valdiates that the given length can be obtained from the buffer. * * @param[in] buffer The buffer to read from. * * @param[in] len The length to be checked. * * @return SSH_OK if the length is valid, SSH_ERROR otherwise. */ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len) { if (buffer->pos + len < len || buffer->pos + len > buffer->used) { return SSH_ERROR; } return SSH_OK; } /** * @internal * * @brief Get a SSH String out of the buffer and adjusts the read pointer. * * @param[in] buffer The buffer to read. * * @returns The SSH String, NULL on error. */ struct ssh_string_struct * ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer) { uint32_t stringlen; uint32_t hostlen; struct ssh_string_struct *str = NULL; int rc; rc = ssh_buffer_get_u32(buffer, &stringlen); if (rc == 0) { return NULL; } hostlen = ntohl(stringlen); /* verify if there is enough space in buffer to get it */ rc = ssh_buffer_validate_length(buffer, hostlen); if (rc != SSH_OK) { return NULL; /* it is indeed */ } str = ssh_string_new(hostlen); if (str == NULL) { return NULL; } stringlen = ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen); if (stringlen != hostlen) { /* should never happen */ SAFE_FREE(str); return NULL; } return str; } /** * @brief Pre-calculate the size we need for packing the buffer. * * This makes sure that enough memory is allocated for packing the buffer and * we only have to do one memory allocation. * * @param[in] buffer The buffer to allocate * * @param[in] format A format string of arguments. * * @param[in] argc The number of arguments. * * @param[in] ap The va_list of arguments. * * @return SSH_OK on success, SSH_ERROR on error. */ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer, const char *format, size_t argc, va_list ap) { const char *p = NULL; ssh_string string = NULL; char *cstring = NULL; size_t needed_size = 0; size_t len; size_t count; int rc = SSH_OK; for (p = format, count = 0; *p != '\0'; p++, count++) { /* Invalid number of arguments passed */ if (count > argc) { return SSH_ERROR; } switch(*p) { case 'b': va_arg(ap, unsigned int); needed_size += sizeof(uint8_t); break; case 'w': va_arg(ap, unsigned int); needed_size += sizeof(uint16_t); break; case 'd': va_arg(ap, uint32_t); needed_size += sizeof(uint32_t); break; case 'q': va_arg(ap, uint64_t); needed_size += sizeof(uint64_t); break; case 'S': string = va_arg(ap, ssh_string); needed_size += 4 + ssh_string_len(string); string = NULL; break; case 's': cstring = va_arg(ap, char *); needed_size += sizeof(uint32_t) + strlen(cstring); cstring = NULL; break; case 'P': len = va_arg(ap, size_t); needed_size += len; va_arg(ap, void *); count++; /* increase argument count */ break; case 'B': va_arg(ap, bignum); /* * Use a fixed size for a bignum * (they should normaly be around 32) */ needed_size += 64; break; case 't': cstring = va_arg(ap, char *); needed_size += strlen(cstring); cstring = NULL; break; default: SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); rc = SSH_ERROR; } if (rc != SSH_OK){ break; } } if (argc != count) { return SSH_ERROR; } if (rc != SSH_ERROR){ /* * Check if our canary is intact, if not, something really bad happened. */ uint32_t canary = va_arg(ap, uint32_t); if (canary != SSH_BUFFER_PACK_END) { abort(); } } rc = ssh_buffer_allocate_size(buffer, needed_size); if (rc != 0) { return SSH_ERROR; } return SSH_OK; } /** @internal * @brief Add multiple values in a buffer on a single function call * @param[in] buffer The buffer to add to * @param[in] format A format string of arguments. * @param[in] ap A va_list of arguments. * @returns SSH_OK on success * SSH_ERROR on error * @see ssh_buffer_add_format() for format list values. */ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, const char *format, size_t argc, va_list ap) { int rc = SSH_ERROR; const char *p; union { uint8_t byte; uint16_t word; uint32_t dword; uint64_t qword; ssh_string string; void *data; } o; char *cstring; bignum b; size_t len; size_t count; if (argc > 256) { return SSH_ERROR; } for (p = format, count = 0; *p != '\0'; p++, count++) { /* Invalid number of arguments passed */ if (count > argc) { return SSH_ERROR; } switch(*p) { case 'b': o.byte = (uint8_t)va_arg(ap, unsigned int); rc = ssh_buffer_add_u8(buffer, o.byte); break; case 'w': o.word = (uint16_t)va_arg(ap, unsigned int); o.word = htons(o.word); rc = ssh_buffer_add_u16(buffer, o.word); break; case 'd': o.dword = va_arg(ap, uint32_t); o.dword = htonl(o.dword); rc = ssh_buffer_add_u32(buffer, o.dword); break; case 'q': o.qword = va_arg(ap, uint64_t); o.qword = htonll(o.qword); rc = ssh_buffer_add_u64(buffer, o.qword); break; case 'S': o.string = va_arg(ap, ssh_string); rc = ssh_buffer_add_ssh_string(buffer, o.string); o.string = NULL; break; case 's': cstring = va_arg(ap, char *); len = strlen(cstring); rc = ssh_buffer_add_u32(buffer, htonl(len)); if (rc == SSH_OK){ rc = ssh_buffer_add_data(buffer, cstring, len); } cstring = NULL; break; case 'P': len = va_arg(ap, size_t); o.data = va_arg(ap, void *); count++; /* increase argument count */ rc = ssh_buffer_add_data(buffer, o.data, len); o.data = NULL; break; case 'B': b = va_arg(ap, bignum); o.string = ssh_make_bignum_string(b); if(o.string == NULL){ rc = SSH_ERROR; break; } rc = ssh_buffer_add_ssh_string(buffer, o.string); SAFE_FREE(o.string); break; case 't': cstring = va_arg(ap, char *); len = strlen(cstring); rc = ssh_buffer_add_data(buffer, cstring, len); cstring = NULL; break; default: SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); rc = SSH_ERROR; } if (rc != SSH_OK){ break; } } if (argc != count) { return SSH_ERROR; } if (rc != SSH_ERROR){ /* Check if our canary is intact, if not something really bad happened */ uint32_t canary = va_arg(ap, uint32_t); if (canary != SSH_BUFFER_PACK_END) { abort(); } } return rc; } /** @internal * @brief Add multiple values in a buffer on a single function call * @param[in] buffer The buffer to add to * @param[in] format A format string of arguments. This string contains single * letters describing the order and type of arguments: * 'b': uint8_t (pushed in network byte order) * 'w': uint16_t (pushed in network byte order) * 'd': uint32_t (pushed in network byte order) * 'q': uint64_t (pushed in network byte order) * 'S': ssh_string * 's': char * (C string, pushed as SSH string) * 't': char * (C string, pushed as free text) * 'P': size_t, void * (len of data, pointer to data) * only pushes data. * 'B': bignum (pushed as SSH string) * @returns SSH_OK on success * SSH_ERROR on error * @warning when using 'P' with a constant size (e.g. 8), do not * forget to cast to (size_t). */ int _ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, size_t argc, ...) { va_list ap; int rc; if (argc > 256) { return SSH_ERROR; } va_start(ap, argc); rc = ssh_buffer_pack_allocate_va(buffer, format, argc, ap); va_end(ap); if (rc != SSH_OK) { return rc; } va_start(ap, argc); rc = ssh_buffer_pack_va(buffer, format, argc, ap); va_end(ap); return rc; } /** @internal * @brief Get multiple values from a buffer on a single function call * @param[in] buffer The buffer to get from * @param[in] format A format string of arguments. * @param[in] ap A va_list of arguments. * @returns SSH_OK on success * SSH_ERROR on error * @see ssh_buffer_get_format() for format list values. */ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, const char *format, size_t argc, va_list ap) { int rc = SSH_ERROR; const char *p = format, *last; union { uint8_t *byte; uint16_t *word; uint32_t *dword; uint64_t *qword; ssh_string *string; char **cstring; bignum *bignum; void **data; } o; size_t len, rlen, max_len; ssh_string tmp_string = NULL; va_list ap_copy; size_t count; max_len = ssh_buffer_get_len(buffer); /* copy the argument list in case a rollback is needed */ va_copy(ap_copy, ap); if (argc > 256) { rc = SSH_ERROR; goto cleanup; } for (count = 0; *p != '\0'; p++, count++) { /* Invalid number of arguments passed */ if (count > argc) { rc = SSH_ERROR; goto cleanup; } rc = SSH_ERROR; switch (*p) { case 'b': o.byte = va_arg(ap, uint8_t *); rlen = ssh_buffer_get_u8(buffer, o.byte); rc = rlen==1 ? SSH_OK : SSH_ERROR; break; case 'w': o.word = va_arg(ap, uint16_t *); rlen = ssh_buffer_get_data(buffer, o.word, sizeof(uint16_t)); if (rlen == 2) { *o.word = ntohs(*o.word); rc = SSH_OK; } break; case 'd': o.dword = va_arg(ap, uint32_t *); rlen = ssh_buffer_get_u32(buffer, o.dword); if (rlen == 4) { *o.dword = ntohl(*o.dword); rc = SSH_OK; } break; case 'q': o.qword = va_arg(ap, uint64_t*); rlen = ssh_buffer_get_u64(buffer, o.qword); if (rlen == 8) { *o.qword = ntohll(*o.qword); rc = SSH_OK; } break; case 'B': o.bignum = va_arg(ap, bignum *); *o.bignum = NULL; tmp_string = ssh_buffer_get_ssh_string(buffer); if (tmp_string == NULL) { break; } *o.bignum = ssh_make_string_bn(tmp_string); ssh_string_burn(tmp_string); SSH_STRING_FREE(tmp_string); rc = (*o.bignum != NULL) ? SSH_OK : SSH_ERROR; break; case 'S': o.string = va_arg(ap, ssh_string *); *o.string = ssh_buffer_get_ssh_string(buffer); rc = *o.string != NULL ? SSH_OK : SSH_ERROR; o.string = NULL; break; case 's': { uint32_t u32len = 0; o.cstring = va_arg(ap, char **); *o.cstring = NULL; rlen = ssh_buffer_get_u32(buffer, &u32len); if (rlen != 4){ break; } len = ntohl(u32len); if (len > max_len - 1) { break; } rc = ssh_buffer_validate_length(buffer, len); if (rc != SSH_OK) { break; } *o.cstring = malloc(len + 1); if (*o.cstring == NULL){ rc = SSH_ERROR; break; } rlen = ssh_buffer_get_data(buffer, *o.cstring, len); if (rlen != len){ SAFE_FREE(*o.cstring); rc = SSH_ERROR; break; } (*o.cstring)[len] = '\0'; o.cstring = NULL; rc = SSH_OK; break; } case 'P': len = va_arg(ap, size_t); if (len > max_len - 1) { rc = SSH_ERROR; break; } rc = ssh_buffer_validate_length(buffer, len); if (rc != SSH_OK) { break; } o.data = va_arg(ap, void **); count++; *o.data = malloc(len); if(*o.data == NULL){ rc = SSH_ERROR; break; } rlen = ssh_buffer_get_data(buffer, *o.data, len); if (rlen != len){ SAFE_FREE(*o.data); rc = SSH_ERROR; break; } o.data = NULL; rc = SSH_OK; break; default: SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p); } if (rc != SSH_OK) { break; } } if (argc != count) { rc = SSH_ERROR; } cleanup: if (rc != SSH_ERROR){ /* Check if our canary is intact, if not something really bad happened */ uint32_t canary = va_arg(ap, uint32_t); if (canary != SSH_BUFFER_PACK_END){ abort(); } } if (rc != SSH_OK){ /* Reset the format string and erase everything that was allocated */ last = p; for(p=format;psecure) { explicit_bzero(o.byte, sizeof(uint8_t)); break; } break; case 'w': o.word = va_arg(ap_copy, uint16_t *); if (buffer->secure) { explicit_bzero(o.word, sizeof(uint16_t)); break; } break; case 'd': o.dword = va_arg(ap_copy, uint32_t *); if (buffer->secure) { explicit_bzero(o.dword, sizeof(uint32_t)); break; } break; case 'q': o.qword = va_arg(ap_copy, uint64_t *); if (buffer->secure) { explicit_bzero(o.qword, sizeof(uint64_t)); break; } break; case 'B': o.bignum = va_arg(ap_copy, bignum *); bignum_safe_free(*o.bignum); break; case 'S': o.string = va_arg(ap_copy, ssh_string *); if (buffer->secure) { ssh_string_burn(*o.string); } SAFE_FREE(*o.string); break; case 's': o.cstring = va_arg(ap_copy, char **); if (buffer->secure) { explicit_bzero(*o.cstring, strlen(*o.cstring)); } SAFE_FREE(*o.cstring); break; case 'P': len = va_arg(ap_copy, size_t); o.data = va_arg(ap_copy, void **); if (buffer->secure) { explicit_bzero(*o.data, len); } SAFE_FREE(*o.data); break; default: (void)va_arg(ap_copy, void *); break; } } } va_end(ap_copy); return rc; } /** @internal * @brief Get multiple values from a buffer on a single function call * @param[in] buffer The buffer to get from * @param[in] format A format string of arguments. This string contains single * letters describing the order and type of arguments: * 'b': uint8_t * (pulled in network byte order) * 'w': uint16_t * (pulled in network byte order) * 'd': uint32_t * (pulled in network byte order) * 'q': uint64_t * (pulled in network byte order) * 'S': ssh_string * * 's': char ** (C string, pulled as SSH string) * 'P': size_t, void ** (len of data, pointer to data) * only pulls data. * 'B': bignum * (pulled as SSH string) * @returns SSH_OK on success * SSH_ERROR on error * @warning when using 'P' with a constant size (e.g. 8), do not * forget to cast to (size_t). */ int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, size_t argc, ...) { va_list ap; int rc; va_start(ap, argc); rc = ssh_buffer_unpack_va(buffer, format, argc, ap); va_end(ap); return rc; } /** @} */ ================================================ FILE: src/libssh/src/callbacks.c ================================================ /* * callbacks.c - callback functions * * This file is part of the SSH Library * * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/callbacks.h" #include "libssh/session.h" #include "libssh/misc.h" #define is_callback_valid(session, cb) \ (cb->size <= 0 || cb->size > 1024 * sizeof(void *)) /* LEGACY */ static void ssh_legacy_log_callback(int priority, const char *function, const char *buffer, void *userdata) { ssh_session session = (ssh_session)userdata; ssh_log_callback log_fn = session->common.callbacks->log_function; void *log_data = session->common.callbacks->userdata; (void)function; /* unused */ log_fn(session, priority, buffer, log_data); } int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) { if (session == NULL || cb == NULL) { return SSH_ERROR; } if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; session->common.callbacks = cb; /* LEGACY */ if (ssh_get_log_callback() == NULL && cb->log_function) { ssh_set_log_callback(ssh_legacy_log_callback); ssh_set_log_userdata(session); } return 0; } static int ssh_add_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb, int prepend) { ssh_session session = NULL; int rc; if (channel == NULL || cb == NULL) { return SSH_ERROR; } session = channel->session; if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; if (channel->callbacks == NULL) { channel->callbacks = ssh_list_new(); if (channel->callbacks == NULL){ ssh_set_error_oom(session); return SSH_ERROR; } } if (prepend) { rc = ssh_list_prepend(channel->callbacks, cb); } else { rc = ssh_list_append(channel->callbacks, cb); } return rc; } int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) { return ssh_add_set_channel_callbacks(channel, cb, 1); } int ssh_add_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) { return ssh_add_set_channel_callbacks(channel, cb, 0); } int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb) { struct ssh_iterator *it; if (channel == NULL || channel->callbacks == NULL){ return SSH_ERROR; } it = ssh_list_find(channel->callbacks, cb); if (it == NULL){ return SSH_ERROR; } ssh_list_remove(channel->callbacks, it); return SSH_OK; } int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){ if (session == NULL || cb == NULL) { return SSH_ERROR; } if (is_callback_valid(session, cb)) { ssh_set_error(session, SSH_FATAL, "Invalid callback passed in (badly initialized)"); return SSH_ERROR; }; session->server_callbacks = cb; return 0; } ================================================ FILE: src/libssh/src/chachapoly.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2015 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/libssh.h" #include "libssh/crypto.h" #include "libssh/chacha.h" #include "libssh/poly1305.h" #include "libssh/misc.h" /* size of the keys k1 and k2 as defined in specs */ #define CHACHA20_KEYLEN 32 struct chacha20_poly1305_keysched { /* key used for encrypting the length field*/ struct chacha_ctx k1; /* key used for encrypting the packets */ struct chacha_ctx k2; }; #pragma pack(push, 1) struct ssh_packet_header { uint32_t length; uint8_t payload[]; }; #pragma pack(pop) static const uint8_t zero_block_counter[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static const uint8_t payload_block_counter[8] = {1, 0, 0, 0, 0, 0, 0, 0}; static int chacha20_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { struct chacha20_poly1305_keysched *sched; uint8_t *u8key = key; (void)IV; if (cipher->chacha20_schedule == NULL) { sched = malloc(sizeof *sched); if (sched == NULL){ return -1; } } else { sched = cipher->chacha20_schedule; } chacha_keysetup(&sched->k2, u8key, CHACHA20_KEYLEN * 8); chacha_keysetup(&sched->k1, u8key + CHACHA20_KEYLEN, CHACHA20_KEYLEN * 8); cipher->chacha20_schedule = sched; return 0; } /** * @internal * * @brief encrypts an outgoing packet with chacha20 and authenticate it * with poly1305. */ static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len, uint8_t *tag, uint64_t seq) { struct ssh_packet_header *in_packet = in, *out_packet = out; uint8_t poly1305_ctx[POLY1305_KEYLEN] = {0}; struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule; seq = htonll(seq); /* step 1, prepare the poly1305 key */ chacha_ivsetup(&keys->k2, (uint8_t *)&seq, zero_block_counter); chacha_encrypt_bytes(&keys->k2, poly1305_ctx, poly1305_ctx, POLY1305_KEYLEN); /* step 2, encrypt length field */ chacha_ivsetup(&keys->k1, (uint8_t *)&seq, zero_block_counter); chacha_encrypt_bytes(&keys->k1, (uint8_t *)&in_packet->length, (uint8_t *)&out_packet->length, sizeof(uint32_t)); /* step 3, encrypt packet payload */ chacha_ivsetup(&keys->k2, (uint8_t *)&seq, payload_block_counter); chacha_encrypt_bytes(&keys->k2, in_packet->payload, out_packet->payload, len - sizeof(uint32_t)); /* ssh_log_hexdump("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx)); */ /* step 4, compute the MAC */ poly1305_auth(tag, (uint8_t *)out_packet, len, poly1305_ctx); /* ssh_log_hexdump("poly1305 src", (uint8_t *)out_packet, len); ssh_log_hexdump("poly1305 tag", tag, POLY1305_TAGLEN); */ } static int chacha20_poly1305_aead_decrypt_length( struct ssh_cipher_struct *cipher, void *in, uint8_t *out, size_t len, uint64_t seq) { struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule; if (len < sizeof(uint32_t)) { return SSH_ERROR; } seq = htonll(seq); chacha_ivsetup(&keys->k1, (uint8_t *)&seq, zero_block_counter); chacha_encrypt_bytes(&keys->k1, in, (uint8_t *)out, sizeof(uint32_t)); return SSH_OK; } static int chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out, size_t encrypted_size, uint64_t seq) { uint8_t poly1305_ctx[POLY1305_KEYLEN] = {0}; uint8_t tag[POLY1305_TAGLEN] = {0}; struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule; uint8_t *mac = (uint8_t *)complete_packet + sizeof(uint32_t) + encrypted_size; int cmp; seq = htonll(seq); ZERO_STRUCT(poly1305_ctx); chacha_ivsetup(&keys->k2, (uint8_t *)&seq, zero_block_counter); chacha_encrypt_bytes(&keys->k2, poly1305_ctx, poly1305_ctx, POLY1305_KEYLEN); #if 0 ssh_log_hexdump("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx)); #endif poly1305_auth(tag, (uint8_t *)complete_packet, encrypted_size + sizeof(uint32_t), poly1305_ctx); #if 0 ssh_log_hexdump("poly1305 src", (uint8_t*)complete_packet, encrypted_size + 4); ssh_log_hexdump("poly1305 tag", tag, POLY1305_TAGLEN); ssh_log_hexdump("received tag", mac, POLY1305_TAGLEN); #endif cmp = memcmp(tag, mac, POLY1305_TAGLEN); if(cmp != 0) { /* mac error */ SSH_LOG(SSH_LOG_PACKET,"poly1305 verify error"); return SSH_ERROR; } chacha_ivsetup(&keys->k2, (uint8_t *)&seq, payload_block_counter); chacha_encrypt_bytes(&keys->k2, (uint8_t *)complete_packet + sizeof(uint32_t), out, encrypted_size); return SSH_OK; } static void chacha20_cleanup(struct ssh_cipher_struct *cipher) { SAFE_FREE(cipher->chacha20_schedule); } const struct ssh_cipher_struct chacha20poly1305_cipher = { .ciphertype = SSH_AEAD_CHACHA20_POLY1305, .name = "chacha20-poly1305@openssh.com", .blocksize = 8, .lenfield_blocksize = 4, .keylen = sizeof(struct chacha20_poly1305_keysched), .keysize = 512, .tag_size = POLY1305_TAGLEN, .set_encrypt_key = chacha20_set_encrypt_key, .set_decrypt_key = chacha20_set_encrypt_key, .aead_encrypt = chacha20_poly1305_aead_encrypt, .aead_decrypt_length = chacha20_poly1305_aead_decrypt_length, .aead_decrypt = chacha20_poly1305_aead_decrypt, .cleanup = chacha20_cleanup }; const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void) { return &chacha20poly1305_cipher; } ================================================ FILE: src/libssh/src/channels.c ================================================ /* * channels.c - SSH channel functions * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/packet.h" #include "libssh/socket.h" #include "libssh/channels.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/messages.h" #if WITH_SERVER #include "libssh/server.h" #endif #define WINDOWBASE 1280000 #define WINDOWLIMIT (WINDOWBASE/2) /* * All implementations MUST be able to process packets with an * uncompressed payload length of 32768 bytes or less and a total packet * size of 35000 bytes or less. */ #define CHANNEL_MAX_PACKET 32768 #define CHANNEL_INITIAL_WINDOW 64000 /** * @defgroup libssh_channel The SSH channel functions * @ingroup libssh * * Functions that manage a SSH channel. * * @{ */ static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet); /** * @brief Allocate a new channel. * * @param[in] session The ssh session to use. * * @return A pointer to a newly allocated channel, NULL on error. */ ssh_channel ssh_channel_new(ssh_session session) { ssh_channel channel = NULL; if (session == NULL) { return NULL; } /* Check if we have an authenticated session */ if (!(session->flags & SSH_SESSION_FLAG_AUTHENTICATED)) { return NULL; } channel = calloc(1, sizeof(struct ssh_channel_struct)); if (channel == NULL) { ssh_set_error_oom(session); return NULL; } channel->stdout_buffer = ssh_buffer_new(); if (channel->stdout_buffer == NULL) { ssh_set_error_oom(session); SAFE_FREE(channel); return NULL; } channel->stderr_buffer = ssh_buffer_new(); if (channel->stderr_buffer == NULL) { ssh_set_error_oom(session); SSH_BUFFER_FREE(channel->stdout_buffer); SAFE_FREE(channel); return NULL; } channel->session = session; channel->exit_status = -1; channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND; if (session->channels == NULL) { session->channels = ssh_list_new(); } ssh_list_prepend(session->channels, channel); /* Set states explicitly */ channel->state = SSH_CHANNEL_STATE_NOT_OPEN; channel->request_state = SSH_CHANNEL_REQ_STATE_NONE; return channel; } /** * @internal * * @brief Create a new channel identifier. * * @param[in] session The SSH session to use. * * @return The new channel identifier. */ uint32_t ssh_channel_new_id(ssh_session session) { return ++(session->maxchannel); } /** * @internal * * @brief Handle a SSH_PACKET_CHANNEL_OPEN_CONFIRMATION packet. * * Constructs the channel object. */ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){ uint32_t channelid=0; ssh_channel channel; int rc; (void)type; (void)user; SSH_LOG(SSH_LOG_PACKET,"Received SSH2_MSG_CHANNEL_OPEN_CONFIRMATION"); rc = ssh_buffer_unpack(packet, "d", &channelid); if (rc != SSH_OK) goto error; channel=ssh_channel_from_local(session,channelid); if(channel==NULL){ ssh_set_error(session, SSH_FATAL, "Unknown channel id %"PRIu32, (uint32_t) channelid); /* TODO: Set error marking in channel object */ return SSH_PACKET_USED; } rc = ssh_buffer_unpack(packet, "ddd", &channel->remote_channel, &channel->remote_window, &channel->remote_maxpacket); if (rc != SSH_OK) goto error; SSH_LOG(SSH_LOG_PROTOCOL, "Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d", channel->local_channel, channel->remote_channel); if (channel->state != SSH_CHANNEL_STATE_OPENING) { SSH_LOG(SSH_LOG_RARE, "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect " "channel state %d", channel->state); goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "Remote window : %"PRIu32", maxpacket : %"PRIu32, (uint32_t) channel->remote_window, (uint32_t) channel->remote_maxpacket); channel->state = SSH_CHANNEL_STATE_OPEN; channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND; return SSH_PACKET_USED; error: ssh_set_error(session, SSH_FATAL, "Invalid packet"); return SSH_PACKET_USED; } /** * @internal * * @brief Handle a SSH_CHANNEL_OPEN_FAILURE and set the state of the channel. */ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){ ssh_channel channel; char *error = NULL; uint32_t code; int rc; (void)user; (void)type; channel=channel_from_msg(session,packet); if(channel==NULL){ SSH_LOG(SSH_LOG_RARE,"Invalid channel in packet"); return SSH_PACKET_USED; } rc = ssh_buffer_unpack(packet, "ds", &code, &error); if (rc != SSH_OK){ ssh_set_error(session, SSH_FATAL, "Invalid packet"); return SSH_PACKET_USED; } if (channel->state != SSH_CHANNEL_STATE_OPENING) { SSH_LOG(SSH_LOG_RARE, "SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel " "state %d", channel->state); goto error; } ssh_set_error(session, SSH_REQUEST_DENIED, "Channel opening failure: channel %u error (%"PRIu32") %s", channel->local_channel, (uint32_t) code, error); SAFE_FREE(error); channel->state=SSH_CHANNEL_STATE_OPEN_DENIED; return SSH_PACKET_USED; error: ssh_set_error(session, SSH_FATAL, "Invalid packet"); return SSH_PACKET_USED; } static int ssh_channel_open_termination(void *c){ ssh_channel channel = (ssh_channel) c; if (channel->state != SSH_CHANNEL_STATE_OPENING || channel->session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } /** * @internal * * @brief Open a channel by sending a SSH_OPEN_CHANNEL message and * wait for the reply. * * @param[in] channel The current channel. * * @param[in] type A C string describing the kind of channel (e.g. "exec"). * * @param[in] window The receiving window of the channel. The window is the * maximum size of data that can stay in buffers and * network. * * @param[in] maxpacket The maximum packet size allowed (like MTU). * * @param[in] payload The buffer containing additional payload for the query. * * @return SSH_OK if successful; SSH_ERROR otherwise. */ static int channel_open(ssh_channel channel, const char *type, uint32_t window, uint32_t maxpacket, ssh_buffer payload) { ssh_session session = channel->session; int err = SSH_ERROR; int rc; switch (channel->state) { case SSH_CHANNEL_STATE_NOT_OPEN: break; case SSH_CHANNEL_STATE_OPENING: goto pending; case SSH_CHANNEL_STATE_OPEN: case SSH_CHANNEL_STATE_CLOSED: case SSH_CHANNEL_STATE_OPEN_DENIED: goto end; default: ssh_set_error(session, SSH_FATAL, "Bad state in channel_open: %d", channel->state); } channel->local_channel = ssh_channel_new_id(session); channel->local_maxpacket = maxpacket; channel->local_window = window; SSH_LOG(SSH_LOG_PROTOCOL, "Creating a channel %d with %d window and %d max packet", channel->local_channel, window, maxpacket); rc = ssh_buffer_pack(session->out_buffer, "bsddd", SSH2_MSG_CHANNEL_OPEN, type, channel->local_channel, channel->local_window, channel->local_maxpacket); if (rc != SSH_OK) { ssh_set_error_oom(session); return err; } if (payload != NULL) { if (ssh_buffer_add_buffer(session->out_buffer, payload) < 0) { ssh_set_error_oom(session); return err; } } channel->state = SSH_CHANNEL_STATE_OPENING; if (ssh_packet_send(session) == SSH_ERROR) { return err; } SSH_LOG(SSH_LOG_PACKET, "Sent a SSH_MSG_CHANNEL_OPEN type %s for channel %d", type, channel->local_channel); pending: /* wait until channel is opened by server */ err = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, ssh_channel_open_termination, channel); if (session->session_state == SSH_SESSION_STATE_ERROR) { err = SSH_ERROR; } end: /* This needs to pass the SSH_AGAIN from the above, * but needs to catch failed channel states */ if (channel->state == SSH_CHANNEL_STATE_OPEN) { err = SSH_OK; } else if (err != SSH_AGAIN) { /* Messages were handled correctly, but he channel state is invalid */ err = SSH_ERROR; } return err; } /* return channel with corresponding local id, or NULL if not found */ ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id) { struct ssh_iterator *it; ssh_channel channel; for (it = ssh_list_get_iterator(session->channels); it != NULL ; it=it->next) { channel = ssh_iterator_value(ssh_channel, it); if (channel == NULL) { continue; } if (channel->local_channel == id) { return channel; } } return NULL; } /** * @internal * @brief grows the local window and send a packet to the other party * @param session SSH session * @param channel SSH channel * @param minimumsize The minimum acceptable size for the new window. * @return SSH_OK if successful; SSH_ERROR otherwise. */ static int grow_window(ssh_session session, ssh_channel channel, uint32_t minimumsize) { uint32_t new_window = minimumsize > WINDOWBASE ? minimumsize : WINDOWBASE; int rc; if(new_window <= channel->local_window){ SSH_LOG(SSH_LOG_PROTOCOL, "growing window (channel %d:%d) to %d bytes : not needed (%d bytes)", channel->local_channel, channel->remote_channel, new_window, channel->local_window); return SSH_OK; } /* WINDOW_ADJUST packet needs a relative increment rather than an absolute * value, so we give here the missing bytes needed to reach new_window */ rc = ssh_buffer_pack(session->out_buffer, "bdd", SSH2_MSG_CHANNEL_WINDOW_ADJUST, channel->remote_channel, new_window - channel->local_window); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } if (ssh_packet_send(session) == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "growing window (channel %d:%d) to %d bytes", channel->local_channel, channel->remote_channel, new_window); channel->local_window = new_window; return SSH_OK; error: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; } /** * @internal * * @brief Parse a channel-related packet to resolve it to a ssh_channel. * * @param[in] session The current SSH session. * * @param[in] packet The buffer to parse packet from. The read pointer will * be moved after the call. * * @return The related ssh_channel, or NULL if the channel is * unknown or the packet is invalid. */ static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet) { ssh_channel channel; uint32_t chan; int rc; rc = ssh_buffer_unpack(packet,"d",&chan); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Getting channel from message: short read"); return NULL; } channel = ssh_channel_from_local(session, chan); if (channel == NULL) { ssh_set_error(session, SSH_FATAL, "Server specified invalid channel %"PRIu32, (uint32_t) chan); } return channel; } SSH_PACKET_CALLBACK(channel_rcv_change_window) { ssh_channel channel; uint32_t bytes; int rc; (void)user; (void)type; channel = channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); } rc = ssh_buffer_unpack(packet, "d", &bytes); if (channel == NULL || rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Error getting a window adjust message: invalid packet"); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PROTOCOL, "Adding %d bytes to channel (%d:%d) (from %d bytes)", bytes, channel->local_channel, channel->remote_channel, channel->remote_window); channel->remote_window += bytes; return SSH_PACKET_USED; } /* is_stderr is set to 1 if the data are extended, ie stderr */ SSH_PACKET_CALLBACK(channel_rcv_data){ ssh_channel channel; ssh_string str; ssh_buffer buf; size_t len; int is_stderr; int rest; (void)user; if(type==SSH2_MSG_CHANNEL_DATA) is_stderr=0; else is_stderr=1; channel = channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); return SSH_PACKET_USED; } if (is_stderr) { uint32_t ignore; /* uint32 data type code. we can ignore it */ ssh_buffer_get_u32(packet, &ignore); } str = ssh_buffer_get_ssh_string(packet); if (str == NULL) { SSH_LOG(SSH_LOG_PACKET, "Invalid data packet!"); return SSH_PACKET_USED; } len = ssh_string_len(str); SSH_LOG(SSH_LOG_PACKET, "Channel receiving %" PRIdS " bytes data in %d (local win=%d remote win=%d)", len, is_stderr, channel->local_window, channel->remote_window); /* What shall we do in this case? Let's accept it anyway */ if (len > channel->local_window) { SSH_LOG(SSH_LOG_RARE, "Data packet too big for our window(%" PRIdS " vs %d)", len, channel->local_window); } if (channel_default_bufferize(channel, ssh_string_data(str), len, is_stderr) < 0) { SSH_STRING_FREE(str); return SSH_PACKET_USED; } if (len <= channel->local_window) { channel->local_window -= len; } else { channel->local_window = 0; /* buggy remote */ } SSH_LOG(SSH_LOG_PACKET, "Channel windows are now (local win=%d remote win=%d)", channel->local_window, channel->remote_window); SSH_STRING_FREE(str); if (is_stderr) { buf = channel->stderr_buffer; } else { buf = channel->stdout_buffer; } ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_data_function) { if (ssh_buffer_get(buf) == NULL) { break; } rest = ssh_callbacks_iterate_exec(channel_data_function, channel->session, channel, ssh_buffer_get(buf), ssh_buffer_get_len(buf), is_stderr); if (rest > 0) { if (channel->counter != NULL) { channel->counter->in_bytes += rest; } ssh_buffer_pass_bytes(buf, rest); } } ssh_callbacks_iterate_end(); if (channel->local_window + ssh_buffer_get_len(buf) < WINDOWLIMIT) { if (grow_window(session, channel, 0) < 0) { return -1; } } return SSH_PACKET_USED; } SSH_PACKET_CALLBACK(channel_rcv_eof) { ssh_channel channel; (void)user; (void)type; channel = channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Received eof on channel (%d:%d)", channel->local_channel, channel->remote_channel); /* channel->remote_window = 0; */ channel->remote_eof = 1; ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_eof_function, channel->session, channel); return SSH_PACKET_USED; } SSH_PACKET_CALLBACK(channel_rcv_close) { ssh_channel channel; (void)user; (void)type; channel = channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Received close on channel (%d:%d)", channel->local_channel, channel->remote_channel); if ((channel->stdout_buffer && ssh_buffer_get_len(channel->stdout_buffer) > 0) || (channel->stderr_buffer && ssh_buffer_get_len(channel->stderr_buffer) > 0)) { channel->delayed_close = 1; } else { channel->state = SSH_CHANNEL_STATE_CLOSED; } if (channel->remote_eof == 0) { SSH_LOG(SSH_LOG_PACKET, "Remote host not polite enough to send an eof before close"); } channel->remote_eof = 1; /* * The remote eof doesn't break things if there was still data into read * buffer because the eof is ignored until the buffer is empty. */ ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_close_function, channel->session, channel); channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE; if(channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL) ssh_channel_do_free(channel); return SSH_PACKET_USED; } SSH_PACKET_CALLBACK(channel_rcv_request) { ssh_channel channel; char *request=NULL; uint8_t status; int rc; (void)user; (void)type; channel = channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS,"%s", ssh_get_error(session)); return SSH_PACKET_USED; } rc = ssh_buffer_unpack(packet, "sb", &request, &status); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); return SSH_PACKET_USED; } if (strcmp(request,"exit-status") == 0) { SAFE_FREE(request); rc = ssh_buffer_unpack(packet, "d", &channel->exit_status); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Invalid exit-status packet"); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "received exit-status %d", channel->exit_status); ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_exit_status_function, channel->session, channel, channel->exit_status); return SSH_PACKET_USED; } if (strcmp(request,"signal") == 0) { char *sig = NULL; SAFE_FREE(request); SSH_LOG(SSH_LOG_PACKET, "received signal"); rc = ssh_buffer_unpack(packet, "s", &sig); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Remote connection sent a signal SIG %s", sig); ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_signal_function, channel->session, channel, sig); SAFE_FREE(sig); return SSH_PACKET_USED; } if (strcmp(request, "exit-signal") == 0) { const char *core = "(core dumped)"; char *sig = NULL; char *errmsg = NULL; char *lang = NULL; uint8_t core_dumped; SAFE_FREE(request); rc = ssh_buffer_unpack(packet, "sbss", &sig, /* signal name */ &core_dumped, /* core dumped */ &errmsg, /* error message */ &lang); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Invalid MSG_CHANNEL_REQUEST"); return SSH_PACKET_USED; } if (core_dumped == 0) { core = ""; } SSH_LOG(SSH_LOG_PACKET, "Remote connection closed by signal SIG %s %s", sig, core); ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_exit_signal_function, channel->session, channel, sig, core_dumped, errmsg, lang); SAFE_FREE(lang); SAFE_FREE(errmsg); SAFE_FREE(sig); return SSH_PACKET_USED; } if(strcmp(request,"keepalive@openssh.com")==0){ SAFE_FREE(request); SSH_LOG(SSH_LOG_PROTOCOL,"Responding to Openssh's keepalive"); rc = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_CHANNEL_FAILURE, channel->remote_channel); if (rc != SSH_OK) { return SSH_PACKET_USED; } ssh_packet_send(session); return SSH_PACKET_USED; } if (strcmp(request, "auth-agent-req@openssh.com") == 0) { SAFE_FREE(request); SSH_LOG(SSH_LOG_PROTOCOL, "Received an auth-agent-req request"); ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_auth_agent_req_function, channel->session, channel); return SSH_PACKET_USED; } #ifdef WITH_SERVER /* If we are here, that means we have a request that is not in the understood * client requests. That means we need to create a ssh message to be passed * to the user code handling ssh messages */ ssh_message_handle_channel_request(session,channel,packet,request,status); #else SSH_LOG(SSH_LOG_WARNING, "Unhandled channel request %s", request); #endif SAFE_FREE(request); return SSH_PACKET_USED; } /* * When data has been received from the ssh server, it can be applied to the * known user function, with help of the callback, or inserted here * * FIXME is the window changed? */ int channel_default_bufferize(ssh_channel channel, void *data, size_t len, bool is_stderr) { ssh_session session; if(channel == NULL) { return -1; } session = channel->session; if(data == NULL) { ssh_set_error_invalid(session); return -1; } SSH_LOG(SSH_LOG_PACKET, "placing %zu bytes into channel buffer (%s)", len, is_stderr ? "stderr" : "stdout"); if (!is_stderr) { /* stdout */ if (channel->stdout_buffer == NULL) { channel->stdout_buffer = ssh_buffer_new(); if (channel->stdout_buffer == NULL) { ssh_set_error_oom(session); return -1; } } if (ssh_buffer_add_data(channel->stdout_buffer, data, len) < 0) { ssh_set_error_oom(session); SSH_BUFFER_FREE(channel->stdout_buffer); channel->stdout_buffer = NULL; return -1; } } else { /* stderr */ if (channel->stderr_buffer == NULL) { channel->stderr_buffer = ssh_buffer_new(); if (channel->stderr_buffer == NULL) { ssh_set_error_oom(session); return -1; } } if (ssh_buffer_add_data(channel->stderr_buffer, data, len) < 0) { ssh_set_error_oom(session); SSH_BUFFER_FREE(channel->stderr_buffer); channel->stderr_buffer = NULL; return -1; } } return 0; } /** * @brief Open a session channel (suited for a shell, not TCP forwarding). * * @param[in] channel An allocated channel. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @see ssh_channel_open_forward() * @see ssh_channel_request_env() * @see ssh_channel_request_shell() * @see ssh_channel_request_exec() */ int ssh_channel_open_session(ssh_channel channel) { if(channel == NULL) { return SSH_ERROR; } return channel_open(channel, "session", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, NULL); } /** * @brief Open an agent authentication forwarding channel. This type of channel * can be opened by a server towards a client in order to provide SSH-Agent services * to the server-side process. This channel can only be opened if the client * claimed support by sending a channel request beforehand. * * @param[in] channel An allocated channel. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @see ssh_channel_open_forward() */ int ssh_channel_open_auth_agent(ssh_channel channel){ if(channel == NULL) { return SSH_ERROR; } return channel_open(channel, "auth-agent@openssh.com", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, NULL); } /** * @brief Open a TCP/IP forwarding channel. * * @param[in] channel An allocated channel. * * @param[in] remotehost The remote host to connected (host name or IP). * * @param[in] remoteport The remote port. * * @param[in] sourcehost The numeric IP address of the machine from where the * connection request originates. This is mostly for * logging purposes. * * @param[in] localport The port on the host from where the connection * originated. This is mostly for logging purposes. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @warning This function does not bind the local port and does not automatically * forward the content of a socket to the channel. You still have to * use channel_read and channel_write for this. */ int ssh_channel_open_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport) { ssh_session session; ssh_buffer payload = NULL; ssh_string str = NULL; int rc = SSH_ERROR; if(channel == NULL) { return rc; } session = channel->session; if(remotehost == NULL || sourcehost == NULL) { ssh_set_error_invalid(session); return rc; } payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(payload, "sdsd", remotehost, remoteport, sourcehost, localport); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = channel_open(channel, "direct-tcpip", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, payload); error: SSH_BUFFER_FREE(payload); SSH_STRING_FREE(str); return rc; } /** * @brief Open a TCP/IP - UNIX domain socket forwarding channel. * * @param[in] channel An allocated channel. * * @param[in] remotepath The UNIX socket path on the remote machine * * @param[in] sourcehost The numeric IP address of the machine from where the * connection request originates. This is mostly for * logging purposes. * * @param[in] localport The port on the host from where the connection * originated. This is mostly for logging purposes. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @warning This function does not bind the local port and does not * automatically forward the content of a socket to the channel. * You still have to use channel_read and channel_write for this. * @warning Requires support of OpenSSH for UNIX domain socket forwarding. */ int ssh_channel_open_forward_unix(ssh_channel channel, const char *remotepath, const char *sourcehost, int localport) { ssh_session session = NULL; ssh_buffer payload = NULL; ssh_string str = NULL; int rc = SSH_ERROR; int version; if (channel == NULL) { return rc; } session = channel->session; version = ssh_get_openssh_version(session); if (version == 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "We're not connected to an OpenSSH server!"); return SSH_ERROR; } if (remotepath == NULL || sourcehost == NULL) { ssh_set_error_invalid(session); return rc; } payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(payload, "ssd", remotepath, sourcehost, localport); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = channel_open(channel, "direct-streamlocal@openssh.com", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, payload); error: SSH_BUFFER_FREE(payload); SSH_STRING_FREE(str); return rc; } /** * @brief Close and free a channel. * * @param[in] channel The channel to free. * * @warning Any data unread on this channel will be lost. */ void ssh_channel_free(ssh_channel channel) { ssh_session session; if (channel == NULL) { return; } session = channel->session; if (session->alive) { bool send_close = false; switch (channel->state) { case SSH_CHANNEL_STATE_OPEN: send_close = true; break; case SSH_CHANNEL_STATE_CLOSED: if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) { send_close = true; } if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_LOCAL) { send_close = false; } break; default: send_close = false; break; } if (send_close) { ssh_channel_close(channel); } } channel->flags |= SSH_CHANNEL_FLAG_FREED_LOCAL; /* The idea behind the flags is the following : it is well possible * that a client closes a channel that stills exists on the server side. * We definitively close the channel when we receive a close message *and* * the user closed it. */ if ((channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) || (channel->flags & SSH_CHANNEL_FLAG_NOT_BOUND)) { ssh_channel_do_free(channel); } } /** * @internal * @brief Effectively free a channel, without caring about flags */ void ssh_channel_do_free(ssh_channel channel) { struct ssh_iterator *it = NULL; ssh_session session = channel->session; it = ssh_list_find(session->channels, channel); if (it != NULL) { ssh_list_remove(session->channels, it); } SSH_BUFFER_FREE(channel->stdout_buffer); SSH_BUFFER_FREE(channel->stderr_buffer); if (channel->callbacks != NULL) { ssh_list_free(channel->callbacks); channel->callbacks = NULL; } channel->session = NULL; SAFE_FREE(channel); } /** * @brief Send an end of file on the channel. * * This doesn't close the channel. You may still read from it but not write. * * @param[in] channel The channel to send the eof to. * * @return SSH_OK on success, SSH_ERROR if an error occurred. * * Example: @code rc = ssh_channel_send_eof(channel); if (rc == SSH_ERROR) { return -1; } while(!ssh_channel_is_eof(channel)) { rc = ssh_channel_read(channel, buf, sizeof(buf), 0); if (rc == SSH_ERROR) { return -1; } } ssh_channel_close(channel); @endcode * * @see ssh_channel_close() * @see ssh_channel_free() * @see ssh_channel_is_eof() */ int ssh_channel_send_eof(ssh_channel channel) { ssh_session session; int rc = SSH_ERROR; int err; if (channel == NULL || channel->session == NULL) { return rc; } /* If the EOF has already been sent we're done here. */ if (channel->local_eof != 0) { return SSH_OK; } session = channel->session; err = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_CHANNEL_EOF, channel->remote_channel); if (err != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = ssh_packet_send(session); SSH_LOG(SSH_LOG_PACKET, "Sent a EOF on client channel (%d:%d)", channel->local_channel, channel->remote_channel); if (rc != SSH_OK) { goto error; } rc = ssh_channel_flush(channel); if (rc == SSH_ERROR) { goto error; } channel->local_eof = 1; return rc; error: ssh_buffer_reinit(session->out_buffer); return rc; } /** * @brief Close a channel. * * This sends an end of file and then closes the channel. You won't be able * to recover any data the server was going to send or was in buffers. * * @param[in] channel The channel to close. * * @return SSH_OK on success, SSH_ERROR if an error occurred. * * @see ssh_channel_free() * @see ssh_channel_is_eof() */ int ssh_channel_close(ssh_channel channel) { ssh_session session; int rc = 0; if(channel == NULL) { return SSH_ERROR; } /* If the channel close has already been sent we're done here. */ if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_LOCAL) { return SSH_OK; } session = channel->session; rc = ssh_channel_send_eof(channel); if (rc != SSH_OK) { return rc; } rc = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_CHANNEL_CLOSE, channel->remote_channel); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = ssh_packet_send(session); SSH_LOG(SSH_LOG_PACKET, "Sent a close on client channel (%d:%d)", channel->local_channel, channel->remote_channel); if (rc == SSH_OK) { channel->state = SSH_CHANNEL_STATE_CLOSED; channel->flags |= SSH_CHANNEL_FLAG_CLOSED_LOCAL; } rc = ssh_channel_flush(channel); if(rc == SSH_ERROR) { goto error; } return rc; error: ssh_buffer_reinit(session->out_buffer); return rc; } /* this termination function waits for a window growing condition */ static int ssh_channel_waitwindow_termination(void *c){ ssh_channel channel = (ssh_channel) c; if (channel->remote_window > 0 || channel->session->session_state == SSH_SESSION_STATE_ERROR || channel->state == SSH_CHANNEL_STATE_CLOSED) return 1; else return 0; } /* This termination function waits until the session is not in blocked status * anymore, e.g. because of a key re-exchange. */ static int ssh_waitsession_unblocked(void *s){ ssh_session session = (ssh_session)s; switch (session->session_state){ case SSH_SESSION_STATE_DH: case SSH_SESSION_STATE_INITIAL_KEX: case SSH_SESSION_STATE_KEXINIT_RECEIVED: return 0; default: return 1; } } /** * @internal * @brief Flushes a channel (and its session) until the output buffer * is empty, or timeout elapsed. * @param channel SSH channel * @return SSH_OK On success, * SSH_ERROR On error. * SSH_AGAIN Timeout elapsed (or in nonblocking mode). */ int ssh_channel_flush(ssh_channel channel){ return ssh_blocking_flush(channel->session, SSH_TIMEOUT_DEFAULT); } static int channel_write_common(ssh_channel channel, const void *data, uint32_t len, int is_stderr) { ssh_session session; uint32_t origlen = len; size_t effectivelen; size_t maxpacketlen; int rc; if(channel == NULL) { return -1; } session = channel->session; if(data == NULL) { ssh_set_error_invalid(session); return -1; } if (len > INT_MAX) { SSH_LOG(SSH_LOG_PROTOCOL, "Length (%u) is bigger than INT_MAX", len); return SSH_ERROR; } /* * Handle the max packet len from remote side, be nice * 10 bytes for the headers */ maxpacketlen = channel->remote_maxpacket - 10; if (channel->local_eof) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't write to channel %d:%d after EOF was sent", channel->local_channel, channel->remote_channel); return -1; } if (channel->state != SSH_CHANNEL_STATE_OPEN || channel->delayed_close != 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Remote channel is closed"); return -1; } if (session->session_state == SSH_SESSION_STATE_ERROR) { return SSH_ERROR; } if (ssh_waitsession_unblocked(session) == 0){ rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, ssh_waitsession_unblocked, session); if (rc == SSH_ERROR || !ssh_waitsession_unblocked(session)) goto out; } while (len > 0) { if (channel->remote_window < len) { SSH_LOG(SSH_LOG_PROTOCOL, "Remote window is %d bytes. going to write %d bytes", channel->remote_window, len); /* What happens when the channel window is zero? */ if(channel->remote_window == 0) { /* nothing can be written */ SSH_LOG(SSH_LOG_PROTOCOL, "Wait for a growing window message..."); rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, ssh_channel_waitwindow_termination,channel); if (rc == SSH_ERROR || !ssh_channel_waitwindow_termination(channel) || session->session_state == SSH_SESSION_STATE_ERROR || channel->state == SSH_CHANNEL_STATE_CLOSED) goto out; continue; } effectivelen = MIN(len, channel->remote_window); } else { effectivelen = len; } effectivelen = MIN(effectivelen, maxpacketlen);; rc = ssh_buffer_pack(session->out_buffer, "bd", is_stderr ? SSH2_MSG_CHANNEL_EXTENDED_DATA : SSH2_MSG_CHANNEL_DATA, channel->remote_channel); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } /* stderr message has an extra field */ if (is_stderr) { rc = ssh_buffer_pack(session->out_buffer, "d", SSH2_EXTENDED_DATA_STDERR); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } } /* append payload data */ rc = ssh_buffer_pack(session->out_buffer, "dP", effectivelen, (size_t)effectivelen, data); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "channel_write wrote %ld bytes", (long int) effectivelen); channel->remote_window -= effectivelen; len -= effectivelen; data = ((uint8_t*)data + effectivelen); if (channel->counter != NULL) { channel->counter->out_bytes += effectivelen; } } /* it's a good idea to flush the socket now */ rc = ssh_channel_flush(channel); if (rc == SSH_ERROR) { goto error; } out: return (int)(origlen - len); error: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; } /** * @brief Get the remote window size. * * This is the maximum amounts of bytes the remote side expects us to send * before growing the window again. * * @param[in] channel The channel to query. * * @return The remote window size * * @warning A nonzero return value does not guarantee the socket is ready * to send that much data. Buffering may happen in the local SSH * packet buffer, so beware of really big window sizes. * * @warning A zero return value means ssh_channel_write (default settings) * will block until the window grows back. */ uint32_t ssh_channel_window_size(ssh_channel channel) { return channel->remote_window; } /** * @brief Blocking write on a channel. * * @param[in] channel The channel to write to. * * @param[in] data A pointer to the data to write. * * @param[in] len The length of the buffer to write to. * * @return The number of bytes written, SSH_ERROR on error. * * @see ssh_channel_read() */ int ssh_channel_write(ssh_channel channel, const void *data, uint32_t len) { return channel_write_common(channel, data, len, 0); } /** * @brief Check if the channel is open or not. * * @param[in] channel The channel to check. * * @return 0 if channel is closed, nonzero otherwise. * * @see ssh_channel_is_closed() */ int ssh_channel_is_open(ssh_channel channel) { if(channel == NULL) { return 0; } return (channel->state == SSH_CHANNEL_STATE_OPEN && channel->session->alive != 0); } /** * @brief Check if the channel is closed or not. * * @param[in] channel The channel to check. * * @return 0 if channel is opened, nonzero otherwise. * * @see ssh_channel_is_open() */ int ssh_channel_is_closed(ssh_channel channel) { if(channel == NULL) { return SSH_ERROR; } return (channel->state != SSH_CHANNEL_STATE_OPEN || channel->session->alive == 0); } /** * @brief Check if remote has sent an EOF. * * @param[in] channel The channel to check. * * @return 0 if there is no EOF, nonzero otherwise. */ int ssh_channel_is_eof(ssh_channel channel) { if(channel == NULL) { return SSH_ERROR; } if ((channel->stdout_buffer && ssh_buffer_get_len(channel->stdout_buffer) > 0) || (channel->stderr_buffer && ssh_buffer_get_len(channel->stderr_buffer) > 0)) { return 0; } return (channel->remote_eof != 0); } /** * @brief Put the channel into blocking or nonblocking mode. * * @param[in] channel The channel to use. * * @param[in] blocking A boolean for blocking or nonblocking. * * @warning A side-effect of this is to put the whole session * in non-blocking mode. * @see ssh_set_blocking() */ void ssh_channel_set_blocking(ssh_channel channel, int blocking) { if(channel == NULL) { return; } ssh_set_blocking(channel->session,blocking); } /** * @internal * * @brief handle a SSH_CHANNEL_SUCCESS packet and set the channel state. */ SSH_PACKET_CALLBACK(ssh_packet_channel_success){ ssh_channel channel; (void)type; (void)user; channel=channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Received SSH_CHANNEL_SUCCESS on channel (%d:%d)", channel->local_channel, channel->remote_channel); if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING){ SSH_LOG(SSH_LOG_RARE, "SSH_CHANNEL_SUCCESS received in incorrect state %d", channel->request_state); } else { channel->request_state=SSH_CHANNEL_REQ_STATE_ACCEPTED; } return SSH_PACKET_USED; } /** * @internal * * @brief Handle a SSH_CHANNEL_FAILURE packet and set the channel state. */ SSH_PACKET_CALLBACK(ssh_packet_channel_failure){ ssh_channel channel; (void)type; (void)user; channel=channel_from_msg(session,packet); if (channel == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "%s", ssh_get_error(session)); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Received SSH_CHANNEL_FAILURE on channel (%d:%d)", channel->local_channel, channel->remote_channel); if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING){ SSH_LOG(SSH_LOG_RARE, "SSH_CHANNEL_FAILURE received in incorrect state %d", channel->request_state); } else { channel->request_state=SSH_CHANNEL_REQ_STATE_DENIED; } return SSH_PACKET_USED; } static int ssh_channel_request_termination(void *c){ ssh_channel channel = (ssh_channel)c; if(channel->request_state != SSH_CHANNEL_REQ_STATE_PENDING || channel->session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } static int channel_request(ssh_channel channel, const char *request, ssh_buffer buffer, int reply) { ssh_session session = channel->session; int rc = SSH_ERROR; int ret; switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } ret = ssh_buffer_pack(session->out_buffer, "bdsb", SSH2_MSG_CHANNEL_REQUEST, channel->remote_channel, request, reply == 0 ? 0 : 1); if (ret != SSH_OK) { ssh_set_error_oom(session); goto error; } if (buffer != NULL) { if (ssh_buffer_add_data(session->out_buffer, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)) < 0) { ssh_set_error_oom(session); goto error; } } channel->request_state = SSH_CHANNEL_REQ_STATE_PENDING; if (ssh_packet_send(session) == SSH_ERROR) { return rc; } SSH_LOG(SSH_LOG_PACKET, "Sent a SSH_MSG_CHANNEL_REQUEST %s", request); if (reply == 0) { channel->request_state = SSH_CHANNEL_REQ_STATE_NONE; return SSH_OK; } pending: rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, ssh_channel_request_termination, channel); if(session->session_state == SSH_SESSION_STATE_ERROR || rc == SSH_ERROR) { channel->request_state = SSH_CHANNEL_REQ_STATE_ERROR; } /* we received something */ switch (channel->request_state){ case SSH_CHANNEL_REQ_STATE_ERROR: rc=SSH_ERROR; break; case SSH_CHANNEL_REQ_STATE_DENIED: ssh_set_error(session, SSH_REQUEST_DENIED, "Channel request %s failed", request); rc=SSH_ERROR; break; case SSH_CHANNEL_REQ_STATE_ACCEPTED: SSH_LOG(SSH_LOG_PROTOCOL, "Channel request %s success",request); rc=SSH_OK; break; case SSH_CHANNEL_REQ_STATE_PENDING: rc = SSH_AGAIN; return rc; case SSH_CHANNEL_REQ_STATE_NONE: /* Never reached */ ssh_set_error(session, SSH_FATAL, "Invalid state in channel_request()"); rc=SSH_ERROR; break; } channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; return rc; error: ssh_buffer_reinit(session->out_buffer); return rc; } /** * @brief Request a pty with a specific type and size. * * @param[in] channel The channel to sent the request. * * @param[in] terminal The terminal type ("vt100, xterm,..."). * * @param[in] col The number of columns. * * @param[in] row The number of rows. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. */ int ssh_channel_request_pty_size(ssh_channel channel, const char *terminal, int col, int row) { ssh_session session; ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } session = channel->session; if(terminal == NULL) { ssh_set_error_invalid(channel->session); return rc; } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(buffer, "sdddddb", terminal, col, row, 0, /* pix */ 0, /* pix */ 1, /* add a 0byte string */ 0); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } pending: rc = channel_request(channel, "pty-req", buffer, 1); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Request a PTY. * * @param[in] channel The channel to send the request. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @see ssh_channel_request_pty_size() */ int ssh_channel_request_pty(ssh_channel channel) { return ssh_channel_request_pty_size(channel, "xterm", 80, 24); } /** * @brief Change the size of the terminal associated to a channel. * * @param[in] channel The channel to change the size. * * @param[in] cols The new number of columns. * * @param[in] rows The new number of rows. * * @return SSH_OK on success, SSH_ERROR if an error occurred. * * @warning Do not call it from a signal handler if you are not sure any other * libssh function using the same channel/session is running at same * time (not 100% threadsafe). */ int ssh_channel_change_pty_size(ssh_channel channel, int cols, int rows) { ssh_session session = channel->session; ssh_buffer buffer = NULL; int rc = SSH_ERROR; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(buffer, "dddd", cols, rows, 0, /* pix */ 0 /* pix */); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } rc = channel_request(channel, "window-change", buffer, 0); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Request a shell. * * @param[in] channel The channel to send the request. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. */ int ssh_channel_request_shell(ssh_channel channel) { if(channel == NULL) { return SSH_ERROR; } return channel_request(channel, "shell", NULL, 1); } /** * @brief Request a subsystem (for example "sftp"). * * @param[in] channel The channel to send the request. * * @param[in] subsys The subsystem to request (for example "sftp"). * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @warning You normally don't have to call it for sftp, see sftp_new(). */ int ssh_channel_request_subsystem(ssh_channel channel, const char *subsys) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } if(subsys == NULL) { ssh_set_error_invalid(channel->session); return rc; } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "s", subsys); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } pending: rc = channel_request(channel, "subsystem", buffer, 1); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Request sftp subsystem on the channel * * @param[in] channel The channel to request the sftp subsystem. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @note You should use sftp_new() which does this for you. */ int ssh_channel_request_sftp( ssh_channel channel){ if(channel == NULL) { return SSH_ERROR; } return ssh_channel_request_subsystem(channel, "sftp"); } static char *generate_cookie(void) { static const char *hex = "0123456789abcdef"; char s[36]; unsigned char rnd[16]; int ok; int i; ok = ssh_get_random(rnd, sizeof(rnd), 0); if (!ok) { return NULL; } for (i = 0; i < 16; i++) { s[i*2] = hex[rnd[i] & 0x0f]; s[i*2+1] = hex[rnd[i] >> 4]; } s[32] = '\0'; return strdup(s); } /** * @brief Sends the "x11-req" channel request over an existing session channel. * * This will enable redirecting the display of the remote X11 applications to * local X server over an secure tunnel. * * @param[in] channel An existing session channel where the remote X11 * applications are going to be executed. * * @param[in] single_connection A boolean to mark only one X11 app will be * redirected. * * @param[in] protocol A x11 authentication protocol. Pass NULL to use the * default value MIT-MAGIC-COOKIE-1. * * @param[in] cookie A x11 authentication cookie. Pass NULL to generate * a random cookie. * * @param[in] screen_number The screen number. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. */ int ssh_channel_request_x11(ssh_channel channel, int single_connection, const char *protocol, const char *cookie, int screen_number) { ssh_buffer buffer = NULL; char *c = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } if (cookie == NULL) { c = generate_cookie(); if (c == NULL) { ssh_set_error_oom(channel->session); goto error; } } rc = ssh_buffer_pack(buffer, "bssd", single_connection == 0 ? 0 : 1, protocol ? protocol : "MIT-MAGIC-COOKIE-1", cookie ? cookie : c, screen_number); if (c != NULL){ SAFE_FREE(c); } if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } pending: rc = channel_request(channel, "x11-req", buffer, 1); error: SSH_BUFFER_FREE(buffer); return rc; } static ssh_channel ssh_channel_accept(ssh_session session, int channeltype, int timeout_ms, int *destination_port) { #ifndef _WIN32 static const struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 /* 50ms */ }; #endif ssh_message msg = NULL; ssh_channel channel = NULL; struct ssh_iterator *iterator; int t; /* * We sleep for 50 ms in ssh_handle_packets() and later sleep for * 50 ms. So we need to decrement by 100 ms. */ for (t = timeout_ms; t >= 0; t -= 100) { if (timeout_ms == 0) { ssh_handle_packets(session, 0); } else { ssh_handle_packets(session, 50); } if (session->ssh_message_list) { iterator = ssh_list_get_iterator(session->ssh_message_list); while (iterator) { msg = (ssh_message)iterator->data; if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL_OPEN && ssh_message_subtype(msg) == channeltype) { ssh_list_remove(session->ssh_message_list, iterator); channel = ssh_message_channel_request_open_reply_accept(msg); if(destination_port) { *destination_port=msg->channel_request_open.destination_port; } ssh_message_free(msg); return channel; } iterator = iterator->next; } } if(t>0){ #ifdef _WIN32 Sleep(50); /* 50ms */ #else nanosleep(&ts, NULL); #endif } } ssh_set_error(session, SSH_NO_ERROR, "No channel request of this type from server"); return NULL; } /** * @brief Accept an X11 forwarding channel. * * @param[in] channel An x11-enabled session channel. * * @param[in] timeout_ms Timeout in milliseconds. * * @return A newly created channel, or NULL if no X11 request from * the server. */ ssh_channel ssh_channel_accept_x11(ssh_channel channel, int timeout_ms) { return ssh_channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms, NULL); } /** * @brief Send an "auth-agent-req" channel request over an existing session channel. * * This client-side request will enable forwarding the agent over an secure tunnel. * When the server is ready to open one authentication agent channel, an * ssh_channel_open_request_auth_agent_callback event will be generated. * * @param[in] channel The channel to send signal. * * @return SSH_OK on success, SSH_ERROR if an error occurred */ int ssh_channel_request_auth_agent(ssh_channel channel) { if (channel == NULL) { return SSH_ERROR; } return channel_request(channel, "auth-agent-req@openssh.com", NULL, 0); } /** * @internal * * @brief Handle a SSH_REQUEST_SUCCESS packet normally sent after a global * request. */ SSH_PACKET_CALLBACK(ssh_request_success){ (void)type; (void)user; (void)packet; SSH_LOG(SSH_LOG_PACKET, "Received SSH_REQUEST_SUCCESS"); if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){ SSH_LOG(SSH_LOG_RARE, "SSH_REQUEST_SUCCESS received in incorrect state %d", session->global_req_state); } else { session->global_req_state=SSH_CHANNEL_REQ_STATE_ACCEPTED; } return SSH_PACKET_USED; } /** * @internal * * @brief Handle a SSH_REQUEST_DENIED packet normally sent after a global * request. */ SSH_PACKET_CALLBACK(ssh_request_denied){ (void)type; (void)user; (void)packet; SSH_LOG(SSH_LOG_PACKET, "Received SSH_REQUEST_FAILURE"); if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){ SSH_LOG(SSH_LOG_RARE, "SSH_REQUEST_DENIED received in incorrect state %d", session->global_req_state); } else { session->global_req_state=SSH_CHANNEL_REQ_STATE_DENIED; } return SSH_PACKET_USED; } static int ssh_global_request_termination(void *s){ ssh_session session = (ssh_session) s; if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING || session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } /** * @internal * * @brief Send a global request (needed for forward listening) and wait for the * result. * * @param[in] session The SSH session handle. * * @param[in] request The type of request (defined in RFC). * * @param[in] buffer Additional data to put in packet. * * @param[in] reply Set if you expect a reply from server. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. */ int ssh_global_request(ssh_session session, const char *request, ssh_buffer buffer, int reply) { int rc; switch (session->global_req_state) { case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } rc = ssh_buffer_pack(session->out_buffer, "bsb", SSH2_MSG_GLOBAL_REQUEST, request, reply == 0 ? 0 : 1); if (rc != SSH_OK){ ssh_set_error_oom(session); rc = SSH_ERROR; goto error; } if (buffer != NULL) { rc = ssh_buffer_add_data(session->out_buffer, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); if (rc < 0) { ssh_set_error_oom(session); rc = SSH_ERROR; goto error; } } session->global_req_state = SSH_CHANNEL_REQ_STATE_PENDING; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return rc; } SSH_LOG(SSH_LOG_PACKET, "Sent a SSH_MSG_GLOBAL_REQUEST %s", request); if (reply == 0) { session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE; return SSH_OK; } pending: rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_DEFAULT, ssh_global_request_termination, session); if(rc==SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR){ session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR; } switch(session->global_req_state){ case SSH_CHANNEL_REQ_STATE_ACCEPTED: SSH_LOG(SSH_LOG_PROTOCOL, "Global request %s success",request); rc=SSH_OK; break; case SSH_CHANNEL_REQ_STATE_DENIED: SSH_LOG(SSH_LOG_PACKET, "Global request %s failed", request); ssh_set_error(session, SSH_REQUEST_DENIED, "Global request %s failed", request); rc=SSH_ERROR; break; case SSH_CHANNEL_REQ_STATE_ERROR: case SSH_CHANNEL_REQ_STATE_NONE: rc = SSH_ERROR; break; case SSH_CHANNEL_REQ_STATE_PENDING: return SSH_AGAIN; } session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE; return rc; error: ssh_buffer_reinit(session->out_buffer); return rc; } /** * @brief Sends the "tcpip-forward" global request to ask the server to begin * listening for inbound connections. * * @param[in] session The ssh session to send the request. * * @param[in] address The address to bind to on the server. Pass NULL to bind * to all available addresses on all protocol families * supported by the server. * * @param[in] port The port to bind to on the server. Pass 0 to ask the * server to allocate the next available unprivileged port * number * * @param[in] bound_port The pointer to get actual bound port. Pass NULL to * ignore. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. **/ int ssh_channel_listen_forward(ssh_session session, const char *address, int port, int *bound_port) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE) goto pending; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(buffer, "sd", address ? address : "", port); if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } pending: rc = ssh_global_request(session, "tcpip-forward", buffer, 1); /* TODO: FIXME no guarantee the last packet we received contains * that info */ if (rc == SSH_OK && port == 0 && bound_port != NULL) { rc = ssh_buffer_unpack(session->in_buffer, "d", bound_port); if (rc != SSH_OK) *bound_port = 0; } error: SSH_BUFFER_FREE(buffer); return rc; } /* DEPRECATED */ int ssh_forward_listen(ssh_session session, const char *address, int port, int *bound_port) { return ssh_channel_listen_forward(session, address, port, bound_port); } /* DEPRECATED */ ssh_channel ssh_forward_accept(ssh_session session, int timeout_ms) { return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, NULL); } /** * @brief Accept an incoming TCP/IP forwarding channel and get information * about incomming connection * @param[in] session The ssh session to use. * * @param[in] timeout_ms A timeout in milliseconds. * * @param[in] destination_port A pointer to destination port or NULL. * * @return Newly created channel, or NULL if no incoming channel request from * the server */ ssh_channel ssh_channel_accept_forward(ssh_session session, int timeout_ms, int* destination_port) { return ssh_channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms, destination_port); } /** * @brief Sends the "cancel-tcpip-forward" global request to ask the server to * cancel the tcpip-forward request. * * @param[in] session The ssh session to send the request. * * @param[in] address The bound address on the server. * * @param[in] port The bound port on the server. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. */ int ssh_channel_cancel_forward(ssh_session session, const char *address, int port) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE) goto pending; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(buffer, "sd", address ? address : "", port); if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } pending: rc = ssh_global_request(session, "cancel-tcpip-forward", buffer, 1); error: SSH_BUFFER_FREE(buffer); return rc; } /* DEPRECATED */ int ssh_forward_cancel(ssh_session session, const char *address, int port) { return ssh_channel_cancel_forward(session, address, port); } /** * @brief Set environment variables. * * @param[in] channel The channel to set the environment variables. * * @param[in] name The name of the variable. * * @param[in] value The value to set. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * @warning Some environment variables may be refused by security reasons. */ int ssh_channel_request_env(ssh_channel channel, const char *name, const char *value) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } if(name == NULL || value == NULL) { ssh_set_error_invalid(channel->session); return rc; } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "ss", name, value); if (rc != SSH_OK){ ssh_set_error_oom(channel->session); goto error; } pending: rc = channel_request(channel, "env", buffer,1); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Run a shell command without an interactive shell. * * This is similar to 'sh -c command'. * * @param[in] channel The channel to execute the command. * * @param[in] cmd The command to execute * (e.g. "ls ~/ -al | grep -i reports"). * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * Example: @code rc = ssh_channel_request_exec(channel, "ps aux"); if (rc > 0) { return -1; } while ((rc = ssh_channel_read(channel, buffer, sizeof(buffer), 0)) > 0) { if (fwrite(buffer, 1, rc, stdout) != (unsigned int) rc) { return -1; } } @endcode * * @see ssh_channel_request_shell() */ int ssh_channel_request_exec(ssh_channel channel, const char *cmd) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } if(cmd == NULL) { ssh_set_error_invalid(channel->session); return rc; } switch(channel->request_state){ case SSH_CHANNEL_REQ_STATE_NONE: break; default: goto pending; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "s", cmd); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } pending: rc = channel_request(channel, "exec", buffer, 1); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Send a signal to remote process (as described in RFC 4254, section 6.9). * * Sends a signal 'sig' to the remote process. * Note, that remote system may not support signals concept. * In such a case this request will be silently ignored. * Only SSH-v2 is supported (I'm not sure about SSH-v1). * * OpenSSH doesn't support signals yet, see: * https://bugzilla.mindrot.org/show_bug.cgi?id=1424 * * @param[in] channel The channel to send signal. * * @param[in] sig The signal to send (without SIG prefix) * \n\n * SIGABRT -> ABRT \n * SIGALRM -> ALRM \n * SIGFPE -> FPE \n * SIGHUP -> HUP \n * SIGILL -> ILL \n * SIGINT -> INT \n * SIGKILL -> KILL \n * SIGPIPE -> PIPE \n * SIGQUIT -> QUIT \n * SIGSEGV -> SEGV \n * SIGTERM -> TERM \n * SIGUSR1 -> USR1 \n * SIGUSR2 -> USR2 \n * * @return SSH_OK on success, SSH_ERROR if an error occurred * (including attempts to send signal via SSH-v1 session). */ int ssh_channel_request_send_signal(ssh_channel channel, const char *sig) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } if(sig == NULL) { ssh_set_error_invalid(channel->session); return rc; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "s", sig); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } rc = channel_request(channel, "signal", buffer, 0); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Send a break signal to the server (as described in RFC 4335). * * Sends a break signal to the remote process. * Note, that remote system may not support breaks. * In such a case this request will be silently ignored. * Only SSH-v2 is supported. * * @param[in] channel The channel to send the break to. * * @param[in] length The break-length in milliseconds to send. * * @return SSH_OK on success, SSH_ERROR if an error occurred * (including attempts to send signal via SSH-v1 session). */ int ssh_channel_request_send_break(ssh_channel channel, uint32_t length) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if (channel == NULL) { return SSH_ERROR; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "d", length); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } rc = channel_request(channel, "break", buffer, 0); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Read data from a channel into a buffer. * * @param[in] channel The channel to read from. * * @param[in] buffer The buffer which will get the data. * * @param[in] count The count of bytes to be read. If it is bigger than 0, * the exact size will be read, else (bytes=0) it will * return once anything is available. * * @param is_stderr A boolean value to mark reading from the stderr stream. * * @return The number of bytes read, 0 on end of file or SSH_ERROR * on error. * @deprecated Please use ssh_channel_read instead * @warning This function doesn't work in nonblocking/timeout mode * @see ssh_channel_read */ int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count, int is_stderr) { ssh_session session; char buffer_tmp[8192]; int r; uint32_t total=0; if(channel == NULL) { return SSH_ERROR; } session = channel->session; if(buffer == NULL) { ssh_set_error_invalid(channel->session); return SSH_ERROR; } ssh_buffer_reinit(buffer); if(count==0){ do { r=ssh_channel_poll(channel, is_stderr); if(r < 0){ return r; } if(r > 0){ r=ssh_channel_read(channel, buffer_tmp, r, is_stderr); if(r < 0){ return r; } if(ssh_buffer_add_data(buffer,buffer_tmp,r) < 0){ ssh_set_error_oom(session); r = SSH_ERROR; } return r; } if(ssh_channel_is_eof(channel)){ return 0; } ssh_handle_packets(channel->session, SSH_TIMEOUT_INFINITE); } while (r == 0); } while(total < count){ r=ssh_channel_read(channel, buffer_tmp, sizeof(buffer_tmp), is_stderr); if(r<0){ return r; } if(r==0){ return total; } if (ssh_buffer_add_data(buffer,buffer_tmp,r) < 0) { ssh_set_error_oom(session); return SSH_ERROR; } total += r; } return total; } struct ssh_channel_read_termination_struct { ssh_channel channel; uint32_t count; ssh_buffer buffer; }; static int ssh_channel_read_termination(void *s){ struct ssh_channel_read_termination_struct *ctx = s; if (ssh_buffer_get_len(ctx->buffer) >= ctx->count || ctx->channel->remote_eof || ctx->channel->session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } /* TODO FIXME Fix the delayed close thing */ /* TODO FIXME Fix the blocking behaviours */ /** * @brief Reads data from a channel. * * @param[in] channel The channel to read from. * * @param[in] dest The destination buffer which will get the data. * * @param[in] count The count of bytes to be read. * * @param[in] is_stderr A boolean value to mark reading from the stderr flow. * * @return The number of bytes read, 0 on end of file or SSH_ERROR * on error. In nonblocking mode it Can return 0 if no data * is available or SSH_AGAIN. * * @warning This function may return less than count bytes of data, and won't * block until count bytes have been read. * @warning The read function using a buffer has been renamed to * channel_read_buffer(). */ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr) { return ssh_channel_read_timeout(channel, dest, count, is_stderr, SSH_TIMEOUT_DEFAULT); } /** * @brief Reads data from a channel. * * @param[in] channel The channel to read from. * * @param[in] dest The destination buffer which will get the data. * * @param[in] count The count of bytes to be read. * * @param[in] is_stderr A boolean value to mark reading from the stderr flow. * * @param[in] timeout_ms A timeout in milliseconds. A value of -1 means * infinite timeout. * * @return The number of bytes read, 0 on end of file or SSH_ERROR * on error. In nonblocking mode it Can return 0 if no data * is available or SSH_AGAIN. * * @warning This function may return less than count bytes of data, and won't * block until count bytes have been read. * @warning The read function using a buffer has been renamed to * channel_read_buffer(). */ int ssh_channel_read_timeout(ssh_channel channel, void *dest, uint32_t count, int is_stderr, int timeout_ms) { ssh_session session; ssh_buffer stdbuf; uint32_t len; struct ssh_channel_read_termination_struct ctx; int rc; if(channel == NULL) { return SSH_ERROR; } if(dest == NULL) { ssh_set_error_invalid(channel->session); return SSH_ERROR; } session = channel->session; stdbuf = channel->stdout_buffer; if (count == 0) { return 0; } if (is_stderr) { stdbuf=channel->stderr_buffer; } /* * We may have problem if the window is too small to accept as much data * as asked */ SSH_LOG(SSH_LOG_PACKET, "Read (%d) buffered : %d bytes. Window: %d", count, ssh_buffer_get_len(stdbuf), channel->local_window); if (count > ssh_buffer_get_len(stdbuf) + channel->local_window) { if (grow_window(session, channel, count - ssh_buffer_get_len(stdbuf)) < 0) { return -1; } } /* block reading until at least one byte has been read * and ignore the trivial case count=0 */ ctx.channel = channel; ctx.buffer = stdbuf; ctx.count = 1; if (timeout_ms < SSH_TIMEOUT_DEFAULT) { timeout_ms = SSH_TIMEOUT_INFINITE; } rc = ssh_handle_packets_termination(session, timeout_ms, ssh_channel_read_termination, &ctx); if (rc == SSH_AGAIN && ssh_is_blocking(session)) { ssh_set_error(session, SSH_FATAL, "Handle packets timeout."); return rc; } if (rc == SSH_ERROR){ return rc; } /* * If the channel is closed or in an error state, reading from it is an error */ if (session->session_state == SSH_SESSION_STATE_ERROR) { return SSH_ERROR; } /* If the server closed the channel properly, there is nothing to do */ if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) { return 0; } if (channel->state == SSH_CHANNEL_STATE_CLOSED) { ssh_set_error(session, SSH_FATAL, "Remote channel is closed."); return SSH_ERROR; } len = ssh_buffer_get_len(stdbuf); /* Read count bytes if len is greater, everything otherwise */ len = (len > count ? count : len); memcpy(dest, ssh_buffer_get(stdbuf), len); ssh_buffer_pass_bytes(stdbuf,len); if (channel->counter != NULL) { channel->counter->in_bytes += len; } /* Authorize some buffering while userapp is busy */ if (channel->local_window < WINDOWLIMIT) { if (grow_window(session, channel, 0) < 0) { return -1; } } return len; } /** * @brief Do a nonblocking read on the channel. * * A nonblocking read on the specified channel. it will return <= count bytes of * data read atomically. * * @param[in] channel The channel to read from. * * @param[in] dest A pointer to a destination buffer. * * @param[in] count The count of bytes of data to be read. * * @param[in] is_stderr A boolean to select the stderr stream. * * @return The number of bytes read, 0 if nothing is available or * SSH_ERROR on error. * * @warning Don't forget to check for EOF as it would return 0 here. * * @see ssh_channel_is_eof() */ int ssh_channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count, int is_stderr) { ssh_session session; ssize_t to_read; int rc; int blocking; if(channel == NULL) { return SSH_ERROR; } if(dest == NULL) { ssh_set_error_invalid(channel->session); return SSH_ERROR; } session = channel->session; to_read = ssh_channel_poll(channel, is_stderr); if (to_read <= 0) { if (session->session_state == SSH_SESSION_STATE_ERROR){ return SSH_ERROR; } return to_read; /* may be an error code */ } if ((size_t)to_read > count) { to_read = (ssize_t)count; } blocking = ssh_is_blocking(session); ssh_set_blocking(session, 0); rc = ssh_channel_read(channel, dest, (uint32_t)to_read, is_stderr); ssh_set_blocking(session,blocking); return rc; } /** * @brief Polls a channel for data to read. * * @param[in] channel The channel to poll. * * @param[in] is_stderr A boolean to select the stderr stream. * * @return The number of bytes available for reading, 0 if nothing * is available or SSH_ERROR on error. * * @warning When the channel is in EOF state, the function returns SSH_EOF. * * @see ssh_channel_is_eof() */ int ssh_channel_poll(ssh_channel channel, int is_stderr){ ssh_buffer stdbuf; if(channel == NULL) { return SSH_ERROR; } stdbuf = channel->stdout_buffer; if (is_stderr) { stdbuf = channel->stderr_buffer; } if (ssh_buffer_get_len(stdbuf) == 0 && channel->remote_eof == 0) { if (channel->session->session_state == SSH_SESSION_STATE_ERROR){ return SSH_ERROR; } if (ssh_handle_packets(channel->session, SSH_TIMEOUT_NONBLOCKING)==SSH_ERROR) { return SSH_ERROR; } } if (ssh_buffer_get_len(stdbuf) > 0){ return ssh_buffer_get_len(stdbuf); } if (channel->remote_eof) { return SSH_EOF; } return ssh_buffer_get_len(stdbuf); } /** * @brief Polls a channel for data to read, waiting for a certain timeout. * * @param[in] channel The channel to poll. * @param[in] timeout Set an upper limit on the time for which this function * will block, in milliseconds. Specifying a negative value * means an infinite timeout. This parameter is passed to * the poll() function. * @param[in] is_stderr A boolean to select the stderr stream. * * @return The number of bytes available for reading, * 0 if nothing is available (timeout elapsed), * SSH_EOF on end of file, * SSH_ERROR on error. * * @warning When the channel is in EOF state, the function returns SSH_EOF. * * @see ssh_channel_is_eof() */ int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr) { ssh_session session; ssh_buffer stdbuf; struct ssh_channel_read_termination_struct ctx; size_t len; int rc; if (channel == NULL) { return SSH_ERROR; } session = channel->session; stdbuf = channel->stdout_buffer; if (is_stderr) { stdbuf = channel->stderr_buffer; } ctx.buffer = stdbuf; ctx.channel = channel; ctx.count = 1; rc = ssh_handle_packets_termination(channel->session, timeout, ssh_channel_read_termination, &ctx); if (rc == SSH_ERROR || session->session_state == SSH_SESSION_STATE_ERROR) { rc = SSH_ERROR; goto out; } else if (rc == SSH_AGAIN) { /* If the above timeout expired, it is ok and we do not need to * attempt to check the read buffer. The calling functions do not * expect us to return SSH_AGAIN either here. */ rc = SSH_OK; goto out; } len = ssh_buffer_get_len(stdbuf); if (len > 0) { if (len > INT_MAX) { rc = SSH_ERROR; } else { rc = (int)len; } goto out; } if (channel->remote_eof) { rc = SSH_EOF; } out: return rc; } /** * @brief Recover the session in which belongs a channel. * * @param[in] channel The channel to recover the session from. * * @return The session pointer. */ ssh_session ssh_channel_get_session(ssh_channel channel) { if(channel == NULL) { return NULL; } return channel->session; } static int ssh_channel_exit_status_termination(void *c){ ssh_channel channel = c; if(channel->exit_status != -1 || /* When a channel is closed, no exit status message can * come anymore */ (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) || channel->session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } /** * @brief Get the exit status of the channel (error code from the executed * instruction). * * @param[in] channel The channel to get the status from. * * @return The exit status, -1 if no exit status has been returned * (yet), or SSH_ERROR on error. * @warning This function may block until a timeout (or never) * if the other side is not willing to close the channel. * * If you're looking for an async handling of this register a callback for the * exit status. * * @see ssh_channel_exit_status_callback */ int ssh_channel_get_exit_status(ssh_channel channel) { int rc; if(channel == NULL) { return SSH_ERROR; } rc = ssh_handle_packets_termination(channel->session, SSH_TIMEOUT_DEFAULT, ssh_channel_exit_status_termination, channel); if (rc == SSH_ERROR || channel->session->session_state == SSH_SESSION_STATE_ERROR) return SSH_ERROR; return channel->exit_status; } /* * This function acts as a meta select. * * First, channels are analyzed to seek potential can-write or can-read ones, * then if no channel has been elected, it goes in a loop with the posix * select(2). * This is made in two parts: protocol select and network select. The protocol * select does not use the network functions at all */ static int channel_protocol_select(ssh_channel *rchans, ssh_channel *wchans, ssh_channel *echans, ssh_channel *rout, ssh_channel *wout, ssh_channel *eout) { ssh_channel chan; int i; int j = 0; for (i = 0; rchans[i] != NULL; i++) { chan = rchans[i]; while (ssh_channel_is_open(chan) && ssh_socket_data_available(chan->session->socket)) { ssh_handle_packets(chan->session, SSH_TIMEOUT_NONBLOCKING); } if ((chan->stdout_buffer && ssh_buffer_get_len(chan->stdout_buffer) > 0) || (chan->stderr_buffer && ssh_buffer_get_len(chan->stderr_buffer) > 0) || chan->remote_eof) { rout[j] = chan; j++; } } rout[j] = NULL; j = 0; for(i = 0; wchans[i] != NULL; i++) { chan = wchans[i]; /* It's not our business to seek if the file descriptor is writable */ if (ssh_socket_data_writable(chan->session->socket) && ssh_channel_is_open(chan) && (chan->remote_window > 0)) { wout[j] = chan; j++; } } wout[j] = NULL; j = 0; for (i = 0; echans[i] != NULL; i++) { chan = echans[i]; if (!ssh_socket_is_open(chan->session->socket) || ssh_channel_is_closed(chan)) { eout[j] = chan; j++; } } eout[j] = NULL; return 0; } /* Just count number of pointers in the array */ static size_t count_ptrs(ssh_channel *ptrs) { size_t c; for (c = 0; ptrs[c] != NULL; c++) ; return c; } /** * @brief Act like the standard select(2) on channels. * * The list of pointers are then actualized and will only contain pointers to * channels that are respectively readable, writable or have an exception to * trap. * * @param[in] readchans A NULL pointer or an array of channel pointers, * terminated by a NULL. * * @param[in] writechans A NULL pointer or an array of channel pointers, * terminated by a NULL. * * @param[in] exceptchans A NULL pointer or an array of channel pointers, * terminated by a NULL. * * @param[in] timeout Timeout as defined by select(2). * * @return SSH_OK on a successful operation, SSH_EINTR if the * select(2) syscall was interrupted, then relaunch the * function, or SSH_ERROR on error. */ int ssh_channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout) { ssh_channel *rchans, *wchans, *echans; ssh_channel dummy = NULL; ssh_event event = NULL; int rc; int i; int tm, tm_base; int firstround=1; struct ssh_timestamp ts; if (timeout != NULL) tm_base = timeout->tv_sec * 1000 + timeout->tv_usec/1000; else tm_base = SSH_TIMEOUT_INFINITE; ssh_timestamp_init(&ts); tm = tm_base; /* don't allow NULL pointers */ if (readchans == NULL) { readchans = &dummy; } if (writechans == NULL) { writechans = &dummy; } if (exceptchans == NULL) { exceptchans = &dummy; } if (readchans[0] == NULL && writechans[0] == NULL && exceptchans[0] == NULL) { /* No channel to poll?? Go away! */ return 0; } /* Prepare the outgoing temporary arrays */ rchans = calloc(count_ptrs(readchans) + 1, sizeof(ssh_channel)); if (rchans == NULL) { return SSH_ERROR; } wchans = calloc(count_ptrs(writechans) + 1, sizeof(ssh_channel)); if (wchans == NULL) { SAFE_FREE(rchans); return SSH_ERROR; } echans = calloc(count_ptrs(exceptchans) + 1, sizeof(ssh_channel)); if (echans == NULL) { SAFE_FREE(rchans); SAFE_FREE(wchans); return SSH_ERROR; } /* * First, try without doing network stuff then, use the ssh_poll * infrastructure to poll on all sessions. */ do { channel_protocol_select(readchans, writechans, exceptchans, rchans, wchans, echans); if (rchans[0] != NULL || wchans[0] != NULL || echans[0] != NULL) { /* At least one channel has an event */ break; } /* Add all channels' sessions right into an event object */ if (event == NULL) { event = ssh_event_new(); if (event == NULL) { SAFE_FREE(rchans); SAFE_FREE(wchans); SAFE_FREE(echans); return SSH_ERROR; } for (i = 0; readchans[i] != NULL; i++) { ssh_poll_get_default_ctx(readchans[i]->session); ssh_event_add_session(event, readchans[i]->session); } for (i = 0; writechans[i] != NULL; i++) { ssh_poll_get_default_ctx(writechans[i]->session); ssh_event_add_session(event, writechans[i]->session); } for (i = 0; exceptchans[i] != NULL; i++) { ssh_poll_get_default_ctx(exceptchans[i]->session); ssh_event_add_session(event, exceptchans[i]->session); } } /* Get out if the timeout has elapsed */ if (!firstround && ssh_timeout_elapsed(&ts, tm_base)){ break; } /* Here we go */ rc = ssh_event_dopoll(event,tm); if (rc != SSH_OK){ SAFE_FREE(rchans); SAFE_FREE(wchans); SAFE_FREE(echans); ssh_event_free(event); return rc; } tm = ssh_timeout_update(&ts, tm_base); firstround=0; } while(1); memcpy(readchans, rchans, (count_ptrs(rchans) + 1) * sizeof(ssh_channel )); memcpy(writechans, wchans, (count_ptrs(wchans) + 1) * sizeof(ssh_channel )); memcpy(exceptchans, echans, (count_ptrs(echans) + 1) * sizeof(ssh_channel )); SAFE_FREE(rchans); SAFE_FREE(wchans); SAFE_FREE(echans); if(event) ssh_event_free(event); return 0; } /** * @brief Set the channel data counter. * * @code * struct ssh_counter_struct counter = { * .in_bytes = 0, * .out_bytes = 0, * .in_packets = 0, * .out_packets = 0 * }; * * ssh_channel_set_counter(channel, &counter); * @endcode * * @param[in] channel The SSH channel. * * @param[in] counter Counter for bytes handled by the channel. */ void ssh_channel_set_counter(ssh_channel channel, ssh_counter counter) { if (channel != NULL) { channel->counter = counter; } } /** * @brief Blocking write on a channel stderr. * * @param[in] channel The channel to write to. * * @param[in] data A pointer to the data to write. * * @param[in] len The length of the buffer to write to. * * @return The number of bytes written, SSH_ERROR on error. * * @see ssh_channel_read() */ int ssh_channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) { return channel_write_common(channel, data, len, 1); } #if WITH_SERVER /** * @brief Open a TCP/IP reverse forwarding channel. * * @param[in] channel An allocated channel. * * @param[in] remotehost The remote host to connected (host name or IP). * * @param[in] remoteport The remote port. * * @param[in] sourcehost The source host (your local computer). It's optional * and for logging purpose. * * @param[in] localport The source port (your local computer). It's optional * and for logging purpose. * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * * @warning This function does not bind the local port and does not automatically * forward the content of a socket to the channel. You still have to * use channel_read and channel_write for this. */ int ssh_channel_open_reverse_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport) { ssh_session session; ssh_buffer payload = NULL; int rc = SSH_ERROR; if(channel == NULL) { return rc; } if(remotehost == NULL || sourcehost == NULL) { ssh_set_error_invalid(channel->session); return rc; } session = channel->session; if(channel->state != SSH_CHANNEL_STATE_NOT_OPEN) goto pending; payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(payload, "sdsd", remotehost, remoteport, sourcehost, localport); if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } pending: rc = channel_open(channel, "forwarded-tcpip", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, payload); error: SSH_BUFFER_FREE(payload); return rc; } /** * @brief Open a X11 channel. * * @param[in] channel An allocated channel. * * @param[in] orig_addr The source host (the local server). * * @param[in] orig_port The source port (the local server). * * @return SSH_OK on success, * SSH_ERROR if an error occurred, * SSH_AGAIN if in nonblocking mode and call has * to be done again. * @warning This function does not bind the local port and does not automatically * forward the content of a socket to the channel. You still have to * use channel_read and channel_write for this. */ int ssh_channel_open_x11(ssh_channel channel, const char *orig_addr, int orig_port) { ssh_session session; ssh_buffer payload = NULL; int rc = SSH_ERROR; if(channel == NULL) { return rc; } if(orig_addr == NULL) { ssh_set_error_invalid(channel->session); return rc; } session = channel->session; if(channel->state != SSH_CHANNEL_STATE_NOT_OPEN) goto pending; payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(payload, "sd", orig_addr, orig_port); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } pending: rc = channel_open(channel, "x11", CHANNEL_INITIAL_WINDOW, CHANNEL_MAX_PACKET, payload); error: SSH_BUFFER_FREE(payload); return rc; } /** * @brief Send the exit status to the remote process * * Sends the exit status to the remote process (as described in RFC 4254, * section 6.10). * Only SSH-v2 is supported (I'm not sure about SSH-v1). * * @param[in] channel The channel to send exit status. * * @param[in] exit_status The exit status to send * * @return SSH_OK on success, SSH_ERROR if an error occurred. * (including attempts to send exit status via SSH-v1 session). */ int ssh_channel_request_send_exit_status(ssh_channel channel, int exit_status) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return SSH_ERROR; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "d", exit_status); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } rc = channel_request(channel, "exit-status", buffer, 0); error: SSH_BUFFER_FREE(buffer); return rc; } /** * @brief Send an exit signal to remote process (RFC 4254, section 6.10). * * This sends the exit status of the remote process. * Note, that remote system may not support signals concept. * In such a case this request will be silently ignored. * Only SSH-v2 is supported (I'm not sure about SSH-v1). * * @param[in] channel The channel to send signal. * * @param[in] sig The signal to send (without SIG prefix) * (e.g. "TERM" or "KILL"). * @param[in] core A boolean to tell if a core was dumped * @param[in] errmsg A CRLF explanation text about the error condition * @param[in] lang The language used in the message (format: RFC 3066) * * @return SSH_OK on success, SSH_ERROR if an error occurred * (including attempts to send signal via SSH-v1 session). */ int ssh_channel_request_send_exit_signal(ssh_channel channel, const char *sig, int core, const char *errmsg, const char *lang) { ssh_buffer buffer = NULL; int rc = SSH_ERROR; if(channel == NULL) { return rc; } if(sig == NULL || errmsg == NULL || lang == NULL) { ssh_set_error_invalid(channel->session); return rc; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(channel->session); goto error; } rc = ssh_buffer_pack(buffer, "sbss", sig, core ? 1 : 0, errmsg, lang); if (rc != SSH_OK) { ssh_set_error_oom(channel->session); goto error; } rc = channel_request(channel, "exit-signal", buffer, 0); error: SSH_BUFFER_FREE(buffer); return rc; } #endif /* @} */ ================================================ FILE: src/libssh/src/client.c ================================================ /* * client.c - SSH client functions * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/packet.h" #include "libssh/options.h" #include "libssh/socket.h" #include "libssh/session.h" #include "libssh/dh.h" #ifdef WITH_GEX #include "libssh/dh-gex.h" #endif /* WITH_GEX */ #include "libssh/ecdh.h" #include "libssh/threads.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/kex.h" #define set_status(session, status) do {\ if (session->common.callbacks && session->common.callbacks->connect_status_function) \ session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \ } while (0) /** * @internal * @brief Callback to be called when the socket is connected or had a * connection error. Changes the state of the session and updates the error * message. * @param code one of SSH_SOCKET_CONNECTED_OK or SSH_SOCKET_CONNECTED_ERROR * @param user is a pointer to session */ static void socket_callback_connected(int code, int errno_code, void *user){ ssh_session session=(ssh_session)user; if (session->session_state != SSH_SESSION_STATE_CONNECTING && session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED) { ssh_set_error(session,SSH_FATAL, "Wrong state in socket_callback_connected : %d", session->session_state); return; } SSH_LOG(SSH_LOG_RARE,"Socket connection callback: %d (%d)",code, errno_code); if(code == SSH_SOCKET_CONNECTED_OK) session->session_state=SSH_SESSION_STATE_SOCKET_CONNECTED; else { session->session_state=SSH_SESSION_STATE_ERROR; ssh_set_error(session,SSH_FATAL,"%s",strerror(errno_code)); } session->ssh_connection_callback(session); } /** * @internal * * @brief Gets the banner from socket and saves it in session. * Updates the session state * * @param data pointer to the beginning of header * @param len size of the banner * @param user is a pointer to session * @returns Number of bytes processed, or zero if the banner is not complete. */ static int callback_receive_banner(const void *data, size_t len, void *user) { char *buffer = (char *)data; ssh_session session=(ssh_session) user; char *str = NULL; size_t i; int ret=0; if (session->session_state != SSH_SESSION_STATE_SOCKET_CONNECTED) { ssh_set_error(session,SSH_FATAL, "Wrong state in callback_receive_banner : %d", session->session_state); return SSH_ERROR; } for (i = 0; i < len; ++i) { #ifdef WITH_PCAP if (session->pcap_ctx && buffer[i] == '\n') { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_IN, buffer,i+1, i+1); } #endif if (buffer[i] == '\r') { buffer[i] = '\0'; } if (buffer[i] == '\n') { int cmp; buffer[i] = '\0'; /* The server MAY send other lines of data... */ cmp = strncmp(buffer, "SSH-", 4); if (cmp == 0) { str = strdup(buffer); if (str == NULL) { return SSH_ERROR; } /* number of bytes read */ ret = i + 1; session->serverbanner = str; session->session_state = SSH_SESSION_STATE_BANNER_RECEIVED; SSH_LOG(SSH_LOG_PACKET, "Received banner: %s", str); session->ssh_connection_callback(session); return ret; } else { SSH_LOG(SSH_LOG_DEBUG, "ssh_protocol_version_exchange: %s", buffer); ret = i + 1; break; } } /* According to RFC 4253 the max banner length is 255 */ if (i > 255) { /* Too big banner */ session->session_state=SSH_SESSION_STATE_ERROR; ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner"); return 0; } } return ret; } /** @internal * @brief Sends a SSH banner to the server. * * @param session The SSH session to use. * * @param server Send client or server banner. * * @return 0 on success, < 0 on error. */ int ssh_send_banner(ssh_session session, int server) { const char *banner = CLIENT_BANNER_SSH2; const char *terminator = "\r\n"; /* The maximum banner length is 255 for SSH2 */ char buffer[256] = {0}; size_t len; int rc = SSH_ERROR; if (server == 1) { if (session->opts.custombanner == NULL){ session->serverbanner = strdup(banner); if (session->serverbanner == NULL) { goto end; } } else { len = strlen(session->opts.custombanner); session->serverbanner = malloc(len + 8 + 1); if(session->serverbanner == NULL) { goto end; } snprintf(session->serverbanner, len + 8 + 1, "SSH-2.0-%s", session->opts.custombanner); } snprintf(buffer, sizeof(buffer), "%s%s", session->serverbanner, terminator); } else { session->clientbanner = strdup(banner); if (session->clientbanner == NULL) { goto end; } snprintf(buffer, sizeof(buffer), "%s%s", session->clientbanner, terminator); } rc = ssh_socket_write(session->socket, buffer, strlen(buffer)); if (rc == SSH_ERROR) { goto end; } #ifdef WITH_PCAP if (session->pcap_ctx != NULL) { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_OUT, buffer, strlen(buffer), strlen(buffer)); } #endif rc = SSH_OK; end: return rc; } /** @internal * @brief launches the DH handshake state machine * @param session session handle * @returns SSH_OK or SSH_ERROR * @warning this function returning is no proof that DH handshake is * completed */ static int dh_handshake(ssh_session session) { int rc = SSH_AGAIN; switch (session->dh_handshake_state) { case DH_STATE_INIT: switch(session->next_crypto->kex_type){ case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: case SSH_KEX_DH_GROUP16_SHA512: case SSH_KEX_DH_GROUP18_SHA512: rc = ssh_client_dh_init(session); break; #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA1: case SSH_KEX_DH_GEX_SHA256: rc = ssh_client_dhgex_init(session); break; #endif /* WITH_GEX */ #ifdef HAVE_ECDH case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_ECDH_SHA2_NISTP384: case SSH_KEX_ECDH_SHA2_NISTP521: rc = ssh_client_ecdh_init(session); break; #endif #ifdef HAVE_CURVE25519 case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: rc = ssh_client_curve25519_init(session); break; #endif default: rc = SSH_ERROR; } break; case DH_STATE_INIT_SENT: /* wait until ssh_packet_dh_reply is called */ break; case DH_STATE_NEWKEYS_SENT: /* wait until ssh_packet_newkeys is called */ break; case DH_STATE_FINISHED: return SSH_OK; default: ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d", session->dh_handshake_state); return SSH_ERROR; } return rc; } static int ssh_service_request_termination(void *s){ ssh_session session = (ssh_session)s; if(session->session_state == SSH_SESSION_STATE_ERROR || session->auth.service_state != SSH_AUTH_SERVICE_SENT) return 1; else return 0; } /** * @internal * * @brief Request a service from the SSH server. * * Service requests are for example: ssh-userauth, ssh-connection, etc. * * @param session The session to use to ask for a service request. * @param service The service request. * * @return SSH_OK on success * @return SSH_ERROR on error * @return SSH_AGAIN No response received yet * @bug actually only works with ssh-userauth */ int ssh_service_request(ssh_session session, const char *service) { int rc=SSH_ERROR; if(session->auth.service_state != SSH_AUTH_SERVICE_NONE) goto pending; rc = ssh_buffer_pack(session->out_buffer, "bs", SSH2_MSG_SERVICE_REQUEST, service); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } session->auth.service_state = SSH_AUTH_SERVICE_SENT; if (ssh_packet_send(session) == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Sending SSH2_MSG_SERVICE_REQUEST failed."); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); pending: rc=ssh_handle_packets_termination(session,SSH_TIMEOUT_USER, ssh_service_request_termination, session); if (rc == SSH_ERROR) { return SSH_ERROR; } switch(session->auth.service_state) { case SSH_AUTH_SERVICE_DENIED: ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied"); break; case SSH_AUTH_SERVICE_ACCEPTED: rc=SSH_OK; break; case SSH_AUTH_SERVICE_SENT: rc=SSH_AGAIN; break; case SSH_AUTH_SERVICE_NONE: rc=SSH_ERROR; break; } return rc; } /** * @addtogroup libssh_session * * @{ */ /** * @internal * * @brief A function to be called each time a step has been done in the * connection. */ static void ssh_client_connection_callback(ssh_session session) { int rc; switch(session->session_state) { case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_CONNECTING: break; case SSH_SESSION_STATE_SOCKET_CONNECTED: ssh_set_fd_towrite(session); ssh_send_banner(session, 0); break; case SSH_SESSION_STATE_BANNER_RECEIVED: if (session->serverbanner == NULL) { goto error; } set_status(session, 0.4f); SSH_LOG(SSH_LOG_PROTOCOL, "SSH server banner: %s", session->serverbanner); /* Here we analyze the different protocols the server allows. */ rc = ssh_analyze_banner(session, 0); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "No version of SSH protocol usable (banner: %s)", session->serverbanner); goto error; } ssh_packet_register_socket_callback(session, session->socket); ssh_packet_set_default_callbacks(session); session->session_state = SSH_SESSION_STATE_INITIAL_KEX; rc = ssh_set_client_kex(session); if (rc != SSH_OK) { goto error; } rc = ssh_send_kex(session, 0); if (rc < 0) { goto error; } set_status(session, 0.5f); break; case SSH_SESSION_STATE_INITIAL_KEX: /* TODO: This state should disappear in favor of get_key handle */ break; case SSH_SESSION_STATE_KEXINIT_RECEIVED: set_status(session,0.6f); ssh_list_kex(&session->next_crypto->server_kex); if (session->next_crypto->client_kex.methods[0] == NULL) { /* in rekeying state if next_crypto client_kex is empty */ rc = ssh_set_client_kex(session); if (rc != SSH_OK) { goto error; } rc = ssh_send_kex(session, 0); if (rc < 0) { goto error; } } if (ssh_kex_select_methods(session) == SSH_ERROR) goto error; set_status(session,0.8f); session->session_state=SSH_SESSION_STATE_DH; if (dh_handshake(session) == SSH_ERROR) { goto error; } FALL_THROUGH; case SSH_SESSION_STATE_DH: if(session->dh_handshake_state==DH_STATE_FINISHED){ set_status(session,1.0f); session->connected = 1; if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) session->session_state = SSH_SESSION_STATE_AUTHENTICATED; else session->session_state=SSH_SESSION_STATE_AUTHENTICATING; } break; case SSH_SESSION_STATE_AUTHENTICATING: break; case SSH_SESSION_STATE_ERROR: goto error; default: ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); } return; error: ssh_socket_close(session->socket); session->alive = 0; session->session_state=SSH_SESSION_STATE_ERROR; } /** @internal * @brief describe under which conditions the ssh_connect function may stop */ static int ssh_connect_termination(void *user){ ssh_session session = (ssh_session)user; switch(session->session_state){ case SSH_SESSION_STATE_ERROR: case SSH_SESSION_STATE_AUTHENTICATING: case SSH_SESSION_STATE_DISCONNECTED: return 1; default: return 0; } } /** * @brief Connect to the ssh server. * * @param[in] session The ssh session to connect. * * @returns SSH_OK on success, SSH_ERROR on error. * @returns SSH_AGAIN, if the session is in nonblocking mode, * and call must be done again. * * @see ssh_new() * @see ssh_disconnect() */ int ssh_connect(ssh_session session) { int ret; if (!is_ssh_initialized()) { ssh_set_error(session, SSH_FATAL, "Library not initialized."); return SSH_ERROR; } if (session == NULL) { return SSH_ERROR; } switch(session->pending_call_state) { case SSH_PENDING_CALL_NONE: break; case SSH_PENDING_CALL_CONNECT: goto pending; default: ssh_set_error(session, SSH_FATAL, "Bad call during pending SSH call in ssh_connect"); return SSH_ERROR; } session->alive = 0; session->client = 1; if (session->opts.fd == SSH_INVALID_SOCKET && session->opts.host == NULL && session->opts.ProxyCommand == NULL) { ssh_set_error(session, SSH_FATAL, "Hostname required"); return SSH_ERROR; } /* If the system configuration files were not yet processed, do it now */ if (!session->opts.config_processed) { ret = ssh_options_parse_config(session, NULL); if (ret != 0) { ssh_set_error(session, SSH_FATAL, "Failed to process system configuration files"); return SSH_ERROR; } } ret = ssh_options_apply(session); if (ret < 0) { ssh_set_error(session, SSH_FATAL, "Couldn't apply options"); return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "libssh %s, using threading %s", ssh_copyright(), ssh_threads_get_type()); session->ssh_connection_callback = ssh_client_connection_callback; session->session_state = SSH_SESSION_STATE_CONNECTING; ssh_socket_set_callbacks(session->socket, &session->socket_callbacks); session->socket_callbacks.connected = socket_callback_connected; session->socket_callbacks.data = callback_receive_banner; session->socket_callbacks.exception = ssh_socket_exception_callback; session->socket_callbacks.userdata = session; ssh_socket_set_external_callbacks(session->socket, &session->socket_external_callbacks); if (session->opts.fd != SSH_INVALID_SOCKET) { session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED; ssh_socket_set_fd(session->socket, session->opts.fd); ret = SSH_OK; #ifndef _WIN32 } else if (session->opts.ProxyCommand != NULL) { ret = ssh_socket_connect_proxycommand(session->socket, session->opts.ProxyCommand); #endif } else { if (session->opts.proxy_host != NULL) { ret = ssh_socket_connect(session->socket, session->opts.proxy_host, session->opts.proxy_port > 0 ? session->opts.proxy_port : 22, session->opts.bindaddr); } else { ret = ssh_socket_connect(session->socket, session->opts.host, session->opts.port > 0 ? session->opts.port : 22, session->opts.bindaddr); } } if (ret == SSH_ERROR) { return SSH_ERROR; } set_status(session, 0.2f); session->alive = 1; SSH_LOG(SSH_LOG_PROTOCOL, "Socket connecting, now waiting for the callbacks to work"); pending: session->pending_call_state = SSH_PENDING_CALL_CONNECT; if(ssh_is_blocking(session)) { int timeout = (session->opts.timeout * 1000) + (session->opts.timeout_usec / 1000); if (timeout == 0) { timeout = 10 * 1000; } SSH_LOG(SSH_LOG_PACKET, "Actual timeout : %d", timeout); ret = ssh_handle_packets_termination(session, timeout, ssh_connect_termination, session); if (session->session_state != SSH_SESSION_STATE_ERROR && (ret == SSH_ERROR || !ssh_connect_termination(session))) { ssh_set_error(session, SSH_FATAL, "Timeout connecting to %s", session->opts.host); session->session_state = SSH_SESSION_STATE_ERROR; } } else { ret = ssh_handle_packets_termination(session, SSH_TIMEOUT_NONBLOCKING, ssh_connect_termination, session); if (ret == SSH_ERROR) { session->session_state = SSH_SESSION_STATE_ERROR; } } SSH_LOG(SSH_LOG_PACKET, "current state : %d", session->session_state); if (!ssh_is_blocking(session) && !ssh_connect_termination(session)) { return SSH_AGAIN; } session->pending_call_state = SSH_PENDING_CALL_NONE; if (session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) { return SSH_ERROR; } return SSH_OK; } /** * @brief Get the issue banner from the server. * * This is the banner showing a disclaimer to users who log in, * typically their right or the fact that they will be monitored. * * @param[in] session The SSH session to use. * * @return A newly allocated string with the banner, NULL on error. */ char *ssh_get_issue_banner(ssh_session session) { if (session == NULL || session->banner == NULL) { return NULL; } return ssh_string_to_char(session->banner); } /** * @brief Get the version of the OpenSSH server, if it is not an OpenSSH server * then 0 will be returned. * * You can use the SSH_VERSION_INT macro to compare version numbers. * * @param[in] session The SSH session to use. * * @return The version number if available, 0 otherwise. * * @code * int openssh = ssh_get_openssh_version(); * * if (openssh == SSH_INT_VERSION(6, 1, 0)) { * printf("Version match!\m"); * } * @endcode */ int ssh_get_openssh_version(ssh_session session) { if (session == NULL) { return 0; } return session->openssh; } /** * @brief Disconnect from a session (client or server). * The session can then be reused to open a new session. * * @param[in] session The SSH session to use. */ void ssh_disconnect(ssh_session session) { struct ssh_iterator *it; int rc; if (session == NULL) { return; } if (session->socket != NULL && ssh_socket_is_open(session->socket)) { rc = ssh_buffer_pack(session->out_buffer, "bdss", SSH2_MSG_DISCONNECT, SSH2_DISCONNECT_BY_APPLICATION, "Bye Bye", ""); /* language tag */ if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } ssh_packet_send(session); ssh_socket_close(session->socket); } error: session->recv_seq = 0; session->send_seq = 0; session->alive = 0; if (session->socket != NULL){ ssh_socket_reset(session->socket); } session->opts.fd = SSH_INVALID_SOCKET; session->session_state=SSH_SESSION_STATE_DISCONNECTED; while ((it=ssh_list_get_iterator(session->channels)) != NULL) { ssh_channel_do_free(ssh_iterator_value(ssh_channel,it)); ssh_list_remove(session->channels, it); } if(session->current_crypto){ crypto_free(session->current_crypto); session->current_crypto=NULL; } if (session->next_crypto) { crypto_free(session->next_crypto); session->next_crypto = crypto_new(); if (session->next_crypto == NULL) { ssh_set_error_oom(session); } } if (session->in_buffer) { ssh_buffer_reinit(session->in_buffer); } if (session->out_buffer) { ssh_buffer_reinit(session->out_buffer); } if (session->in_hashbuf) { ssh_buffer_reinit(session->in_hashbuf); } if (session->out_hashbuf) { ssh_buffer_reinit(session->out_hashbuf); } session->auth.supported_methods = 0; SAFE_FREE(session->serverbanner); SAFE_FREE(session->clientbanner); if(session->ssh_message_list){ ssh_message msg; while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list)) != NULL){ ssh_message_free(msg); } ssh_list_free(session->ssh_message_list); session->ssh_message_list=NULL; } if (session->packet_callbacks){ ssh_list_free(session->packet_callbacks); session->packet_callbacks=NULL; } } const char *ssh_copyright(void) { return SSH_STRINGIFY(LIBSSH_VERSION) " (c) 2003-2019 " "Aris Adamantiadis, Andreas Schneider " "and libssh contributors. " "Distributed under the LGPL, please refer to COPYING " "file for information about your rights"; } /** @} */ ================================================ FILE: src/libssh/src/config.c ================================================ /* * config.c - parse the ssh config file * * This file is part of the SSH Library * * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifdef HAVE_GLOB_H # include #endif #include #include #include "libssh/config_parser.h" #include "libssh/config.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/options.h" #define MAX_LINE_SIZE 1024 struct ssh_config_keyword_table_s { const char *name; enum ssh_config_opcode_e opcode; }; static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = { { "host", SOC_HOST }, { "match", SOC_MATCH }, { "hostname", SOC_HOSTNAME }, { "port", SOC_PORT }, { "user", SOC_USERNAME }, { "identityfile", SOC_IDENTITY }, { "ciphers", SOC_CIPHERS }, { "macs", SOC_MACS }, { "compression", SOC_COMPRESSION }, { "connecttimeout", SOC_TIMEOUT }, { "protocol", SOC_PROTOCOL }, { "stricthostkeychecking", SOC_STRICTHOSTKEYCHECK }, { "userknownhostsfile", SOC_KNOWNHOSTS }, { "proxycommand", SOC_PROXYCOMMAND }, { "gssapiserveridentity", SOC_GSSAPISERVERIDENTITY }, { "gssapiclientidentity", SOC_GSSAPICLIENTIDENTITY }, { "gssapidelegatecredentials", SOC_GSSAPIDELEGATECREDENTIALS }, { "include", SOC_INCLUDE }, { "bindaddress", SOC_BINDADDRESS}, { "globalknownhostsfile", SOC_GLOBALKNOWNHOSTSFILE}, { "loglevel", SOC_LOGLEVEL}, { "hostkeyalgorithms", SOC_HOSTKEYALGORITHMS}, { "kexalgorithms", SOC_KEXALGORITHMS}, { "mac", SOC_UNSUPPORTED}, /* SSHv1 */ { "gssapiauthentication", SOC_GSSAPIAUTHENTICATION}, { "kbdinteractiveauthentication", SOC_KBDINTERACTIVEAUTHENTICATION}, { "passwordauthentication", SOC_PASSWORDAUTHENTICATION}, { "pubkeyauthentication", SOC_PUBKEYAUTHENTICATION}, { "addkeystoagent", SOC_UNSUPPORTED}, { "addressfamily", SOC_UNSUPPORTED}, { "batchmode", SOC_UNSUPPORTED}, { "canonicaldomains", SOC_UNSUPPORTED}, { "canonicalizefallbacklocal", SOC_UNSUPPORTED}, { "canonicalizehostname", SOC_UNSUPPORTED}, { "canonicalizemaxdots", SOC_UNSUPPORTED}, { "canonicalizepermittedcnames", SOC_UNSUPPORTED}, { "certificatefile", SOC_UNSUPPORTED}, { "challengeresponseauthentication", SOC_UNSUPPORTED}, { "checkhostip", SOC_UNSUPPORTED}, { "cipher", SOC_UNSUPPORTED}, /* SSHv1 */ { "compressionlevel", SOC_UNSUPPORTED}, /* SSHv1 */ { "connectionattempts", SOC_UNSUPPORTED}, { "enablesshkeysign", SOC_UNSUPPORTED}, { "fingerprinthash", SOC_UNSUPPORTED}, { "forwardagent", SOC_UNSUPPORTED}, { "gssapikeyexchange", SOC_UNSUPPORTED}, { "gssapirenewalforcesrekey", SOC_UNSUPPORTED}, { "gssapitrustdns", SOC_UNSUPPORTED}, { "hashknownhosts", SOC_UNSUPPORTED}, { "hostbasedauthentication", SOC_UNSUPPORTED}, { "hostbasedkeytypes", SOC_UNSUPPORTED}, { "hostkeyalias", SOC_UNSUPPORTED}, { "identitiesonly", SOC_UNSUPPORTED}, { "identityagent", SOC_UNSUPPORTED}, { "ipqos", SOC_UNSUPPORTED}, { "kbdinteractivedevices", SOC_UNSUPPORTED}, { "nohostauthenticationforlocalhost", SOC_UNSUPPORTED}, { "numberofpasswordprompts", SOC_UNSUPPORTED}, { "pkcs11provider", SOC_UNSUPPORTED}, { "preferredauthentications", SOC_UNSUPPORTED}, { "proxyjump", SOC_PROXYJUMP}, { "proxyusefdpass", SOC_UNSUPPORTED}, { "pubkeyacceptedtypes", SOC_PUBKEYACCEPTEDTYPES}, { "rekeylimit", SOC_REKEYLIMIT}, { "remotecommand", SOC_UNSUPPORTED}, { "revokedhostkeys", SOC_UNSUPPORTED}, { "rhostsrsaauthentication", SOC_UNSUPPORTED}, { "rsaauthentication", SOC_UNSUPPORTED}, /* SSHv1 */ { "serveralivecountmax", SOC_UNSUPPORTED}, { "serveraliveinterval", SOC_UNSUPPORTED}, { "streamlocalbindmask", SOC_UNSUPPORTED}, { "streamlocalbindunlink", SOC_UNSUPPORTED}, { "syslogfacility", SOC_UNSUPPORTED}, { "tcpkeepalive", SOC_UNSUPPORTED}, { "updatehostkeys", SOC_UNSUPPORTED}, { "useprivilegedport", SOC_UNSUPPORTED}, { "verifyhostkeydns", SOC_UNSUPPORTED}, { "visualhostkey", SOC_UNSUPPORTED}, { "clearallforwardings", SOC_NA}, { "controlmaster", SOC_NA}, { "controlpersist", SOC_NA}, { "controlpath", SOC_NA}, { "dynamicforward", SOC_NA}, { "escapechar", SOC_NA}, { "exitonforwardfailure", SOC_NA}, { "forwardx11", SOC_NA}, { "forwardx11timeout", SOC_NA}, { "forwardx11trusted", SOC_NA}, { "gatewayports", SOC_NA}, { "ignoreunknown", SOC_NA}, { "localcommand", SOC_NA}, { "localforward", SOC_NA}, { "permitlocalcommand", SOC_NA}, { "remoteforward", SOC_NA}, { "requesttty", SOC_NA}, { "sendenv", SOC_NA}, { "tunnel", SOC_NA}, { "tunneldevice", SOC_NA}, { "xauthlocation", SOC_NA}, { "pubkeyacceptedkeytypes", SOC_PUBKEYACCEPTEDTYPES}, { NULL, SOC_UNKNOWN } }; enum ssh_config_match_e { MATCH_UNKNOWN = -1, MATCH_ALL, MATCH_FINAL, MATCH_CANONICAL, MATCH_EXEC, MATCH_HOST, MATCH_ORIGINALHOST, MATCH_USER, MATCH_LOCALUSER }; struct ssh_config_match_keyword_table_s { const char *name; enum ssh_config_match_e opcode; }; static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[] = { { "all", MATCH_ALL }, { "canonical", MATCH_CANONICAL }, { "final", MATCH_FINAL }, { "exec", MATCH_EXEC }, { "host", MATCH_HOST }, { "originalhost", MATCH_ORIGINALHOST }, { "user", MATCH_USER }, { "localuser", MATCH_LOCALUSER }, { NULL, MATCH_UNKNOWN }, }; static int ssh_config_parse_line(ssh_session session, const char *line, unsigned int count, int *parsing); static enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword) { int i; for (i = 0; ssh_config_keyword_table[i].name != NULL; i++) { if (strcasecmp(keyword, ssh_config_keyword_table[i].name) == 0) { return ssh_config_keyword_table[i].opcode; } } return SOC_UNKNOWN; } static void local_parse_file(ssh_session session, const char *filename, int *parsing) { FILE *f; char line[MAX_LINE_SIZE] = {0}; unsigned int count = 0; int rv; f = fopen(filename, "r"); if (f == NULL) { SSH_LOG(SSH_LOG_RARE, "Cannot find file %s to load", filename); return; } SSH_LOG(SSH_LOG_PACKET, "Reading additional configuration data from %s", filename); while (fgets(line, sizeof(line), f)) { count++; rv = ssh_config_parse_line(session, line, count, parsing); if (rv < 0) { fclose(f); return; } } fclose(f); return; } #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) static void local_parse_glob(ssh_session session, const char *fileglob, int *parsing) { glob_t globbuf = { .gl_flags = 0, }; int rt; size_t i; rt = glob(fileglob, GLOB_TILDE, NULL, &globbuf); if (rt == GLOB_NOMATCH) { globfree(&globbuf); return; } else if (rt != 0) { SSH_LOG(SSH_LOG_RARE, "Glob error: %s", fileglob); globfree(&globbuf); return; } for (i = 0; i < globbuf.gl_pathc; i++) { local_parse_file(session, globbuf.gl_pathv[i], parsing); } globfree(&globbuf); } #endif /* HAVE_GLOB HAVE_GLOB_GL_FLAGS_MEMBER */ static enum ssh_config_match_e ssh_config_get_match_opcode(const char *keyword) { size_t i; for (i = 0; ssh_config_match_keyword_table[i].name != NULL; i++) { if (strcasecmp(keyword, ssh_config_match_keyword_table[i].name) == 0) { return ssh_config_match_keyword_table[i].opcode; } } return MATCH_UNKNOWN; } static int ssh_config_match(char *value, const char *pattern, bool negate) { int ok, result = 0; ok = match_pattern_list(value, pattern, strlen(pattern), 0); if (ok <= 0 && negate == true) { result = 1; } else if (ok > 0 && negate == false) { result = 1; } SSH_LOG(SSH_LOG_TRACE, "%s '%s' against pattern '%s'%s (ok=%d)", result == 1 ? "Matched" : "Not matched", value, pattern, negate == true ? " (negated)" : "", ok); return result; } /* @brief: Parse the ProxyJump configuration line and if parsing, * stores the result in the configuration option */ static int ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) { char *c = NULL, *cp = NULL, *endp = NULL; char *username = NULL; char *hostname = NULL; char *port = NULL; char *next = NULL; int cmp, rv = SSH_ERROR; bool parse_entry = do_parsing; /* Special value none disables the proxy */ cmp = strcasecmp(s, "none"); if (cmp == 0 && do_parsing) { ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, s); return SSH_OK; } /* This is comma-separated list of [user@]host[:port] entries */ c = strdup(s); if (c == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } cp = c; do { endp = strchr(cp, ','); if (endp != NULL) { /* Split out the token */ *endp = '\0'; } if (parse_entry) { /* We actually care only about the first item */ rv = ssh_config_parse_uri(cp, &username, &hostname, &port); /* The rest of the list needs to be passed on */ if (endp != NULL) { next = strdup(endp + 1); if (next == NULL) { ssh_set_error_oom(session); rv = SSH_ERROR; } } } else { /* The rest is just sanity-checked to avoid failures later */ rv = ssh_config_parse_uri(cp, NULL, NULL, NULL); } if (rv != SSH_OK) { goto out; } parse_entry = 0; if (endp != NULL) { cp = endp + 1; } else { cp = NULL; /* end */ } } while (cp != NULL); if (hostname != NULL && do_parsing) { char com[512] = {0}; rv = snprintf(com, sizeof(com), "ssh%s%s%s%s%s%s -W [%%h]:%%p %s", username ? " -l " : "", username ? username : "", port ? " -p " : "", port ? port : "", next ? " -J " : "", next ? next : "", hostname); if (rv < 0 || rv >= (int)sizeof(com)) { SSH_LOG(SSH_LOG_WARN, "Too long ProxyJump configuration line"); rv = SSH_ERROR; goto out; } ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, com); } rv = SSH_OK; out: SAFE_FREE(username); SAFE_FREE(hostname); SAFE_FREE(port); SAFE_FREE(next); SAFE_FREE(c); return rv; } static int ssh_config_parse_line(ssh_session session, const char *line, unsigned int count, int *parsing) { enum ssh_config_opcode_e opcode; const char *p = NULL, *p2 = NULL; char *s = NULL, *x = NULL; char *keyword = NULL; char *lowerhost = NULL; size_t len; int i, rv; uint8_t *seen = session->opts.options_seen; long l; int64_t ll; /* Ignore empty lines */ if (line == NULL || *line == '\0') { return 0; } x = s = strdup(line); if (s == NULL) { ssh_set_error_oom(session); return -1; } /* Remove trailing spaces */ for (len = strlen(s) - 1; len > 0; len--) { if (! isspace(s[len])) { break; } s[len] = '\0'; } keyword = ssh_config_get_token(&s); if (keyword == NULL || *keyword == '#' || *keyword == '\0' || *keyword == '\n') { SAFE_FREE(x); return 0; } opcode = ssh_config_get_opcode(keyword); if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_MATCH && opcode != SOC_INCLUDE && opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */ /* Skip all the options that were already applied */ if (seen[opcode] != 0) { SAFE_FREE(x); return 0; } seen[opcode] = 1; } switch (opcode) { case SOC_INCLUDE: /* recursive include of other files */ p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) local_parse_glob(session, p, parsing); #else local_parse_file(session, p, parsing); #endif /* HAVE_GLOB */ } break; case SOC_MATCH: { bool negate; int result = 1; size_t args = 0; enum ssh_config_match_e opt; char *localuser = NULL; *parsing = 0; do { p = p2 = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { break; } args++; SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'", count, p); /* If the option is prefixed with ! the result should be negated */ negate = false; if (p[0] == '!') { negate = true; p++; } opt = ssh_config_get_match_opcode(p); switch (opt) { case MATCH_ALL: p = ssh_config_get_str_tok(&s, NULL); if (args <= 2 && (p == NULL || p[0] == '\0')) { /* The first or second, but last argument. The "all" keyword * can be prefixed with either "final" or "canonical" * keywords which do not have any effect here. */ if (negate == true) { result = 0; } break; } ssh_set_error(session, SSH_FATAL, "line %d: ERROR - Match all cannot be combined with " "other Match attributes", count); SAFE_FREE(x); return -1; case MATCH_FINAL: case MATCH_CANONICAL: SSH_LOG(SSH_LOG_WARN, "line %d: Unsupported Match keyword '%s', skipping", count, p); /* Not set any result here -- the result is dependent on the * following matches after this keyword */ break; case MATCH_EXEC: /* Skip to the end of line as unsupported */ p = ssh_config_get_cmd(&s); if (p == NULL || p[0] == '\0') { SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " "'%s' requires argument", count, p2); SAFE_FREE(x); return -1; } args++; SSH_LOG(SSH_LOG_WARN, "line %d: Unsupported Match keyword '%s', ignoring", count, p2); result = 0; break; case MATCH_LOCALUSER: /* Here we match only one argument */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { ssh_set_error(session, SSH_FATAL, "line %d: ERROR - Match user keyword " "requires argument", count); SAFE_FREE(x); return -1; } localuser = ssh_get_local_username(); if (localuser == NULL) { SSH_LOG(SSH_LOG_WARN, "line %d: Can not get local username " "for conditional matching.", count); SAFE_FREE(x); return -1; } result &= ssh_config_match(localuser, p, negate); SAFE_FREE(localuser); args++; break; case MATCH_ORIGINALHOST: /* Skip one argument */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { SSH_LOG(SSH_LOG_WARN, "line %d: Match keyword " "'%s' requires argument", count, p2); SAFE_FREE(x); return -1; } args++; SSH_LOG(SSH_LOG_WARN, "line %d: Unsupported Match keyword '%s', ignoring", count, p2); result = 0; break; case MATCH_HOST: /* Here we match only one argument */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { ssh_set_error(session, SSH_FATAL, "line %d: ERROR - Match host keyword " "requires argument", count); SAFE_FREE(x); return -1; } result &= ssh_config_match(session->opts.host, p, negate); args++; break; case MATCH_USER: /* Here we match only one argument */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL || p[0] == '\0') { ssh_set_error(session, SSH_FATAL, "line %d: ERROR - Match user keyword " "requires argument", count); SAFE_FREE(x); return -1; } result &= ssh_config_match(session->opts.username, p, negate); args++; break; case MATCH_UNKNOWN: default: ssh_set_error(session, SSH_FATAL, "ERROR - Unknown argument '%s' for Match keyword", p); SAFE_FREE(x); return -1; } } while (p != NULL && p[0] != '\0'); if (args == 0) { ssh_set_error(session, SSH_FATAL, "ERROR - Match keyword requires an argument"); SAFE_FREE(x); return -1; } *parsing = result; break; } case SOC_HOST: { int ok = 0, result = -1; *parsing = 0; lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL; for (p = ssh_config_get_str_tok(&s, NULL); p != NULL && p[0] != '\0'; p = ssh_config_get_str_tok(&s, NULL)) { if (ok >= 0) { ok = match_hostname(lowerhost, p, strlen(p)); if (result == -1 && ok < 0) { result = 0; } else if (result == -1 && ok > 0) { result = 1; } } } SAFE_FREE(lowerhost); if (result != -1) { *parsing = result; } break; } case SOC_HOSTNAME: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { char *z = ssh_path_expand_escape(session, p); if (z == NULL) { z = strdup(p); } ssh_options_set(session, SSH_OPTIONS_HOST, z); free(z); } break; case SOC_PORT: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_PORT_STR, p); } break; case SOC_USERNAME: if (session->opts.username == NULL) { p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_USER, p); } } break; case SOC_IDENTITY: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, p); } break; case SOC_CIPHERS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, p); ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p); } break; case SOC_MACS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, p); ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, p); } break; case SOC_COMPRESSION: i = ssh_config_get_yesno(&s, -1); if (i >= 0 && *parsing) { if (i) { ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes"); } else { ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "no"); } } break; case SOC_PROTOCOL: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { char *a, *b; b = strdup(p); if (b == NULL) { SAFE_FREE(x); ssh_set_error_oom(session); return -1; } i = 0; ssh_options_set(session, SSH_OPTIONS_SSH2, &i); for (a = strtok(b, ","); a; a = strtok(NULL, ",")) { switch (atoi(a)) { case 1: break; case 2: i = 1; ssh_options_set(session, SSH_OPTIONS_SSH2, &i); break; default: break; } } SAFE_FREE(b); } break; case SOC_TIMEOUT: l = ssh_config_get_long(&s, -1); if (l >= 0 && *parsing) { ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &l); } break; case SOC_STRICTHOSTKEYCHECK: i = ssh_config_get_yesno(&s, -1); if (i >= 0 && *parsing) { ssh_options_set(session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &i); } break; case SOC_KNOWNHOSTS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, p); } break; case SOC_PROXYCOMMAND: p = ssh_config_get_cmd(&s); /* We share the seen value with the ProxyJump */ if (p && *parsing && !seen[SOC_PROXYJUMP]) { ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p); } break; case SOC_PROXYJUMP: p = ssh_config_get_str_tok(&s, NULL); if (p == NULL) { SAFE_FREE(x); return -1; } /* We share the seen value with the ProxyCommand */ rv = ssh_config_parse_proxy_jump(session, p, (*parsing && !seen[SOC_PROXYCOMMAND])); if (rv != SSH_OK) { SAFE_FREE(x); return -1; } break; case SOC_GSSAPISERVERIDENTITY: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_GSSAPI_SERVER_IDENTITY, p); } break; case SOC_GSSAPICLIENTIDENTITY: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY, p); } break; case SOC_GSSAPIDELEGATECREDENTIALS: i = ssh_config_get_yesno(&s, -1); if (i >=0 && *parsing) { ssh_options_set(session, SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS, &i); } break; case SOC_BINDADDRESS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_BINDADDR, p); } break; case SOC_GLOBALKNOWNHOSTSFILE: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, p); } break; case SOC_LOGLEVEL: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { int value = -1; if (strcasecmp(p, "quiet") == 0) { value = SSH_LOG_NONE; } else if (strcasecmp(p, "fatal") == 0 || strcasecmp(p, "error")== 0 || strcasecmp(p, "info") == 0) { value = SSH_LOG_WARN; } else if (strcasecmp(p, "verbose") == 0) { value = SSH_LOG_INFO; } else if (strcasecmp(p, "DEBUG") == 0 || strcasecmp(p, "DEBUG1") == 0) { value = SSH_LOG_DEBUG; } else if (strcasecmp(p, "DEBUG2") == 0 || strcasecmp(p, "DEBUG3") == 0) { value = SSH_LOG_TRACE; } if (value != -1) { ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &value); } } break; case SOC_HOSTKEYALGORITHMS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p); } break; case SOC_PUBKEYACCEPTEDTYPES: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, p); } break; case SOC_KEXALGORITHMS: p = ssh_config_get_str_tok(&s, NULL); if (p && *parsing) { ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, p); } break; case SOC_REKEYLIMIT: /* Parse the data limit */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL) { break; } else if (strcmp(p, "default") == 0) { /* Default rekey limits enforced automaticaly */ ll = 0; } else { char *endp = NULL; ll = strtoll(p, &endp, 10); if (p == endp || ll < 0) { /* No number or negative */ SSH_LOG(SSH_LOG_WARN, "Invalid argument to rekey limit"); break; } switch (*endp) { case 'G': if (ll > LLONG_MAX / 1024) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 1024; FALL_THROUGH; case 'M': if (ll > LLONG_MAX / 1024) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 1024; FALL_THROUGH; case 'K': if (ll > LLONG_MAX / 1024) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 1024; endp++; FALL_THROUGH; case '\0': /* just the number */ break; default: /* Invalid suffix */ ll = -1; break; } if (*endp != ' ' && *endp != '\0') { SSH_LOG(SSH_LOG_WARN, "Invalid trailing characters after the rekey limit: %s", endp); break; } } if (ll > -1 && *parsing) { uint64_t v = (uint64_t)ll; ssh_options_set(session, SSH_OPTIONS_REKEY_DATA, &v); } /* Parse the time limit */ p = ssh_config_get_str_tok(&s, NULL); if (p == NULL) { break; } else if (strcmp(p, "none") == 0) { ll = 0; } else { char *endp = NULL; ll = strtoll(p, &endp, 10); if (p == endp || ll < 0) { /* No number or negative */ SSH_LOG(SSH_LOG_WARN, "Invalid argument to rekey limit"); break; } switch (*endp) { case 'w': case 'W': if (ll > LLONG_MAX / 7) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 7; FALL_THROUGH; case 'd': case 'D': if (ll > LLONG_MAX / 24) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 24; FALL_THROUGH; case 'h': case 'H': if (ll > LLONG_MAX / 60) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 60; FALL_THROUGH; case 'm': case 'M': if (ll > LLONG_MAX / 60) { SSH_LOG(SSH_LOG_WARN, "Possible overflow of rekey limit"); ll = -1; break; } ll = ll * 60; FALL_THROUGH; case 's': case 'S': endp++; FALL_THROUGH; case '\0': /* just the number */ break; default: /* Invalid suffix */ ll = -1; break; } if (*endp != '\0') { SSH_LOG(SSH_LOG_WARN, "Invalid trailing characters after the" " rekey limit: %s", endp); break; } } if (ll > -1 && *parsing) { uint32_t v = (uint32_t)ll; ssh_options_set(session, SSH_OPTIONS_REKEY_TIME, &v); } break; case SOC_GSSAPIAUTHENTICATION: case SOC_KBDINTERACTIVEAUTHENTICATION: case SOC_PASSWORDAUTHENTICATION: case SOC_PUBKEYAUTHENTICATION: i = ssh_config_get_yesno(&s, 0); if (i>=0 && *parsing) { switch(opcode){ case SOC_GSSAPIAUTHENTICATION: ssh_options_set(session, SSH_OPTIONS_GSSAPI_AUTH, &i); break; case SOC_KBDINTERACTIVEAUTHENTICATION: ssh_options_set(session, SSH_OPTIONS_KBDINT_AUTH, &i); break; case SOC_PASSWORDAUTHENTICATION: ssh_options_set(session, SSH_OPTIONS_PASSWORD_AUTH, &i); break; case SOC_PUBKEYAUTHENTICATION: ssh_options_set(session, SSH_OPTIONS_PUBKEY_AUTH, &i); break; /* make gcc happy */ default: break; } } break; case SOC_NA: SSH_LOG(SSH_LOG_INFO, "Unapplicable option: %s, line: %d", keyword, count); break; case SOC_UNSUPPORTED: SSH_LOG(SSH_LOG_RARE, "Unsupported option: %s, line: %d", keyword, count); break; case SOC_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown option: %s, line: %d", keyword, count); break; default: ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d", opcode); SAFE_FREE(x); return -1; break; } SAFE_FREE(x); return 0; } /* @brief Parse configuration file and set the options to the given session * * @params[in] session The ssh session * @params[in] filename The path to the ssh configuration file * * @returns 0 on successful parsing the configuration file, -1 on error */ int ssh_config_parse_file(ssh_session session, const char *filename) { char line[MAX_LINE_SIZE] = {0}; unsigned int count = 0; FILE *f; int parsing, rv; f = fopen(filename, "r"); if (f == NULL) { return 0; } SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename); parsing = 1; while (fgets(line, sizeof(line), f)) { count++; rv = ssh_config_parse_line(session, line, count, &parsing); if (rv < 0) { fclose(f); return -1; } } fclose(f); return 0; } ================================================ FILE: src/libssh/src/config_parser.c ================================================ /* * config_parser.c - Common configuration file parser functions * * This file is part of the SSH Library * * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include "libssh/config_parser.h" #include "libssh/priv.h" char *ssh_config_get_cmd(char **str) { register char *c; char *r; /* Ignore leading spaces */ for (c = *str; *c; c++) { if (! isblank(*c)) { break; } } if (*c == '\"') { for (r = ++c; *c; c++) { if (*c == '\"') { *c = '\0'; goto out; } } } for (r = c; *c; c++) { if (*c == '\n') { *c = '\0'; goto out; } } out: *str = c + 1; return r; } char *ssh_config_get_token(char **str) { register char *c; char *r; c = ssh_config_get_cmd(str); for (r = c; *c; c++) { if (isblank(*c) || *c == '=') { *c = '\0'; goto out; } } out: *str = c + 1; return r; } long ssh_config_get_long(char **str, long notfound) { char *p, *endp; long i; p = ssh_config_get_token(str); if (p && *p) { i = strtol(p, &endp, 10); if (p == endp) { return notfound; } return i; } return notfound; } const char *ssh_config_get_str_tok(char **str, const char *def) { char *p; p = ssh_config_get_token(str); if (p && *p) { return p; } return def; } int ssh_config_get_yesno(char **str, int notfound) { const char *p; p = ssh_config_get_str_tok(str, NULL); if (p == NULL) { return notfound; } if (strncasecmp(p, "yes", 3) == 0) { return 1; } else if (strncasecmp(p, "no", 2) == 0) { return 0; } return notfound; } int ssh_config_parse_uri(const char *tok, char **username, char **hostname, char **port) { char *endp = NULL; long port_n; /* Sanitize inputs */ if (username != NULL) { *username = NULL; } if (hostname != NULL) { *hostname = NULL; } if (port != NULL) { *port = NULL; } /* Username part (optional) */ endp = strchr(tok, '@'); if (endp != NULL) { /* Zero-length username is not valid */ if (tok == endp) { goto error; } if (username != NULL) { *username = strndup(tok, endp - tok); if (*username == NULL) { goto error; } } tok = endp + 1; /* If there is second @ character, this does not look like our URI */ endp = strchr(tok, '@'); if (endp != NULL) { goto error; } } /* Hostname */ if (*tok == '[') { /* IPv6 address is enclosed with square brackets */ tok++; endp = strchr(tok, ']'); if (endp == NULL) { goto error; } } else { /* Hostnames or aliases expand to the last colon or to the end */ endp = strrchr(tok, ':'); if (endp == NULL) { endp = strchr(tok, '\0'); } } if (tok == endp) { /* Zero-length hostnames are not valid */ goto error; } if (hostname != NULL) { *hostname = strndup(tok, endp - tok); if (*hostname == NULL) { goto error; } } /* Skip also the closing bracket */ if (*endp == ']') { endp++; } /* Port (optional) */ if (*endp != '\0') { char *port_end = NULL; /* Verify the port is valid positive number */ port_n = strtol(endp + 1, &port_end, 10); if (port_n < 1 || *port_end != '\0') { SSH_LOG(SSH_LOG_WARN, "Failed to parse port number." " The value '%ld' is invalid or there are some" " trailing characters: '%s'", port_n, port_end); goto error; } if (port != NULL) { *port = strdup(endp + 1); if (*port == NULL) { goto error; } } } return SSH_OK; error: if (username != NULL) { SAFE_FREE(*username); } if (hostname != NULL) { SAFE_FREE(*hostname); } if (port != NULL) { SAFE_FREE(*port); } return SSH_ERROR; } ================================================ FILE: src/libssh/src/connect.c ================================================ /* * connect.c - handles connections to ssh servers * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include #include "libssh/libssh.h" #include "libssh/misc.h" #ifdef _WIN32 /* * Only use Windows API functions available on Windows 2000 SP4 or later. * The available constants are in . * http://msdn.microsoft.com/en-us/library/aa383745.aspx * http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx */ #undef _WIN32_WINNT #ifdef HAVE_WSPIAPI_H #define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */ #undef NTDDI_VERSION #define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */ #else #define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */ #undef NTDDI_VERSION #define NTDDI_VERSION 0x05010000 /* NTDDI_WINXP */ #endif #if _MSC_VER >= 1400 #include #undef close #define close _close #endif /* _MSC_VER */ #include #include /* is necessary for getaddrinfo before Windows XP, but it isn't * available on some platforms like MinGW. */ #ifdef HAVE_WSPIAPI_H #include #endif #ifndef EINPROGRESS #define EINPROGRESS WSAEINPROGRESS #endif #else /* _WIN32 */ #include #include #include #include #include #endif /* _WIN32 */ #include "libssh/priv.h" #include "libssh/socket.h" #include "libssh/channels.h" #include "libssh/session.h" #include "libssh/poll.h" #ifndef HAVE_GETADDRINFO #error "Your system must have getaddrinfo()" #endif #ifdef _WIN32 #ifndef gai_strerror char WSAAPI *gai_strerrorA(int code) { static char buf[256]; snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code); return buf; } #endif /* gai_strerror */ #endif /* _WIN32 */ static int ssh_connect_socket_close(socket_t s) { #ifdef _WIN32 return closesocket(s); #else return close(s); #endif } static int getai(const char *host, int port, struct addrinfo **ai) { const char *service = NULL; struct addrinfo hints; char s_port[10]; ZERO_STRUCT(hints); hints.ai_protocol = IPPROTO_TCP; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (port == 0) { hints.ai_flags = AI_PASSIVE; } else { snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port); service = s_port; #ifdef AI_NUMERICSERV hints.ai_flags = AI_NUMERICSERV; #endif } if (ssh_is_ipaddr(host)) { /* this is an IP address */ SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host); hints.ai_flags |= AI_NUMERICHOST; } return getaddrinfo(host, service, &hints, ai); } static int set_tcp_nodelay(socket_t socket) { int opt = 1; return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)); } /** * @internal * * @brief Launches a nonblocking connect to an IPv4 or IPv6 host * specified by its IP address or hostname. * * @returns A file descriptor, < 0 on error. * @warning very ugly !!! */ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host, const char *bind_addr, int port) { socket_t s = -1; int rc; struct addrinfo *ai = NULL; struct addrinfo *itr = NULL; rc = getai(host, port, &ai); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Failed to resolve hostname %s (%s)", host, gai_strerror(rc)); return -1; } for (itr = ai; itr != NULL; itr = itr->ai_next) { /* create socket */ s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol); if (s < 0) { ssh_set_error(session, SSH_FATAL, "Socket create failed: %s", strerror(errno)); continue; } if (bind_addr) { struct addrinfo *bind_ai; struct addrinfo *bind_itr; SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr); rc = getai(bind_addr, 0, &bind_ai); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Failed to resolve bind address %s (%s)", bind_addr, gai_strerror(rc)); ssh_connect_socket_close(s); s = -1; break; } for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) { if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) { ssh_set_error(session, SSH_FATAL, "Binding local address: %s", strerror(errno)); continue; } else { break; } } freeaddrinfo(bind_ai); /* Cannot bind to any local addresses */ if (bind_itr == NULL) { ssh_connect_socket_close(s); s = -1; continue; } } rc = ssh_socket_set_nonblocking(s); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Failed to set socket non-blocking for %s:%d", host, port); ssh_connect_socket_close(s); s = -1; continue; } if (session->opts.nodelay) { /* For winsock, socket options are only effective before connect */ rc = set_tcp_nodelay(s); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Failed to set TCP_NODELAY on socket: %s", strerror(errno)); ssh_connect_socket_close(s); s = -1; continue; } } errno = 0; rc = connect(s, itr->ai_addr, itr->ai_addrlen); if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) { ssh_set_error(session, SSH_FATAL, "Failed to connect: %s", strerror(errno)); ssh_connect_socket_close(s); s = -1; continue; } break; } freeaddrinfo(ai); return s; } /** * @addtogroup libssh_session * * @{ */ static int ssh_select_cb (socket_t fd, int revents, void *userdata) { fd_set *set = (fd_set *)userdata; if (revents & POLLIN) { FD_SET(fd, set); } return 0; } /** * @brief A wrapper for the select syscall * * This functions acts more or less like the select(2) syscall.\n * There is no support for writing or exceptions.\n * * @param[in] channels Arrays of channels pointers terminated by a NULL. * It is never rewritten. * * @param[out] outchannels Arrays of same size that "channels", there is no need * to initialize it. * * @param[in] maxfd Maximum +1 file descriptor from readfds. * * @param[in] readfds A fd_set of file descriptors to be select'ed for * reading. * * @param[in] timeout The timeout in milliseconds. * * @return SSH_OK on success, * SSH_ERROR on error, * SSH_EINTR if it was interrupted. In that case, * just restart it. * * @warning libssh is not reentrant here. That means that if a signal is caught * during the processing of this function, you cannot call libssh * functions on sessions that are busy with ssh_select(). * * @see select(2) */ int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd, fd_set *readfds, struct timeval *timeout) { fd_set origfds; socket_t fd; size_t i, j; int rc; int base_tm, tm; struct ssh_timestamp ts; ssh_event event = ssh_event_new(); int firstround = 1; base_tm = tm = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); for (i = 0 ; channels[i] != NULL; ++i) { ssh_event_add_session(event, channels[i]->session); } ZERO_STRUCT(origfds); FD_ZERO(&origfds); for (fd = 0; fd < maxfd ; fd++) { if (FD_ISSET(fd, readfds)) { ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds); FD_SET(fd, &origfds); } } outchannels[0] = NULL; FD_ZERO(readfds); ssh_timestamp_init(&ts); do { /* Poll every channel */ j = 0; for (i = 0; channels[i]; i++) { rc = ssh_channel_poll(channels[i], 0); if (rc != 0) { outchannels[j] = channels[i]; j++; } else { rc = ssh_channel_poll(channels[i], 1); if (rc != 0) { outchannels[j] = channels[i]; j++; } } } outchannels[j] = NULL; if (j != 0) { break; } /* watch if a user socket was triggered */ for (fd = 0; fd < maxfd; fd++) { if (FD_ISSET(fd, readfds)) { goto out; } } /* If the timeout is elapsed, we should go out */ if (!firstround && ssh_timeout_elapsed(&ts, base_tm)) { goto out; } /* since there's nothing, let's fire the polling */ rc = ssh_event_dopoll(event,tm); if (rc == SSH_ERROR) { goto out; } tm = ssh_timeout_update(&ts, base_tm); firstround = 0; } while (1); out: for (fd = 0; fd < maxfd; fd++) { if (FD_ISSET(fd, &origfds)) { ssh_event_remove_fd(event, fd); } } ssh_event_free(event); return SSH_OK; } /** @} */ ================================================ FILE: src/libssh/src/connector.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2015 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/priv.h" #include "libssh/poll.h" #include "libssh/callbacks.h" #include "libssh/session.h" #include #include #include #include #define CHUNKSIZE 4096 #ifdef _WIN32 # ifdef HAVE_IO_H # include # undef open # define open _open # undef close # define close _close # undef read # define read _read # undef unlink # define unlink _unlink # endif /* HAVE_IO_H */ #else # include # include #endif struct ssh_connector_struct { ssh_session session; ssh_channel in_channel; ssh_channel out_channel; socket_t in_fd; socket_t out_fd; bool fd_is_socket; ssh_poll_handle in_poll; ssh_poll_handle out_poll; ssh_event event; int in_available; int out_wontblock; struct ssh_channel_callbacks_struct in_channel_cb; struct ssh_channel_callbacks_struct out_channel_cb; enum ssh_connector_flags_e in_flags; enum ssh_connector_flags_e out_flags; }; static int ssh_connector_channel_data_cb(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata); static int ssh_connector_channel_write_wontblock_cb(ssh_session session, ssh_channel channel, size_t bytes, void *userdata); static ssize_t ssh_connector_fd_read(ssh_connector connector, void *buffer, uint32_t len); static ssize_t ssh_connector_fd_write(ssh_connector connector, const void *buffer, uint32_t len); static bool ssh_connector_fd_is_socket(socket_t socket); ssh_connector ssh_connector_new(ssh_session session) { ssh_connector connector; connector = calloc(1, sizeof(struct ssh_connector_struct)); if (connector == NULL){ ssh_set_error_oom(session); return NULL; } connector->session = session; connector->in_fd = SSH_INVALID_SOCKET; connector->out_fd = SSH_INVALID_SOCKET; connector->fd_is_socket = false; ssh_callbacks_init(&connector->in_channel_cb); ssh_callbacks_init(&connector->out_channel_cb); connector->in_channel_cb.userdata = connector; connector->in_channel_cb.channel_data_function = ssh_connector_channel_data_cb; connector->out_channel_cb.userdata = connector; connector->out_channel_cb.channel_write_wontblock_function = ssh_connector_channel_write_wontblock_cb; return connector; } void ssh_connector_free (ssh_connector connector) { if (connector->in_channel != NULL) { ssh_remove_channel_callbacks(connector->in_channel, &connector->in_channel_cb); } if (connector->out_channel != NULL) { ssh_remove_channel_callbacks(connector->out_channel, &connector->out_channel_cb); } if (connector->event != NULL){ ssh_connector_remove_event(connector); } if (connector->in_poll != NULL) { ssh_poll_free(connector->in_poll); connector->in_poll = NULL; } if (connector->out_poll != NULL) { ssh_poll_free(connector->out_poll); connector->out_poll = NULL; } free(connector); } int ssh_connector_set_in_channel(ssh_connector connector, ssh_channel channel, enum ssh_connector_flags_e flags) { connector->in_channel = channel; connector->in_fd = SSH_INVALID_SOCKET; connector->in_flags = flags; /* Fallback to default value for invalid flags */ if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) { connector->in_flags = SSH_CONNECTOR_STDOUT; } return ssh_add_channel_callbacks(channel, &connector->in_channel_cb); } int ssh_connector_set_out_channel(ssh_connector connector, ssh_channel channel, enum ssh_connector_flags_e flags) { connector->out_channel = channel; connector->out_fd = SSH_INVALID_SOCKET; connector->out_flags = flags; /* Fallback to default value for invalid flags */ if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) { connector->in_flags = SSH_CONNECTOR_STDOUT; } return ssh_add_channel_callbacks(channel, &connector->out_channel_cb); } void ssh_connector_set_in_fd(ssh_connector connector, socket_t fd) { connector->in_fd = fd; connector->fd_is_socket = ssh_connector_fd_is_socket(fd); connector->in_channel = NULL; } void ssh_connector_set_out_fd(ssh_connector connector, socket_t fd) { connector->out_fd = fd; connector->fd_is_socket = ssh_connector_fd_is_socket(fd); connector->out_channel = NULL; } /* TODO */ static void ssh_connector_except(ssh_connector connector, socket_t fd) { (void) connector; (void) fd; } /* TODO */ static void ssh_connector_except_channel(ssh_connector connector, ssh_channel channel) { (void) connector; (void) channel; } /** * @internal * * @brief Reset the poll events to be followed for each file descriptors. */ static void ssh_connector_reset_pollevents(ssh_connector connector) { if (connector->in_fd != SSH_INVALID_SOCKET) { if (connector->in_available) { ssh_poll_remove_events(connector->in_poll, POLLIN); } else { ssh_poll_add_events(connector->in_poll, POLLIN); } } if (connector->out_fd != SSH_INVALID_SOCKET) { if (connector->out_wontblock) { ssh_poll_remove_events(connector->out_poll, POLLOUT); } else { ssh_poll_add_events(connector->out_poll, POLLOUT); } } } /** * @internal * * @brief Callback called when a poll event is received on an input fd. */ static void ssh_connector_fd_in_cb(ssh_connector connector) { unsigned char buffer[CHUNKSIZE]; uint32_t toread = CHUNKSIZE; ssize_t r; ssize_t w; int total = 0; int rc; SSH_LOG(SSH_LOG_TRACE, "connector POLLIN event for fd %d", connector->in_fd); if (connector->out_wontblock) { if (connector->out_channel != NULL) { size_t size = ssh_channel_window_size(connector->out_channel); /* Don't attempt reading more than the window */ toread = MIN(size, CHUNKSIZE); } r = ssh_connector_fd_read(connector, buffer, toread); if (r < 0) { ssh_connector_except(connector, connector->in_fd); return; } if (connector->out_channel != NULL) { if (r == 0) { SSH_LOG(SSH_LOG_TRACE, "input fd %d is EOF", connector->in_fd); if (connector->out_channel->local_eof == 0) { rc = ssh_channel_send_eof(connector->out_channel); (void)rc; /* TODO Handle rc? */ } connector->in_available = 1; /* Don't poll on it */ return; } else if (r> 0) { /* loop around ssh_channel_write in case our window reduced due to a race */ while (total != r){ if (connector->out_flags & SSH_CONNECTOR_STDOUT) { w = ssh_channel_write(connector->out_channel, buffer + total, r - total); } else { w = ssh_channel_write_stderr(connector->out_channel, buffer + total, r - total); } if (w == SSH_ERROR) { return; } total += w; } } } else if (connector->out_fd != SSH_INVALID_SOCKET) { if (r == 0){ close(connector->out_fd); connector->out_fd = SSH_INVALID_SOCKET; } else { /* * Loop around write in case the write blocks even for CHUNKSIZE * bytes */ while (total != r) { w = ssh_connector_fd_write(connector, buffer + total, r - total); if (w < 0){ ssh_connector_except(connector, connector->out_fd); return; } total += w; } } } else { ssh_set_error(connector->session, SSH_FATAL, "output socket or channel closed"); return; } connector->out_wontblock = 0; connector->in_available = 0; } else { connector->in_available = 1; } } /** @internal * @brief Callback called when a poll event is received on an output fd */ static void ssh_connector_fd_out_cb(ssh_connector connector){ unsigned char buffer[CHUNKSIZE]; int r; int w; int total = 0; SSH_LOG(SSH_LOG_TRACE, "connector POLLOUT event for fd %d", connector->out_fd); if(connector->in_available){ if (connector->in_channel != NULL){ r = ssh_channel_read_nonblocking(connector->in_channel, buffer, CHUNKSIZE, 0); if(r == SSH_ERROR){ ssh_connector_except_channel(connector, connector->in_channel); return; } else if(r == 0 && ssh_channel_is_eof(connector->in_channel)){ close(connector->out_fd); connector->out_fd = SSH_INVALID_SOCKET; return; } else if(r>0) { /* loop around write in case the write blocks even for CHUNKSIZE bytes */ while (total != r){ w = ssh_connector_fd_write(connector, buffer + total, r - total); if (w < 0){ ssh_connector_except(connector, connector->out_fd); return; } total += w; } } } else if (connector->in_fd != SSH_INVALID_SOCKET){ /* fallback on the socket input callback */ connector->out_wontblock = 1; ssh_connector_fd_in_cb(connector); } else { ssh_set_error(connector->session, SSH_FATAL, "Output socket or channel closed"); return; } connector->in_available = 0; connector->out_wontblock = 0; } else { connector->out_wontblock = 1; } } /** * @internal * * @brief Callback called when a poll event is received on a file descriptor. * * This is for (input or output. * * @param[in] fd file descriptor receiving the event * * @param[in] revents received Poll(2) events * * @param[in] userdata connector * * @returns 0 */ static int ssh_connector_fd_cb(ssh_poll_handle p, socket_t fd, int revents, void *userdata) { ssh_connector connector = userdata; (void)p; if (revents & POLLERR) { ssh_connector_except(connector, fd); } else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) { ssh_connector_fd_in_cb(connector); } else if(((revents & POLLOUT) || (revents & POLLHUP)) && fd == connector->out_fd) { ssh_connector_fd_out_cb(connector); } ssh_connector_reset_pollevents(connector); return 0; } /** * @internal * * @brief Callback called when data is received on channel. * * @param[in] data Pointer to the data * * @param[in] len Length of data * * @param[in] is_stderr Set to 1 if the data are out of band * * @param[in] userdata The ssh connector * * @returns Amount of data bytes consumed */ static int ssh_connector_channel_data_cb(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata) { ssh_connector connector = userdata; int w; size_t window; (void) session; (void) channel; (void) is_stderr; SSH_LOG(SSH_LOG_TRACE,"connector data on channel"); if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) { /* ignore stderr */ return 0; } else if (!is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDOUT)) { /* ignore stdout */ return 0; } if (connector->out_wontblock) { if (connector->out_channel != NULL) { int window_len; window = ssh_channel_window_size(connector->out_channel); window_len = MIN(window, len); /* Route the data to the right exception channel */ if (is_stderr && (connector->out_flags & SSH_CONNECTOR_STDERR)) { w = ssh_channel_write_stderr(connector->out_channel, data, window_len); } else if (!is_stderr && (connector->out_flags & SSH_CONNECTOR_STDOUT)) { w = ssh_channel_write(connector->out_channel, data, window_len); } else if (connector->out_flags & SSH_CONNECTOR_STDOUT) { w = ssh_channel_write(connector->out_channel, data, window_len); } else { w = ssh_channel_write_stderr(connector->out_channel, data, window_len); } if (w == SSH_ERROR) { ssh_connector_except_channel(connector, connector->out_channel); } } else if (connector->out_fd != SSH_INVALID_SOCKET) { w = ssh_connector_fd_write(connector, data, len); if (w < 0) ssh_connector_except(connector, connector->out_fd); } else { ssh_set_error(session, SSH_FATAL, "output socket or channel closed"); return SSH_ERROR; } connector->out_wontblock = 0; connector->in_available = 0; if ((unsigned int)w < len) { connector->in_available = 1; } ssh_connector_reset_pollevents(connector); return w; } else { connector->in_available = 1; return 0; } } /** * @internal * * @brief Callback called when the channel is free to write. * * @param[in] bytes Amount of bytes that can be written without blocking * * @param[in] userdata The ssh connector * * @returns Amount of data bytes consumed */ static int ssh_connector_channel_write_wontblock_cb(ssh_session session, ssh_channel channel, size_t bytes, void *userdata) { ssh_connector connector = userdata; uint8_t buffer[CHUNKSIZE]; int r, w; (void) channel; SSH_LOG(SSH_LOG_TRACE, "Channel write won't block"); if (connector->in_available) { if (connector->in_channel != NULL) { size_t len = MIN(CHUNKSIZE, bytes); r = ssh_channel_read_nonblocking(connector->in_channel, buffer, len, 0); if (r == SSH_ERROR) { ssh_connector_except_channel(connector, connector->in_channel); } else if(r == 0 && ssh_channel_is_eof(connector->in_channel)){ ssh_channel_send_eof(connector->out_channel); } else if (r > 0) { w = ssh_channel_write(connector->out_channel, buffer, r); if (w == SSH_ERROR) { ssh_connector_except_channel(connector, connector->out_channel); } } } else if (connector->in_fd != SSH_INVALID_SOCKET) { /* fallback on on the socket input callback */ connector->out_wontblock = 1; ssh_connector_fd_in_cb(connector); ssh_connector_reset_pollevents(connector); } else { ssh_set_error(session, SSH_FATAL, "Output socket or channel closed"); return 0; } connector->in_available = 0; connector->out_wontblock = 0; } else { connector->out_wontblock = 1; } return 0; } int ssh_connector_set_event(ssh_connector connector, ssh_event event) { int rc = SSH_OK; if ((connector->in_fd == SSH_INVALID_SOCKET && connector->in_channel == NULL) || (connector->out_fd == SSH_INVALID_SOCKET && connector->out_channel == NULL)) { rc = SSH_ERROR; ssh_set_error(connector->session,SSH_FATAL,"Connector not complete"); goto error; } connector->event = event; if (connector->in_fd != SSH_INVALID_SOCKET) { if (connector->in_poll == NULL) { connector->in_poll = ssh_poll_new(connector->in_fd, POLLIN|POLLERR, ssh_connector_fd_cb, connector); } rc = ssh_event_add_poll(event, connector->in_poll); if (rc != SSH_OK) { goto error; } } if (connector->out_fd != SSH_INVALID_SOCKET) { if (connector->out_poll == NULL) { connector->out_poll = ssh_poll_new(connector->out_fd, POLLOUT|POLLERR, ssh_connector_fd_cb, connector); } rc = ssh_event_add_poll(event, connector->out_poll); if (rc != SSH_OK) { goto error; } } if (connector->in_channel != NULL) { rc = ssh_event_add_session(event, ssh_channel_get_session(connector->in_channel)); if (rc != SSH_OK) goto error; if (ssh_channel_poll_timeout(connector->in_channel, 0, 0) > 0){ connector->in_available = 1; } } if(connector->out_channel != NULL) { ssh_session session = ssh_channel_get_session(connector->out_channel); rc = ssh_event_add_session(event, session); if (rc != SSH_OK) { goto error; } if (ssh_channel_window_size(connector->out_channel) > 0) { connector->out_wontblock = 1; } } error: return rc; } int ssh_connector_remove_event(ssh_connector connector) { ssh_session session; if (connector->in_poll != NULL) { ssh_event_remove_poll(connector->event, connector->in_poll); ssh_poll_free(connector->in_poll); connector->in_poll = NULL; } if (connector->out_poll != NULL) { ssh_event_remove_poll(connector->event, connector->out_poll); ssh_poll_free(connector->out_poll); connector->out_poll = NULL; } if (connector->in_channel != NULL) { session = ssh_channel_get_session(connector->in_channel); ssh_event_remove_session(connector->event, session); } if (connector->out_channel != NULL) { session = ssh_channel_get_session(connector->out_channel); ssh_event_remove_session(connector->event, session); } connector->event = NULL; return SSH_OK; } /** * @internal * * @brief Check the file descriptor to check if it is a Windows socket handle. * */ static bool ssh_connector_fd_is_socket(socket_t s) { #ifdef _WIN32 struct sockaddr_storage ss; int len = sizeof(struct sockaddr_storage); int rc; rc = getsockname(s, (struct sockaddr *)&ss, &len); if (rc == 0) { return true; } SSH_LOG(SSH_LOG_TRACE, "Error %i in getsockname() for fd %d", WSAGetLastError(), s); return false; #else struct stat sb; int rc; rc = fstat(s, &sb); if (rc != 0) { SSH_LOG(SSH_LOG_TRACE, "error %i in fstat() for fd %d", errno, s); return false; } /* The descriptor is a socket */ if (S_ISSOCK(sb.st_mode)) { return true; } return false; #endif /* _WIN32 */ } /** * @internal * * @brief read len bytes from socket into buffer * */ static ssize_t ssh_connector_fd_read(ssh_connector connector, void *buffer, uint32_t len) { ssize_t nread = -1; if (connector->fd_is_socket) { nread = recv(connector->in_fd,buffer, len, 0); } else { nread = read(connector->in_fd,buffer, len); } return nread; } /** * @internal * * @brief brief writes len bytes from buffer to socket * */ static ssize_t ssh_connector_fd_write(ssh_connector connector, const void *buffer, uint32_t len) { ssize_t bwritten = -1; int flags = 0; #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; #endif if (connector->fd_is_socket) { bwritten = send(connector->out_fd,buffer, len, flags); } else { bwritten = write(connector->out_fd, buffer, len); } return bwritten; } ================================================ FILE: src/libssh/src/curve25519.c ================================================ /* * curve25519.c - Curve25519 ECDH functions for key exchange * curve25519-sha256@libssh.org and curve25519-sha256 * * This file is part of the SSH Library * * Copyright (c) 2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 2.1 of the License. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/curve25519.h" #ifdef HAVE_CURVE25519 #ifdef WITH_NACL #include "nacl/crypto_scalarmult_curve25519.h" #endif #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/dh.h" #include "libssh/pki.h" #include "libssh/bignum.h" #ifdef HAVE_OPENSSL_X25519 #include #endif static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply); static ssh_packet_callback dh_client_callbacks[] = { ssh_packet_client_curve25519_reply }; static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = { .start = SSH2_MSG_KEX_ECDH_REPLY, .n_callbacks = 1, .callbacks = dh_client_callbacks, .user = NULL }; static int ssh_curve25519_init(ssh_session session) { int rc; #ifdef HAVE_OPENSSL_X25519 EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; size_t pubkey_len = CURVE25519_PUBKEY_SIZE; size_t pkey_len = CURVE25519_PRIVKEY_SIZE; pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL); if (pctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to initialize X25519 context: %s", ERR_error_string(ERR_get_error(), NULL)); return SSH_ERROR; } rc = EVP_PKEY_keygen_init(pctx); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to initialize X25519 keygen: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_PKEY_CTX_free(pctx); return SSH_ERROR; } rc = EVP_PKEY_keygen(pctx, &pkey); EVP_PKEY_CTX_free(pctx); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to generate X25519 keys: %s", ERR_error_string(ERR_get_error(), NULL)); return SSH_ERROR; } if (session->server) { rc = EVP_PKEY_get_raw_public_key(pkey, session->next_crypto->curve25519_server_pubkey, &pubkey_len); } else { rc = EVP_PKEY_get_raw_public_key(pkey, session->next_crypto->curve25519_client_pubkey, &pubkey_len); } if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get X25519 raw public key: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_PKEY_free(pkey); return SSH_ERROR; } rc = EVP_PKEY_get_raw_private_key(pkey, session->next_crypto->curve25519_privkey, &pkey_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get X25519 raw private key: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_PKEY_free(pkey); return SSH_ERROR; } EVP_PKEY_free(pkey); #else rc = ssh_get_random(session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE, 1); if (rc != 1) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } if (session->server) { crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey, session->next_crypto->curve25519_privkey); } else { crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey, session->next_crypto->curve25519_privkey); } #endif /* HAVE_OPENSSL_X25519 */ return SSH_OK; } /** @internal * @brief Starts curve25519-sha256@libssh.org / curve25519-sha256 key exchange */ int ssh_client_curve25519_init(ssh_session session) { int rc; rc = ssh_curve25519_init(session); if (rc != SSH_OK) { return rc; } rc = ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_KEX_ECDH_INIT, CURVE25519_PUBKEY_SIZE, (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_ERROR; } /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_curve25519_client_callbacks); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); return rc; } static int ssh_curve25519_build_k(ssh_session session) { ssh_curve25519_pubkey k; #ifdef HAVE_OPENSSL_X25519 EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL, *pubkey = NULL; size_t shared_key_len = sizeof(k); int rc, ret = SSH_ERROR; pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, session->next_crypto->curve25519_privkey, CURVE25519_PRIVKEY_SIZE); if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create X25519 EVP_PKEY: %s", ERR_error_string(ERR_get_error(), NULL)); return SSH_ERROR; } pctx = EVP_PKEY_CTX_new(pkey, NULL); if (pctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to initialize X25519 context: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } rc = EVP_PKEY_derive_init(pctx); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to initialize X25519 key derivation: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } if (session->server) { pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, session->next_crypto->curve25519_client_pubkey, CURVE25519_PUBKEY_SIZE); } else { pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, session->next_crypto->curve25519_server_pubkey, CURVE25519_PUBKEY_SIZE); } if (pubkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create X25519 public key EVP_PKEY: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } rc = EVP_PKEY_derive_set_peer(pctx, pubkey); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to set peer X25519 public key: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } rc = EVP_PKEY_derive(pctx, k, &shared_key_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to derive X25519 shared secret: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } ret = SSH_OK; out: EVP_PKEY_free(pkey); EVP_PKEY_free(pubkey); EVP_PKEY_CTX_free(pctx); if (ret == SSH_ERROR) { return ret; } #else if (session->server) { crypto_scalarmult(k, session->next_crypto->curve25519_privkey, session->next_crypto->curve25519_client_pubkey); } else { crypto_scalarmult(k, session->next_crypto->curve25519_privkey, session->next_crypto->curve25519_server_pubkey); } #endif /* HAVE_OPENSSL_X25519 */ bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret); if (session->next_crypto->shared_secret == NULL) { return SSH_ERROR; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("Session server cookie", session->next_crypto->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", session->next_crypto->client_kex.cookie, 16); ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret); #endif return 0; } /** @internal * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS */ static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){ ssh_string q_s_string = NULL; ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_curve25519_client_callbacks); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Failed to import next public key"); goto error; } q_s_string = ssh_buffer_get_ssh_string(packet); if (q_s_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet"); goto error; } if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){ ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d", (int)ssh_string_len(q_s_string)); SSH_STRING_FREE(q_s_string); goto error; } memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE); SSH_STRING_FREE(q_s_string); signature = ssh_buffer_get_ssh_string(packet); if (signature == NULL) { ssh_set_error(session, SSH_FATAL, "No signature in packet"); goto error; } session->next_crypto->dh_server_signature = signature; signature=NULL; /* ownership changed */ /* TODO: verify signature now instead of waiting for NEWKEYS */ if (ssh_curve25519_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* Send the MSG_NEWKEYS */ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } rc=ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; return SSH_PACKET_USED; error: session->session_state=SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #ifdef WITH_SERVER static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init); static ssh_packet_callback dh_server_callbacks[]= { ssh_packet_server_curve25519_init }; static struct ssh_packet_callbacks_struct ssh_curve25519_server_callbacks = { .start = SSH2_MSG_KEX_ECDH_INIT, .n_callbacks = 1, .callbacks = dh_server_callbacks, .user = NULL }; /** @internal * @brief sets up the curve25519-sha256@libssh.org kex callbacks */ void ssh_server_curve25519_init(ssh_session session){ /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_curve25519_server_callbacks); } /** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a * SSH_MSG_KEXDH_REPLY */ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){ /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; ssh_string server_pubkey_blob = NULL; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; int rc; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_curve25519_server_callbacks); /* Extract the client pubkey from the init packet */ q_c_string = ssh_buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); goto error; } if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){ ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %zu", ssh_string_len(q_c_string)); SSH_STRING_FREE(q_c_string); goto error; } memcpy(session->next_crypto->curve25519_client_pubkey, ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE); SSH_STRING_FREE(q_c_string); /* Build server's keypair */ rc = ssh_curve25519_init(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Failed to generate curve25519 keys"); goto error; } rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_REPLY); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* build k and session_id */ rc = ssh_curve25519_build_k(session); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey, &digest); if (rc == SSH_ERROR) { goto error; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Could not export server public key"); goto error; } /* add host's public key */ rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_blob); SSH_STRING_FREE(server_pubkey_blob); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* add ecdh public key */ q_s_string = ssh_string_new(CURVE25519_PUBKEY_SIZE); if (q_s_string == NULL) { goto error; } ssh_string_fill(q_s_string, session->next_crypto->curve25519_server_pubkey, CURVE25519_PUBKEY_SIZE); rc = ssh_buffer_add_ssh_string(session->out_buffer, q_s_string); SSH_STRING_FREE(q_s_string); if (rc < 0) { ssh_set_error_oom(session); goto error; } /* add signature blob */ sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob); SSH_STRING_FREE(sig_blob); if (rc < 0) { ssh_set_error_oom(session); goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_ECDH_REPLY sent"); rc = ssh_packet_send(session); if (rc == SSH_ERROR) { return SSH_ERROR; } /* Send the MSG_NEWKEYS */ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc < 0) { goto error; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return SSH_PACKET_USED; error: ssh_buffer_reinit(session->out_buffer); session->session_state=SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #endif /* WITH_SERVER */ #endif /* HAVE_CURVE25519 */ ================================================ FILE: src/libssh/src/dh-gex.c ================================================ /* * dh-gex.c - diffie-hellman group exchange * * This file is part of the SSH Library * * Copyright (c) 2016 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include "libssh/priv.h" #include "libssh/dh-gex.h" #include "libssh/libssh.h" #include "libssh/ssh2.h" #include "libssh/callbacks.h" #include "libssh/dh.h" #include "libssh/buffer.h" #include "libssh/session.h" /* Minimum, recommanded and maximum size of DH group */ #define DH_PMIN 2048 #define DH_PREQ 2048 #define DH_PMAX 8192 static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group); static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply); static ssh_packet_callback dhgex_client_callbacks[] = { ssh_packet_client_dhgex_group, /* SSH_MSG_KEX_DH_GEX_GROUP */ NULL, /* SSH_MSG_KEX_DH_GEX_INIT */ ssh_packet_client_dhgex_reply /* SSH_MSG_KEX_DH_GEX_REPLY */ }; static struct ssh_packet_callbacks_struct ssh_dhgex_client_callbacks = { .start = SSH2_MSG_KEX_DH_GEX_GROUP, .n_callbacks = 3, .callbacks = dhgex_client_callbacks, .user = NULL }; /** @internal * @brief initiates a diffie-hellman-group-exchange kex */ int ssh_client_dhgex_init(ssh_session session) { int rc; rc = ssh_dh_init_common(session->next_crypto); if (rc != SSH_OK){ goto error; } session->next_crypto->dh_pmin = DH_PMIN; session->next_crypto->dh_pn = DH_PREQ; session->next_crypto->dh_pmax = DH_PMAX; /* Minimum group size, preferred group size, maximum group size */ rc = ssh_buffer_pack(session->out_buffer, "bddd", SSH2_MSG_KEX_DH_GEX_REQUEST, session->next_crypto->dh_pmin, session->next_crypto->dh_pn, session->next_crypto->dh_pmax); if (rc != SSH_OK) { goto error; } /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_dhgex_client_callbacks); session->dh_handshake_state = DH_STATE_REQUEST_SENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } return rc; error: ssh_dh_cleanup(session->next_crypto); return SSH_ERROR; } /** @internal * @brief handle a DH_GEX_GROUP packet, client side. This packet contains * the group parameters. */ SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_group) { int rc; int blen; bignum pmin1 = NULL, one = NULL; bignum_CTX ctx = bignum_ctx_new(); bignum modulus = NULL, generator = NULL; const_bignum pubkey; (void) type; (void) user; SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_GROUP received"); if (bignum_ctx_invalid(ctx)) { goto error; } if (session->dh_handshake_state != DH_STATE_REQUEST_SENT) { ssh_set_error(session, SSH_FATAL, "Received DH_GEX_GROUP in invalid state"); goto error; } one = bignum_new(); pmin1 = bignum_new(); if (one == NULL || pmin1 == NULL) { ssh_set_error_oom(session); goto error; } rc = ssh_buffer_unpack(packet, "BB", &modulus, &generator); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Invalid DH_GEX_GROUP packet"); goto error; } /* basic checks */ if (ssh_fips_mode() && !ssh_dh_is_known_group(modulus, generator)) { ssh_set_error(session, SSH_FATAL, "The received DH group is not FIPS approved"); goto error; } rc = bignum_set_word(one, 1); if (rc != 1) { goto error; } blen = bignum_num_bits(modulus); if (blen < DH_PMIN || blen > DH_PMAX) { ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p: %d not in [%d:%d]", blen, DH_PMIN, DH_PMAX); goto error; } if (bignum_cmp(modulus, one) <= 0) { /* p must be positive and preferably bigger than one */ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p"); } if (!bignum_is_bit_set(modulus, 0)) { /* p must be a prime and therefore not divisible by 2 */ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter p"); goto error; } bignum_sub(pmin1, modulus, one); if (bignum_cmp(generator, one) <= 0 || bignum_cmp(generator, pmin1) > 0) { /* generator must be at least 2 and smaller than p-1*/ ssh_set_error(session, SSH_FATAL, "Invalid dh group parameter g"); goto error; } bignum_ctx_free(ctx); ctx = NULL; /* all checks passed, set parameters (the BNs are copied in openssl backend) */ rc = ssh_dh_set_parameters(session->next_crypto->dh_ctx, modulus, generator); if (rc != SSH_OK) { goto error; } #ifdef HAVE_LIBCRYPTO bignum_safe_free(modulus); bignum_safe_free(generator); #endif modulus = NULL; generator = NULL; /* compute and send DH public parameter */ rc = ssh_dh_keypair_gen_keys(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR); if (rc == SSH_ERROR) { goto error; } rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR, NULL, &pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_buffer_pack(session->out_buffer, "bB", SSH2_MSG_KEX_DH_GEX_INIT, pubkey); if (rc != SSH_OK) { goto error; } session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } bignum_safe_free(one); bignum_safe_free(pmin1); return SSH_PACKET_USED; error: bignum_safe_free(modulus); bignum_safe_free(generator); bignum_safe_free(one); bignum_safe_free(pmin1); if(!bignum_ctx_invalid(ctx)) { bignum_ctx_free(ctx); } ssh_dh_cleanup(session->next_crypto); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } static SSH_PACKET_CALLBACK(ssh_packet_client_dhgex_reply) { struct ssh_crypto_struct *crypto=session->next_crypto; int rc; ssh_string pubkey_blob = NULL; bignum server_pubkey = NULL; (void)type; (void)user; SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEX_DH_GEX_REPLY received"); ssh_packet_remove_callbacks(session, &ssh_dhgex_client_callbacks); rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, &crypto->dh_server_signature); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Invalid DH_GEX_REPLY packet"); goto error; } rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, server_pubkey); if (rc != SSH_OK) { bignum_safe_free(server_pubkey); goto error; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); if (rc != 0) { goto error; } rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR, &session->next_crypto->shared_secret); ssh_dh_debug_crypto(session->next_crypto); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); goto error; } /* Send the MSG_NEWKEYS */ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; return SSH_PACKET_USED; error: ssh_dh_cleanup(session->next_crypto); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #ifdef WITH_SERVER #define MODULI_FILE "/etc/ssh/moduli" /* 2 "Safe" prime; (p-1)/2 is also prime. */ #define SAFE_PRIME 2 /* 0x04 Probabilistic Miller-Rabin primality tests. */ #define PRIM_TEST_REQUIRED 0x04 /** * @internal * * @brief Determines if the proposed modulus size is more appropriate than the * current one. * * @returns 1 if it's more appropriate. Returns 0 if same or less appropriate */ static bool dhgroup_better_size(uint32_t pmin, uint32_t pn, uint32_t pmax, size_t current_size, size_t proposed_size) { if (current_size == proposed_size) { return false; } if (current_size == pn) { /* can't do better */ return false; } if (current_size == 0 && proposed_size >= pmin && proposed_size <= pmax) { return true; } if (proposed_size < pmin || proposed_size > pmax) { /* out of bounds */ return false; } if (current_size == 0) { /* not in the allowed window */ return false; } if (proposed_size >= pn && proposed_size < current_size) { return true; } if (proposed_size <= pn && proposed_size > current_size) { return true; } if (proposed_size >= pn && current_size < pn) { return true; } /* We're in the allowed window but a better match already exists. */ return false; } /** @internal * @brief returns 1 with 1/n probability * @returns 1 on with P(1/n), 0 with P(n-1/n). */ static bool invn_chance(int n) { uint32_t nounce = 0; int ok; ok = ssh_get_random(&nounce, sizeof(nounce), 0); if (!ok) { return false; } return (nounce % n) == 0; } /** @internal * @brief retrieves a DH group from an open moduli file. */ static int ssh_retrieve_dhgroup_file(FILE *moduli, uint32_t pmin, uint32_t pn, uint32_t pmax, size_t *best_size, char **best_generator, char **best_modulus) { char timestamp[32] = {0}; char generator[32] = {0}; char modulus[4096] = {0}; size_t type, tests, tries, size, proposed_size; int firstbyte; int rc; size_t line = 0; size_t best_nlines = 0; for(;;) { line++; firstbyte = getc(moduli); if (firstbyte == '#'){ do { firstbyte = getc(moduli); } while(firstbyte != '\n' && firstbyte != EOF); continue; } if (firstbyte == EOF) { break; } ungetc(firstbyte, moduli); rc = fscanf(moduli, "%31s %zu %zu %zu %zu %31s %4095s\n", timestamp, &type, &tests, &tries, &size, generator, modulus); if (rc != 7){ if (rc == EOF) { break; } SSH_LOG(SSH_LOG_INFO, "Invalid moduli entry line %zu", line); do { firstbyte = getc(moduli); } while(firstbyte != '\n' && firstbyte != EOF); continue; } /* we only want safe primes that were tested */ if (type != SAFE_PRIME || !(tests & PRIM_TEST_REQUIRED)) { continue; } proposed_size = size + 1; if (proposed_size != *best_size && dhgroup_better_size(pmin, pn, pmax, *best_size, proposed_size)) { best_nlines = 0; *best_size = proposed_size; } if (proposed_size == *best_size) { best_nlines++; } /* Use reservoir sampling algorithm */ if (proposed_size == *best_size && invn_chance(best_nlines)) { SAFE_FREE(*best_generator); SAFE_FREE(*best_modulus); *best_generator = strdup(generator); if (*best_generator == NULL) { return SSH_ERROR; } *best_modulus = strdup(modulus); if (*best_modulus == NULL) { SAFE_FREE(*best_generator); return SSH_ERROR; } } } if (*best_size != 0) { SSH_LOG(SSH_LOG_INFO, "Selected %zu bits modulus out of %zu candidates in %zu lines", *best_size, best_nlines - 1, line); } else { SSH_LOG(SSH_LOG_WARNING, "No moduli found for [%u:%u:%u]", pmin, pn, pmax); } return SSH_OK; } /** @internal * @brief retrieves a DH group from the moduli file based on bits len parameters * @param[in] pmin minimum group size in bits * @param[in] pn preferred group size * @param[in] pmax maximum group size * @param[out] size size of the chosen modulus * @param[out] p modulus * @param[out] g generator * @return SSH_OK on success, SSH_ERROR otherwise. */ static int ssh_retrieve_dhgroup(uint32_t pmin, uint32_t pn, uint32_t pmax, size_t *size, bignum *p, bignum *g) { FILE *moduli = NULL; char *generator = NULL; char *modulus = NULL; int rc; /* In FIPS mode, we can not negotiate arbitrary primes, * but just the approved ones */ if (ssh_fips_mode()) { SSH_LOG(SSH_LOG_TRACE, "In FIPS mode, using built-in primes"); return ssh_fallback_group(pmax, p, g); } moduli = fopen(MODULI_FILE, "r"); if (moduli == NULL) { SSH_LOG(SSH_LOG_WARNING, "Unable to open moduli file: %s", strerror(errno)); return ssh_fallback_group(pmax, p, g); } *size = 0; *p = NULL; *g = NULL; rc = ssh_retrieve_dhgroup_file(moduli, pmin, pn, pmax, size, &generator, &modulus); fclose(moduli); if (rc == SSH_ERROR || *size == 0) { goto error; } rc = bignum_hex2bn(generator, g); if (rc == 0) { goto error; } rc = bignum_hex2bn(modulus, p); if (rc == 0) { goto error; } SAFE_FREE(generator); SAFE_FREE(modulus); return SSH_OK; error: bignum_safe_free(*g); bignum_safe_free(*p); SAFE_FREE(generator); SAFE_FREE(modulus); return SSH_ERROR; } static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_request); static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_init); static ssh_packet_callback dhgex_server_callbacks[]= { NULL, /* SSH_MSG_KEX_DH_GEX_REQUEST_OLD */ NULL, /* SSH_MSG_KEX_DH_GEX_GROUP */ ssh_packet_server_dhgex_init, /* SSH_MSG_KEX_DH_GEX_INIT */ NULL, /* SSH_MSG_KEX_DH_GEX_REPLY */ ssh_packet_server_dhgex_request /* SSH_MSG_GEX_DH_GEX_REQUEST */ }; static struct ssh_packet_callbacks_struct ssh_dhgex_server_callbacks = { .start = SSH2_MSG_KEX_DH_GEX_REQUEST_OLD, .n_callbacks = 5, .callbacks = dhgex_server_callbacks, .user = NULL }; /** @internal * @brief sets up the diffie-hellman-groupx kex callbacks */ void ssh_server_dhgex_init(ssh_session session){ /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_dhgex_server_callbacks); ssh_dh_init_common(session->next_crypto); session->dh_handshake_state = DH_STATE_INIT; } static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_request) { bignum modulus = NULL, generator = NULL; uint32_t pmin, pn, pmax; size_t size = 0; int rc; (void) type; (void) user; if (session->dh_handshake_state != DH_STATE_INIT) { ssh_set_error(session, SSH_FATAL, "Received DH_GEX_REQUEST in invalid state"); goto error; } /* Minimum group size, preferred group size, maximum group size */ rc = ssh_buffer_unpack(packet, "ddd", &pmin, &pn, &pmax); if (rc != SSH_OK){ ssh_set_error_invalid(session); goto error; } SSH_LOG(SSH_LOG_INFO, "dh-gex: DHGEX_REQUEST[%u:%u:%u]", pmin, pn, pmax); if (pmin > pn || pn > pmax || pn > DH_PMAX || pmax < DH_PMIN) { ssh_set_error(session, SSH_FATAL, "Invalid dh-gex arguments [%u:%u:%u]", pmin, pn, pmax); goto error; } session->next_crypto->dh_pmin = pmin; session->next_crypto->dh_pn = pn; session->next_crypto->dh_pmax = pmax; /* ensure safe parameters */ if (pmin < DH_PMIN) { pmin = DH_PMIN; if (pn < pmin) { pn = pmin; } } rc = ssh_retrieve_dhgroup(pmin, pn, pmax, &size, &modulus, &generator); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Couldn't find DH group for [%u:%u:%u]", pmin, pn, pmax); goto error; } rc = ssh_dh_set_parameters(session->next_crypto->dh_ctx, modulus, generator); if (rc != SSH_OK) { bignum_safe_free(generator); bignum_safe_free(modulus); goto error; } rc = ssh_buffer_pack(session->out_buffer, "bBB", SSH2_MSG_KEX_DH_GEX_GROUP, modulus, generator); #ifdef HAVE_LIBCRYPTO bignum_safe_free(generator); bignum_safe_free(modulus); #endif if (rc != SSH_OK) { ssh_set_error_invalid(session); goto error; } session->dh_handshake_state = DH_STATE_GROUP_SENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } error: return SSH_PACKET_USED; } /** @internal * @brief parse an incoming SSH_MSG_KEX_DH_GEX_INIT packet and complete * Diffie-Hellman key exchange **/ static SSH_PACKET_CALLBACK(ssh_packet_server_dhgex_init){ (void) type; (void) user; SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEX_DHGEX_INIT"); ssh_packet_remove_callbacks(session, &ssh_dhgex_server_callbacks); ssh_server_dh_process_init(session, packet); return SSH_PACKET_USED; } #endif /* WITH_SERVER */ ================================================ FILE: src/libssh/src/dh.c ================================================ /* * dh.c - Diffie-Helman algorithm code against SSH 2 * * This file is part of the SSH Library * * Copyright (c) 2003-2018 by Aris Adamantiadis * Copyright (c) 2009-2013 by Andreas Schneider * Copyright (c) 2012 by Dmitriy Kuznetsov * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/dh.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" static unsigned char p_group1_value[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #define P_GROUP1_LEN 128 /* Size in bytes of the p number */ static unsigned char p_group14_value[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */ static unsigned char p_group16_value[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */ static unsigned char p_group18_value[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */ bignum ssh_dh_generator; bignum ssh_dh_group1; bignum ssh_dh_group14; bignum ssh_dh_group16; bignum ssh_dh_group18; static int dh_crypto_initialized; /** * @internal * @brief Initialize global constants used in DH key agreement * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_dh_init(void) { unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */ int rc; if (dh_crypto_initialized) { return SSH_OK; } dh_crypto_initialized = 1; ssh_dh_generator = bignum_new(); if (ssh_dh_generator == NULL) { goto error; } rc = bignum_set_word(ssh_dh_generator, g_int); if (rc != 1) { goto error; } bignum_bin2bn(p_group1_value, P_GROUP1_LEN, &ssh_dh_group1); if (ssh_dh_group1 == NULL) { goto error; } bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &ssh_dh_group14); if (ssh_dh_group14 == NULL) { goto error; } bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &ssh_dh_group16); if (ssh_dh_group16 == NULL) { goto error; } bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &ssh_dh_group18); if (ssh_dh_group18 == NULL) { goto error; } return 0; error: ssh_dh_finalize(); return SSH_ERROR; } /** * @internal * @brief Finalize and free global constants used in DH key agreement */ void ssh_dh_finalize(void) { if (!dh_crypto_initialized) { return; } bignum_safe_free(ssh_dh_generator); bignum_safe_free(ssh_dh_group1); bignum_safe_free(ssh_dh_group14); bignum_safe_free(ssh_dh_group16); bignum_safe_free(ssh_dh_group18); dh_crypto_initialized = 0; } int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob) { return ssh_pki_import_pubkey_blob(pubkey_blob, &session->next_crypto->server_pubkey); } static SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply); static ssh_packet_callback dh_client_callbacks[]= { ssh_packet_client_dh_reply }; static struct ssh_packet_callbacks_struct ssh_dh_client_callbacks = { .start = SSH2_MSG_KEXDH_REPLY, .n_callbacks = 1, .callbacks = dh_client_callbacks, .user = NULL }; /** @internal * @brief Starts diffie-hellman-group1 key exchange */ int ssh_client_dh_init(ssh_session session){ struct ssh_crypto_struct *crypto = session->next_crypto; const_bignum pubkey; int rc; rc = ssh_dh_init_common(crypto); if (rc == SSH_ERROR) { goto error; } rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR); if (rc == SSH_ERROR){ goto error; } rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR, NULL, &pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_buffer_pack(session->out_buffer, "bB", SSH2_MSG_KEXDH_INIT, pubkey); if (rc != SSH_OK) { goto error; } /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_dh_client_callbacks); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); return rc; error: ssh_dh_cleanup(crypto); return SSH_ERROR; } SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){ struct ssh_crypto_struct *crypto=session->next_crypto; ssh_string pubkey_blob = NULL; bignum server_pubkey; int rc; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks); rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey, &crypto->dh_server_signature); if (rc == SSH_ERROR) { goto error; } rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, server_pubkey); if (rc != SSH_OK) { bignum_safe_free(server_pubkey); goto error; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); if (rc != 0) { goto error; } rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR, &session->next_crypto->shared_secret); ssh_dh_debug_crypto(session->next_crypto); if (rc == SSH_ERROR){ ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); goto error; } /* Send the MSG_NEWKEYS */ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } rc=ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; return SSH_PACKET_USED; error: ssh_dh_cleanup(session->next_crypto); session->session_state=SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #ifdef WITH_SERVER static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init); static ssh_packet_callback dh_server_callbacks[] = { ssh_packet_server_dh_init, }; static struct ssh_packet_callbacks_struct ssh_dh_server_callbacks = { .start = SSH2_MSG_KEXDH_INIT, .n_callbacks = 1, .callbacks = dh_server_callbacks, .user = NULL }; /** @internal * @brief sets up the diffie-hellman-groupx kex callbacks */ void ssh_server_dh_init(ssh_session session){ /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_dh_server_callbacks); ssh_dh_init_common(session->next_crypto); } /** @internal * @brief processes a SSH_MSG_KEXDH_INIT or SSH_MSG_KEX_DH_GEX_INIT packet and sends * the appropriate SSH_MSG_KEXDH_REPLY or SSH_MSG_KEX_DH_GEX_REPLY */ int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet) { struct ssh_crypto_struct *crypto = session->next_crypto; ssh_key privkey = NULL; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; ssh_string pubkey_blob = NULL; bignum client_pubkey; const_bignum server_pubkey; int packet_type; int rc; rc = ssh_buffer_unpack(packet, "B", &client_pubkey); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "No e number in client request"); goto error; } rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR, NULL, client_pubkey); if (rc != SSH_OK) { bignum_safe_free(client_pubkey); goto error; } rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR); if (rc == SSH_ERROR) { goto error; } rc = ssh_get_key_params(session, &privkey, &digest); if (rc != SSH_OK) { goto error; } rc = ssh_dh_compute_shared_secret(crypto->dh_ctx, DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR, &crypto->shared_secret); ssh_dh_debug_crypto(crypto); if (rc == SSH_ERROR) { ssh_set_error(session, SSH_FATAL, "Could not generate shared secret"); goto error; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } switch (crypto->kex_type){ case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: case SSH_KEX_DH_GROUP16_SHA512: case SSH_KEX_DH_GROUP18_SHA512: packet_type = SSH2_MSG_KEXDH_REPLY; break; #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA1: case SSH_KEX_DH_GEX_SHA256: packet_type = SSH2_MSG_KEX_DH_GEX_REPLY; break; #endif /* WITH_GEX */ default: ssh_set_error(session, SSH_FATAL, "Invalid kex type"); goto error; } rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, &server_pubkey); if (rc != SSH_OK){ goto error; } rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob); if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } rc = ssh_buffer_pack(session->out_buffer, "bSBS", packet_type, pubkey_blob, server_pubkey, sig_blob); SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(pubkey_blob); if(rc != SSH_OK) { ssh_set_error_oom(session); ssh_buffer_reinit(session->out_buffer); goto error; } rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY"); if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { ssh_buffer_reinit(session->out_buffer); goto error; } session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; if (ssh_packet_send(session) == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); return SSH_OK; error: SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(pubkey_blob); session->session_state = SSH_SESSION_STATE_ERROR; ssh_dh_cleanup(session->next_crypto); return SSH_ERROR; } /** @internal * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete * Diffie-Hellman key exchange **/ static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){ (void)type; (void)user; SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXDH_INIT"); ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks); ssh_server_dh_process_init(session, packet); return SSH_PACKET_USED; } /** @internal * @brief Choose a fallback group for the DH Group exchange if the * moduli file is not readable * @param[in] pmax maximum requestsd group size * @param[out] modulus * @param[out] generator * @returns SSH_OK on success, SSH_ERROR otherwise */ int ssh_fallback_group(uint32_t pmax, bignum *modulus, bignum *generator) { *modulus = NULL; *generator = NULL; if (pmax < 3072) { bignum_dup(ssh_dh_group14, modulus); } else if (pmax < 6144) { bignum_dup(ssh_dh_group16, modulus); } else { bignum_dup(ssh_dh_group18, modulus); } if (*modulus == NULL) { return SSH_ERROR; } bignum_dup(ssh_dh_generator, generator); if (*generator == NULL) { bignum_safe_free((*modulus)); return SSH_ERROR; } return SSH_OK; } #endif /* WITH_SERVER */ /** * @addtogroup libssh_session * * @{ */ bool ssh_dh_is_known_group(bignum modulus, bignum generator) { int cmp, bits; bignum m = NULL; bits = bignum_num_bits(modulus); if (bits < 3072) { m = ssh_dh_group14; } else if (bits < 6144) { m = ssh_dh_group16; } else { m = ssh_dh_group18; } cmp = bignum_cmp(m, modulus); if (cmp != 0) { return false; } cmp = bignum_cmp(ssh_dh_generator, generator); if (cmp != 0) { return false; } SSH_LOG(SSH_LOG_TRACE, "The received primes in FIPS are known"); return true; } ssh_key ssh_dh_get_current_server_publickey(ssh_session session) { if (session->current_crypto == NULL) { return NULL; } return session->current_crypto->server_pubkey; } /* Caller need to free the blob */ int ssh_dh_get_current_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob) { const ssh_key pubkey = ssh_dh_get_current_server_publickey(session); return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); } ssh_key ssh_dh_get_next_server_publickey(ssh_session session) { return session->next_crypto->server_pubkey; } /* Caller need to free the blob */ int ssh_dh_get_next_server_publickey_blob(ssh_session session, ssh_string *pubkey_blob) { const ssh_key pubkey = ssh_dh_get_next_server_publickey(session); return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob); } /** * @internal * * @brief Convert a buffer into an unpadded base64 string. * The caller has to free the memory. * * @param hash What should be converted to a base64 string. * * @param len Length of the buffer to convert. * * @return The base64 string or NULL on error. * * @see ssh_string_free_char() */ static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len) { char *b64_padded = NULL; char *b64_unpadded = NULL; size_t k; b64_padded = (char *)bin_to_base64(hash, (int)len); if (b64_padded == NULL) { return NULL; } for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--); b64_unpadded = strndup(b64_padded, k); SAFE_FREE(b64_padded); return b64_unpadded; } /** * @brief Get a hash as a human-readable hex- or base64-string. * * This gets an allocated fingerprint hash. If it is a SHA sum, it will * return an unpadded base64 strings. If it is a MD5 sum, it will return hex * string. Either way, the output is prepended by the hash-type. * * @warning Do NOT use MD5 or SHA1! Those hash functions are being deprecated. * * @param type Which sort of hash is given, use * SSH_PUBLICKEY_HASH_SHA256 or better. * * @param hash The hash to be converted to fingerprint. * * @param len Length of the buffer to convert. * * @return Returns the allocated fingerprint hash or NULL on error. * * @see ssh_string_free_char() */ char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len) { const char *prefix = "UNKNOWN"; char *fingerprint = NULL; char *str = NULL; size_t str_len; int rc; switch (type) { case SSH_PUBLICKEY_HASH_SHA1: case SSH_PUBLICKEY_HASH_SHA256: fingerprint = ssh_get_b64_unpadded(hash, len); break; case SSH_PUBLICKEY_HASH_MD5: fingerprint = ssh_get_hexa(hash, len); break; } if (fingerprint == NULL) { return NULL; } switch (type) { case SSH_PUBLICKEY_HASH_MD5: prefix = "MD5"; break; case SSH_PUBLICKEY_HASH_SHA1: prefix = "SHA1"; break; case SSH_PUBLICKEY_HASH_SHA256: prefix = "SHA256"; break; } str_len = strlen(prefix); if (str_len + 1 + strlen(fingerprint) + 1 < str_len) { SAFE_FREE(fingerprint); return NULL; } str_len += 1 + strlen(fingerprint) + 1; str = malloc(str_len); if (str == NULL) { SAFE_FREE(fingerprint); return NULL; } rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint); SAFE_FREE(fingerprint); if (rc < 0 || rc < (int)(str_len - 1)) { SAFE_FREE(str); } return str; } /** * @brief Print a hash as a human-readable hex- or base64-string. * * This prints an unpadded base64 strings for SHA sums and hex strings for MD5 * sum. Either way, the output is prepended by the hash-type. * * @param type Which sort of hash is given. Use * SSH_PUBLICKEY_HASH_SHA256 or better. * * @param hash The hash to be converted to fingerprint. * * @param len Length of the buffer to convert. * * @see ssh_get_publickey_hash() * @see ssh_get_fingerprint_hash() */ void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len) { char *fingerprint = NULL; fingerprint = ssh_get_fingerprint_hash(type, hash, len); if (fingerprint == NULL) { return; } fprintf(stderr, "%s\n", fingerprint); SAFE_FREE(fingerprint); } /** @} */ ================================================ FILE: src/libssh/src/dh_crypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2019 by Simo Sorce - Red Hat, Inc. * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/session.h" #include "libssh/dh.h" #include "libssh/buffer.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "openssl/crypto.h" #include "openssl/dh.h" #include "libcrypto-compat.h" extern bignum ssh_dh_generator; extern bignum ssh_dh_group1; extern bignum ssh_dh_group14; extern bignum ssh_dh_group16; extern bignum ssh_dh_group18; struct dh_ctx { DH *keypair[2]; }; void ssh_dh_debug_crypto(struct ssh_crypto_struct *c) { #ifdef DEBUG_CRYPTO const_bignum x = NULL, y = NULL, e = NULL, f = NULL; ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e); ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f); ssh_print_bignum("x", x); ssh_print_bignum("y", y); ssh_print_bignum("e", e); ssh_print_bignum("f", f); ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16); ssh_print_bignum("k", c->shared_secret); #else (void)c; /* UNUSED_PARAM */ #endif } int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, const_bignum *priv, const_bignum *pub) { if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || ((priv == NULL) && (pub == NULL)) || (ctx == NULL) || (ctx->keypair[peer] == NULL)) { return SSH_ERROR; } DH_get0_key(ctx->keypair[peer], pub, priv); if (priv && (*priv == NULL || bignum_num_bits(*priv) == 0)) { return SSH_ERROR; } if (pub && (*pub == NULL || bignum_num_bits(*pub) == 0)) { return SSH_ERROR; } return SSH_OK; } int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, const bignum priv, const bignum pub) { bignum priv_key = NULL; bignum pub_key = NULL; if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || ((priv == NULL) && (pub == NULL)) || (ctx == NULL) || (ctx->keypair[peer] == NULL)) { return SSH_ERROR; } if (priv) { priv_key = priv; } if (pub) { pub_key = pub; } (void)DH_set0_key(ctx->keypair[peer], pub_key, priv_key); return SSH_OK; } int ssh_dh_get_parameters(struct dh_ctx *ctx, const_bignum *modulus, const_bignum *generator) { if (ctx == NULL || ctx->keypair[0] == NULL) { return SSH_ERROR; } DH_get0_pqg(ctx->keypair[0], modulus, NULL, generator); return SSH_OK; } int ssh_dh_set_parameters(struct dh_ctx *ctx, const bignum modulus, const bignum generator) { size_t i; int rc; if ((ctx == NULL) || (modulus == NULL) || (generator == NULL)) { return SSH_ERROR; } for (i = 0; i < 2; i++) { bignum p = NULL; bignum g = NULL; /* when setting modulus or generator, * make sure to invalidate existing keys */ DH_free(ctx->keypair[i]); ctx->keypair[i] = DH_new(); if (ctx->keypair[i] == NULL) { rc = SSH_ERROR; goto done; } p = BN_dup(modulus); g = BN_dup(generator); rc = DH_set0_pqg(ctx->keypair[i], p, NULL, g); if (rc != 1) { BN_free(p); BN_free(g); rc = SSH_ERROR; goto done; } } rc = SSH_OK; done: if (rc != SSH_OK) { DH_free(ctx->keypair[0]); DH_free(ctx->keypair[1]); ctx->keypair[0] = NULL; ctx->keypair[1] = NULL; } return rc; } /** * @internal * @brief allocate and initialize ephemeral values used in dh kex */ int ssh_dh_init_common(struct ssh_crypto_struct *crypto) { struct dh_ctx *ctx; int rc; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return SSH_ERROR; } crypto->dh_ctx = ctx; switch (crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator); break; case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator); break; case SSH_KEX_DH_GROUP16_SHA512: rc = ssh_dh_set_parameters(ctx, ssh_dh_group16, ssh_dh_generator); break; case SSH_KEX_DH_GROUP18_SHA512: rc = ssh_dh_set_parameters(ctx, ssh_dh_group18, ssh_dh_generator); break; default: rc = SSH_OK; break; } if (rc != SSH_OK) { ssh_dh_cleanup(crypto); } return rc; } void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) { if (crypto->dh_ctx != NULL) { DH_free(crypto->dh_ctx->keypair[0]); DH_free(crypto->dh_ctx->keypair[1]); free(crypto->dh_ctx); crypto->dh_ctx = NULL; } } /** @internal * @brief generates a secret DH parameter of at least DH_SECURITY_BITS * security as well as the corresponding public key. * @param[out] parms a dh_ctx that will hold the new keys. * @param peer Select either client or server key storage. Valid values are: * DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR * * @return SSH_OK on success, SSH_ERROR on error */ int ssh_dh_keypair_gen_keys(struct dh_ctx *dh_ctx, int peer) { int rc; if ((dh_ctx == NULL) || (dh_ctx->keypair[peer] == NULL)) { return SSH_ERROR; } rc = DH_generate_key(dh_ctx->keypair[peer]); if (rc != 1) { return SSH_ERROR; } return SSH_OK; } /** @internal * @brief generates a shared secret between the local peer and the remote * peer. The local peer must have been initialized using either the * ssh_dh_keypair_gen_keys() function or by seetting manually both * the private and public keys. The remote peer only needs to have * the remote's peer public key set. * @param[in] local peer identifier (DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR) * @param[in] remote peer identifier (DH_CLIENT_KEYPAIR or DH_SERVER_KEYPAIR) * @param[out] dest a new bignum with the shared secret value is returned. * @return SSH_OK on success, SSH_ERROR on error */ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, bignum *dest) { unsigned char *kstring = NULL; const_bignum pub_key = NULL; int klen, rc; if ((dh_ctx == NULL) || (dh_ctx->keypair[local] == NULL) || (dh_ctx->keypair[remote] == NULL)) { return SSH_ERROR; } kstring = malloc(DH_size(dh_ctx->keypair[local])); if (kstring == NULL) { rc = SSH_ERROR; goto done; } rc = ssh_dh_keypair_get_keys(dh_ctx, remote, NULL, &pub_key); if (rc != SSH_OK) { rc = SSH_ERROR; goto done; } klen = DH_compute_key(kstring, pub_key, dh_ctx->keypair[local]); if (klen == -1) { rc = SSH_ERROR; goto done; } *dest = BN_bin2bn(kstring, klen, NULL); if (*dest == NULL) { rc = SSH_ERROR; goto done; } rc = SSH_OK; done: free(kstring); return rc; } ================================================ FILE: src/libssh/src/dh_key.c ================================================ /* * dh-int.c - Diffie-Helman algorithm code against SSH 2 * * This file is part of the SSH Library * * Copyright (c) 2003-2018 by Aris Adamantiadis * Copyright (c) 2009-2013 by Andreas Schneider * Copyright (c) 2012 by Dmitriy Kuznetsov * Copyright (c) 2019 by Simo Sorce * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/dh.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" extern bignum ssh_dh_generator; extern bignum ssh_dh_group1; extern bignum ssh_dh_group14; extern bignum ssh_dh_group16; extern bignum ssh_dh_group18; /* * How many bits of security we want for fast DH. DH private key size must be * twice that size. */ #define DH_SECURITY_BITS 512 struct dh_keypair { bignum priv_key; bignum pub_key; }; struct dh_ctx { /* 0 is client, 1 is server */ struct dh_keypair keypair[2]; bignum generator; bignum modulus; }; void ssh_dh_debug_crypto(struct ssh_crypto_struct *c) { #ifdef DEBUG_CRYPTO const_bignum x = NULL, y = NULL, e = NULL, f = NULL; ssh_dh_keypair_get_keys(c->dh_ctx, DH_CLIENT_KEYPAIR, &x, &e); ssh_dh_keypair_get_keys(c->dh_ctx, DH_SERVER_KEYPAIR, &y, &f); ssh_print_bignum("p", c->dh_ctx->modulus); ssh_print_bignum("g", c->dh_ctx->generator); ssh_print_bignum("x", x); ssh_print_bignum("y", y); ssh_print_bignum("e", e); ssh_print_bignum("f", f); ssh_log_hexdump("Session server cookie", c->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", c->client_kex.cookie, 16); ssh_print_bignum("k", c->shared_secret); #else (void)c; /* UNUSED_PARAM */ #endif } static void ssh_dh_free_modulus(struct dh_ctx *ctx) { if ((ctx->modulus != ssh_dh_group1) && (ctx->modulus != ssh_dh_group14) && (ctx->modulus != ssh_dh_group16) && (ctx->modulus != ssh_dh_group18)) { bignum_safe_free(ctx->modulus); } ctx->modulus = NULL; } static void ssh_dh_free_generator(struct dh_ctx *ctx) { if (ctx->generator != ssh_dh_generator) { bignum_safe_free(ctx->generator); } } static void ssh_dh_free_dh_keypair(struct dh_keypair *keypair) { bignum_safe_free(keypair->priv_key); bignum_safe_free(keypair->pub_key); } static int ssh_dh_init_dh_keypair(struct dh_keypair *keypair) { int rc; keypair->priv_key = bignum_new(); if (keypair->priv_key == NULL) { rc = SSH_ERROR; goto done; } keypair->pub_key = bignum_new(); if (keypair->pub_key == NULL) { rc = SSH_ERROR; goto done; } rc = SSH_OK; done: if (rc != SSH_OK) { ssh_dh_free_dh_keypair(keypair); } return rc; } int ssh_dh_keypair_get_keys(struct dh_ctx *ctx, int peer, const_bignum *priv, const_bignum *pub) { if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || ((priv == NULL) && (pub == NULL)) || (ctx == NULL)) { return SSH_ERROR; } if (priv) { /* check that we have something in it */ if (bignum_num_bits(ctx->keypair[peer].priv_key)) { *priv = ctx->keypair[peer].priv_key; } else { return SSH_ERROR; } } if (pub) { /* check that we have something in it */ if (bignum_num_bits(ctx->keypair[peer].pub_key)) { *pub = ctx->keypair[peer].pub_key; } else { return SSH_ERROR; } } return SSH_OK; } int ssh_dh_keypair_set_keys(struct dh_ctx *ctx, int peer, bignum priv, bignum pub) { if (((peer != DH_CLIENT_KEYPAIR) && (peer != DH_SERVER_KEYPAIR)) || ((priv == NULL) && (pub == NULL)) || (ctx == NULL)) { return SSH_ERROR; } if (priv) { bignum_safe_free(ctx->keypair[peer].priv_key); ctx->keypair[peer].priv_key = priv; } if (pub) { bignum_safe_free(ctx->keypair[peer].pub_key); ctx->keypair[peer].pub_key = pub; } return SSH_OK; } int ssh_dh_get_parameters(struct dh_ctx *ctx, const_bignum *modulus, const_bignum *generator) { if (ctx == NULL) { return SSH_ERROR; } if (modulus) { *modulus = ctx->modulus; } if (generator) { *generator = ctx->generator; } return SSH_OK; } int ssh_dh_set_parameters(struct dh_ctx *ctx, bignum modulus, bignum generator) { int rc; if ((ctx == NULL) || ((modulus == NULL) && (generator == NULL))) { return SSH_ERROR; } /* when setting modulus or generator, * make sure to invalidate existing keys */ ssh_dh_free_dh_keypair(&ctx->keypair[DH_CLIENT_KEYPAIR]); ssh_dh_free_dh_keypair(&ctx->keypair[DH_SERVER_KEYPAIR]); rc = ssh_dh_init_dh_keypair(&ctx->keypair[DH_CLIENT_KEYPAIR]); if (rc != SSH_OK) { goto done; } rc = ssh_dh_init_dh_keypair(&ctx->keypair[DH_SERVER_KEYPAIR]); if (rc != SSH_OK) { goto done; } if (modulus) { ssh_dh_free_modulus(ctx); ctx->modulus = modulus; } if (generator) { ssh_dh_free_generator(ctx); ctx->generator = generator; } done: return rc; } /** * @internal * @brief allocate and initialize ephemeral values used in dh kex */ int ssh_dh_init_common(struct ssh_crypto_struct *crypto) { struct dh_ctx *ctx = NULL; int rc; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return SSH_ERROR; } switch (crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: rc = ssh_dh_set_parameters(ctx, ssh_dh_group1, ssh_dh_generator); break; case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: rc = ssh_dh_set_parameters(ctx, ssh_dh_group14, ssh_dh_generator); break; case SSH_KEX_DH_GROUP16_SHA512: rc = ssh_dh_set_parameters(ctx, ssh_dh_group16, ssh_dh_generator); break; case SSH_KEX_DH_GROUP18_SHA512: rc = ssh_dh_set_parameters(ctx, ssh_dh_group18, ssh_dh_generator); break; default: rc = SSH_OK; break; } crypto->dh_ctx = ctx; if (rc != SSH_OK) { ssh_dh_cleanup(crypto); } return rc; } void ssh_dh_cleanup(struct ssh_crypto_struct *crypto) { struct dh_ctx *ctx = crypto->dh_ctx; if (ctx == NULL) { return; } ssh_dh_free_dh_keypair(&ctx->keypair[DH_CLIENT_KEYPAIR]); ssh_dh_free_dh_keypair(&ctx->keypair[DH_SERVER_KEYPAIR]); ssh_dh_free_modulus(ctx); ssh_dh_free_generator(ctx); free(ctx); crypto->dh_ctx = NULL; } /** @internal * @brief generates a secret DH parameter of at least DH_SECURITY_BITS * security as well as the corresponding public key. * @param[out] parms a dh_kex paramters structure with preallocated bignum * where to store the parameters * @return SSH_OK on success, SSH_ERROR on error */ int ssh_dh_keypair_gen_keys(struct dh_ctx *dh_ctx, int peer) { bignum tmp = NULL; bignum_CTX ctx = NULL; int rc = 0; int bits = 0; int p_bits = 0; ctx = bignum_ctx_new(); if (bignum_ctx_invalid(ctx)){ goto error; } tmp = bignum_new(); if (tmp == NULL) { goto error; } p_bits = bignum_num_bits(dh_ctx->modulus); /* we need at most DH_SECURITY_BITS */ bits = MIN(DH_SECURITY_BITS * 2, p_bits); /* ensure we're not too close of p so rnd()%p stays uniform */ if (bits <= p_bits && bits + 64 > p_bits) { bits += 64; } rc = bignum_rand(tmp, bits); if (rc != 1) { goto error; } rc = bignum_mod(dh_ctx->keypair[peer].priv_key, tmp, dh_ctx->modulus, ctx); if (rc != 1) { goto error; } /* Now compute the corresponding public key */ rc = bignum_mod_exp(dh_ctx->keypair[peer].pub_key, dh_ctx->generator, dh_ctx->keypair[peer].priv_key, dh_ctx->modulus, ctx); if (rc != 1) { goto error; } bignum_safe_free(tmp); bignum_ctx_free(ctx); return SSH_OK; error: bignum_safe_free(tmp); bignum_ctx_free(ctx); return SSH_ERROR; } /** @internal * @brief generates a shared secret between the local peer and the remote peer * @param[in] local peer identifier * @param[in] remote peer identifier * @param[out] dest a preallocated bignum where to store parameter * @return SSH_OK on success, SSH_ERROR on error */ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote, bignum *dest) { int rc; bignum_CTX ctx = bignum_ctx_new(); if (bignum_ctx_invalid(ctx)) { return -1; } if (*dest == NULL) { *dest = bignum_new(); if (*dest == NULL) { rc = 0; goto done; } } rc = bignum_mod_exp(*dest, dh_ctx->keypair[remote].pub_key, dh_ctx->keypair[local].priv_key, dh_ctx->modulus, ctx); done: bignum_ctx_free(ctx); if (rc != 1) { return SSH_ERROR; } return SSH_OK; } ================================================ FILE: src/libssh/src/ecdh.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2011-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/session.h" #include "libssh/ecdh.h" #include "libssh/dh.h" #include "libssh/buffer.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" #ifdef HAVE_ECDH static SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply); static ssh_packet_callback ecdh_client_callbacks[]= { ssh_packet_client_ecdh_reply }; struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks = { .start = SSH2_MSG_KEX_ECDH_REPLY, .n_callbacks = 1, .callbacks = ecdh_client_callbacks, .user = NULL }; /** @internal * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back * a SSH_MSG_NEWKEYS */ SSH_PACKET_CALLBACK(ssh_packet_client_ecdh_reply){ ssh_string q_s_string = NULL; ssh_string pubkey_blob = NULL; ssh_string signature = NULL; int rc; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_ecdh_client_callbacks); pubkey_blob = ssh_buffer_get_ssh_string(packet); if (pubkey_blob == NULL) { ssh_set_error(session,SSH_FATAL, "No public key in packet"); goto error; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); if (rc != 0) { goto error; } q_s_string = ssh_buffer_get_ssh_string(packet); if (q_s_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet"); goto error; } session->next_crypto->ecdh_server_pubkey = q_s_string; signature = ssh_buffer_get_ssh_string(packet); if (signature == NULL) { ssh_set_error(session, SSH_FATAL, "No signature in packet"); goto error; } session->next_crypto->dh_server_signature = signature; signature=NULL; /* ownership changed */ /* TODO: verify signature now instead of waiting for NEWKEYS */ if (ecdh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* Send the MSG_NEWKEYS */ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } rc=ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; return SSH_PACKET_USED; error: session->session_state=SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #ifdef WITH_SERVER static ssh_packet_callback ecdh_server_callbacks[] = { ssh_packet_server_ecdh_init }; struct ssh_packet_callbacks_struct ssh_ecdh_server_callbacks = { .start = SSH2_MSG_KEX_ECDH_INIT, .n_callbacks = 1, .callbacks = ecdh_server_callbacks, .user = NULL }; /** @internal * @brief sets up the ecdh kex callbacks */ void ssh_server_ecdh_init(ssh_session session){ ssh_packet_set_callbacks(session, &ssh_ecdh_server_callbacks); } #endif /* WITH_SERVER */ #endif /* HAVE_ECDH */ ================================================ FILE: src/libssh/src/ecdh_crypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2011-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/session.h" #include "libssh/ecdh.h" #include "libssh/dh.h" #include "libssh/buffer.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" #ifdef HAVE_ECDH #include #define NISTP256 NID_X9_62_prime256v1 #define NISTP384 NID_secp384r1 #define NISTP521 NID_secp521r1 /** @internal * @brief Map the given key exchange enum value to its curve name. */ static int ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { return NISTP256; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { return NISTP384; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { return NISTP521; } return SSH_ERROR; } /** @internal * @brief Starts ecdh-sha2-nistp256 key exchange */ int ssh_client_ecdh_init(ssh_session session){ EC_KEY *key; const EC_GROUP *group; const EC_POINT *pubkey; ssh_string client_pubkey; int curve; int len; int rc; bignum_CTX ctx = BN_CTX_new(); rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { BN_CTX_free(ctx); return SSH_ERROR; } curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == SSH_ERROR) { BN_CTX_free(ctx); return SSH_ERROR; } key = EC_KEY_new_by_curve_name(curve); if (key == NULL) { BN_CTX_free(ctx); return SSH_ERROR; } group = EC_KEY_get0_group(key); EC_KEY_generate_key(key); pubkey=EC_KEY_get0_public_key(key); len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, NULL,0,ctx); client_pubkey = ssh_string_new(len); if (client_pubkey == NULL) { BN_CTX_free(ctx); EC_KEY_free(key); return SSH_ERROR; } EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(client_pubkey),len,ctx); BN_CTX_free(ctx); rc = ssh_buffer_add_ssh_string(session->out_buffer,client_pubkey); if (rc < 0) { EC_KEY_free(key); SSH_STRING_FREE(client_pubkey); return SSH_ERROR; } session->next_crypto->ecdh_privkey = key; session->next_crypto->ecdh_client_pubkey = client_pubkey; /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); return rc; } int ecdh_build_k(ssh_session session) { const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey); EC_POINT *pubkey; void *buffer; int rc; int len = (EC_GROUP_get_degree(group) + 7) / 8; bignum_CTX ctx = bignum_ctx_new(); if (ctx == NULL) { return -1; } pubkey = EC_POINT_new(group); if (pubkey == NULL) { bignum_ctx_free(ctx); return -1; } if (session->server) { rc = EC_POINT_oct2point(group, pubkey, ssh_string_data(session->next_crypto->ecdh_client_pubkey), ssh_string_len(session->next_crypto->ecdh_client_pubkey), ctx); } else { rc = EC_POINT_oct2point(group, pubkey, ssh_string_data(session->next_crypto->ecdh_server_pubkey), ssh_string_len(session->next_crypto->ecdh_server_pubkey), ctx); } bignum_ctx_free(ctx); if (rc <= 0) { EC_POINT_clear_free(pubkey); return -1; } buffer = malloc(len); if (buffer == NULL) { EC_POINT_clear_free(pubkey); return -1; } rc = ECDH_compute_key(buffer, len, pubkey, session->next_crypto->ecdh_privkey, NULL); EC_POINT_clear_free(pubkey); if (rc <= 0) { free(buffer); return -1; } bignum_bin2bn(buffer, len, &session->next_crypto->shared_secret); free(buffer); if (session->next_crypto->shared_secret == NULL) { EC_KEY_free(session->next_crypto->ecdh_privkey); session->next_crypto->ecdh_privkey = NULL; return -1; } EC_KEY_free(session->next_crypto->ecdh_privkey); session->next_crypto->ecdh_privkey = NULL; #ifdef DEBUG_CRYPTO ssh_log_hexdump("Session server cookie", session->next_crypto->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", session->next_crypto->client_kex.cookie, 16); ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret); #endif return 0; } #ifdef WITH_SERVER /** @brief Handle a SSH_MSG_KEXDH_INIT packet (server) and send a * SSH_MSG_KEXDH_REPLY */ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; EC_KEY *ecdh_key; const EC_GROUP *group; const EC_POINT *ecdh_pubkey; bignum_CTX ctx; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; ssh_string pubkey_blob = NULL; int curve; int len; int rc; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_ecdh_server_callbacks); /* Extract the client pubkey from the init packet */ q_c_string = ssh_buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); goto error; } session->next_crypto->ecdh_client_pubkey = q_c_string; /* Build server's keypair */ ctx = BN_CTX_new(); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == SSH_ERROR) { BN_CTX_free(ctx); return SSH_ERROR; } ecdh_key = EC_KEY_new_by_curve_name(curve); if (ecdh_key == NULL) { ssh_set_error_oom(session); BN_CTX_free(ctx); goto error; } group = EC_KEY_get0_group(ecdh_key); EC_KEY_generate_key(ecdh_key); ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key); len = EC_POINT_point2oct(group, ecdh_pubkey, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx); q_s_string = ssh_string_new(len); if (q_s_string == NULL) { EC_KEY_free(ecdh_key); BN_CTX_free(ctx); goto error; } EC_POINT_point2oct(group, ecdh_pubkey, POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(q_s_string), len, ctx); BN_CTX_free(ctx); session->next_crypto->ecdh_privkey = ecdh_key; session->next_crypto->ecdh_server_pubkey = q_s_string; /* build k and session_id */ rc = ecdh_build_k(session); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey, &digest); if (rc == SSH_ERROR) { goto error; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not export server public key"); SSH_STRING_FREE(sig_blob); return SSH_ERROR; } rc = ssh_buffer_pack(session->out_buffer, "bSSS", SSH2_MSG_KEXDH_REPLY, pubkey_blob, /* host's pubkey */ q_s_string, /* ecdh public key */ sig_blob); /* signature blob */ SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(pubkey_blob); if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = ssh_packet_send(session); if (rc == SSH_ERROR) { goto error; } /* Send the MSG_NEWKEYS */ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc < 0) { goto error; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = ssh_packet_send(session); if (rc == SSH_ERROR){ goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return SSH_PACKET_USED; error: ssh_buffer_reinit(session->out_buffer); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } #endif /* WITH_SERVER */ #endif /* HAVE_ECDH */ ================================================ FILE: src/libssh/src/ecdh_gcrypt.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2011-2013 by Aris Adamantiadis * Copyright (C) 2016 g10 Code GmbH * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/session.h" #include "libssh/ecdh.h" #include "libssh/dh.h" #include "libssh/buffer.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "libssh/libgcrypt.h" #ifdef HAVE_ECDH #include /** @internal * @brief Map the given key exchange enum value to its curve name. */ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { return "NIST P-256"; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { return "NIST P-384"; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { return "NIST P-521"; } return NULL; } /** @internal * @brief Starts ecdh-sha2-nistp{256,384,521} key exchange. */ int ssh_client_ecdh_init(ssh_session session) { int rc; gpg_error_t err; ssh_string client_pubkey = NULL; gcry_sexp_t param = NULL; gcry_sexp_t key = NULL; const char *curve = NULL; curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == NULL) { rc = SSH_ERROR; goto out; } rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { rc = SSH_ERROR; goto out; } err = gcry_sexp_build(¶m, NULL, "(genkey(ecdh(curve %s)))", curve); if (err) { rc = SSH_ERROR; goto out; } err = gcry_pk_genkey(&key, param); if (err) { rc = SSH_ERROR; goto out; } client_pubkey = ssh_sexp_extract_mpi(key, "q", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (client_pubkey == NULL) { rc = SSH_ERROR; goto out; } rc = ssh_buffer_add_ssh_string(session->out_buffer, client_pubkey); if (rc < 0) { rc = SSH_ERROR; goto out; } session->next_crypto->ecdh_privkey = key; key = NULL; session->next_crypto->ecdh_client_pubkey = client_pubkey; client_pubkey = NULL; /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); out: gcry_sexp_release(param); gcry_sexp_release(key); SSH_STRING_FREE(client_pubkey); return rc; } int ecdh_build_k(ssh_session session) { gpg_error_t err; gcry_sexp_t data = NULL; gcry_sexp_t result = NULL; /* We need to get the x coordinate. Libgcrypt 1.7 and above offers a suitable API for that. */ #if (GCRYPT_VERSION_NUMBER >= 0x010700) gcry_mpi_t s = NULL; gcry_mpi_point_t point; #else size_t k_len = 0; enum ssh_key_exchange_e kex_type = session->next_crypto->kex_type; ssh_string s; #endif ssh_string pubkey_raw; gcry_sexp_t pubkey = NULL; ssh_string privkey = NULL; int rc = SSH_ERROR; const char *curve = NULL; curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == NULL) { goto out; } pubkey_raw = session->server ? session->next_crypto->ecdh_client_pubkey : session->next_crypto->ecdh_server_pubkey; err = gcry_sexp_build(&pubkey, NULL, "(key-data(public-key(ecdh(curve %s)(q %b))))", curve, ssh_string_len(pubkey_raw), ssh_string_data(pubkey_raw)); if (err) { goto out; } privkey = ssh_sexp_extract_mpi(session->next_crypto->ecdh_privkey, "d", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (privkey == NULL) { goto out; } err = gcry_sexp_build(&data, NULL, "(data(flags raw)(value %b))", ssh_string_len(privkey), ssh_string_data(privkey)); if (err) { goto out; } err = gcry_pk_encrypt(&result, data, pubkey); if (err) { goto out; } #if (GCRYPT_VERSION_NUMBER >= 0x010700) err = gcry_sexp_extract_param(result, "", "s", &s, NULL); if (err) { goto out; } point = gcry_mpi_point_new(0); if (point == NULL) { gcry_mpi_release(s); goto out; } err = gcry_mpi_ec_decode_point(point, s, NULL); gcry_mpi_release(s); if (err) { goto out; } session->next_crypto->shared_secret = gcry_mpi_new(0); gcry_mpi_point_snatch_get(session->next_crypto->shared_secret, NULL, NULL, point); #else s = ssh_sexp_extract_mpi(result, "s", GCRYMPI_FMT_USG, GCRYMPI_FMT_USG); if (s == NULL) { goto out; } if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { k_len = 65; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { k_len = 97; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { k_len = 133; } else { ssh_string_burn(s); SSH_STRING_FREE(s); goto out; } if (ssh_string_len(s) != k_len) { ssh_string_burn(s); SSH_STRING_FREE(s); goto out; } err = gcry_mpi_scan(&session->next_crypto->shared_secret, GCRYMPI_FMT_USG, (const char *)ssh_string_data(s) + 1, k_len / 2, NULL); ssh_string_burn(s); SSH_STRING_FREE(s); if (err) { goto out; } #endif rc = SSH_OK; gcry_sexp_release(session->next_crypto->ecdh_privkey); session->next_crypto->ecdh_privkey = NULL; #ifdef DEBUG_CRYPTO ssh_log_hexdump("Session server cookie", session->next_crypto->server_kex.cookie, 16); ssh_log_hexdump("Session client cookie", session->next_crypto->client_kex.cookie, 16); ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret); #endif out: gcry_sexp_release(pubkey); gcry_sexp_release(data); gcry_sexp_release(result); ssh_string_burn(privkey); SSH_STRING_FREE(privkey); return rc; } #ifdef WITH_SERVER /** @brief Handle a SSH_MSG_KEXDH_INIT packet (server) and send a * SSH_MSG_KEXDH_REPLY */ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ gpg_error_t err; /* ECDH keys */ ssh_string q_c_string; ssh_string q_s_string; gcry_sexp_t param = NULL; gcry_sexp_t key = NULL; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; ssh_string pubkey_blob = NULL; int rc = SSH_ERROR; const char *curve = NULL; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_ecdh_server_callbacks); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == NULL) { goto out; } /* Extract the client pubkey from the init packet */ q_c_string = ssh_buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet"); goto out; } session->next_crypto->ecdh_client_pubkey = q_c_string; /* Build server's keypair */ err = gcry_sexp_build(¶m, NULL, "(genkey(ecdh(curve %s) (flags transient-key)))", curve); if (err) { goto out; } err = gcry_pk_genkey(&key, param); if (err) goto out; q_s_string = ssh_sexp_extract_mpi(key, "q", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (q_s_string == NULL) { goto out; } session->next_crypto->ecdh_privkey = key; key = NULL; session->next_crypto->ecdh_server_pubkey = q_s_string; /* build k and session_id */ rc = ecdh_build_k(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto out; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey, &digest); if (rc != SSH_OK) { goto out; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto out; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); rc = SSH_ERROR; goto out; } rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not export server public key"); SSH_STRING_FREE(sig_blob); goto out; } rc = ssh_buffer_pack(session->out_buffer, "bSSS", SSH2_MSG_KEXDH_REPLY, pubkey_blob, /* host's pubkey */ q_s_string, /* ecdh public key */ sig_blob); /* signature blob */ SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(pubkey_blob); if (rc != SSH_OK) { ssh_set_error_oom(session); goto out; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = ssh_packet_send(session); if (rc != SSH_OK) { goto out; } /* Send the MSG_NEWKEYS */ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc != SSH_OK) { goto out; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = ssh_packet_send(session); SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); out: gcry_sexp_release(param); gcry_sexp_release(key); if (rc == SSH_ERROR) { ssh_buffer_reinit(session->out_buffer); session->session_state = SSH_SESSION_STATE_ERROR; } return SSH_PACKET_USED; } #endif /* WITH_SERVER */ #endif /* HAVE_ECDH */ ================================================ FILE: src/libssh/src/ecdh_mbedcrypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2017 Sartura d.o.o. * * Author: Juraj Vijtiuk * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/session.h" #include "libssh/ecdh.h" #include "libssh/buffer.h" #include "libssh/ssh2.h" #include "libssh/dh.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "libssh/libmbedcrypto.h" #include #include #ifdef HAVE_ECDH static mbedtls_ecp_group_id ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { if (kex_type == SSH_KEX_ECDH_SHA2_NISTP256) { return MBEDTLS_ECP_DP_SECP256R1; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP384) { return MBEDTLS_ECP_DP_SECP384R1; } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { return MBEDTLS_ECP_DP_SECP521R1; } return MBEDTLS_ECP_DP_NONE; } int ssh_client_ecdh_init(ssh_session session) { ssh_string client_pubkey = NULL; mbedtls_ecp_group grp; int rc; mbedtls_ecp_group_id curve; curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == MBEDTLS_ECP_DP_NONE) { return SSH_ERROR; } rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); if (rc < 0) { return SSH_ERROR; } session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair)); if (session->next_crypto->ecdh_privkey == NULL) { return SSH_ERROR; } mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey); mbedtls_ecp_group_init(&grp); rc = mbedtls_ecp_group_load(&grp, curve); if (rc != 0) { rc = SSH_ERROR; goto out; } rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d, &session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (rc != 0) { rc = SSH_ERROR; goto out; } client_pubkey = make_ecpoint_string(&grp, &session->next_crypto->ecdh_privkey->Q); if (client_pubkey == NULL) { rc = SSH_ERROR; goto out; } rc = ssh_buffer_add_ssh_string(session->out_buffer, client_pubkey); if (rc < 0) { rc = SSH_ERROR; goto out; } session->next_crypto->ecdh_client_pubkey = client_pubkey; client_pubkey = NULL; /* register the packet callbacks */ ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); session->dh_handshake_state = DH_STATE_INIT_SENT; rc = ssh_packet_send(session); out: mbedtls_ecp_group_free(&grp); SSH_STRING_FREE(client_pubkey); return rc; } int ecdh_build_k(ssh_session session) { mbedtls_ecp_group grp; mbedtls_ecp_point pubkey; int rc; mbedtls_ecp_group_id curve; curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == MBEDTLS_ECP_DP_NONE) { return SSH_ERROR; } mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&pubkey); rc = mbedtls_ecp_group_load(&grp, curve); if (rc != 0) { rc = SSH_ERROR; goto out; } if (session->server) { rc = mbedtls_ecp_point_read_binary(&grp, &pubkey, ssh_string_data(session->next_crypto->ecdh_client_pubkey), ssh_string_len(session->next_crypto->ecdh_client_pubkey)); } else { rc = mbedtls_ecp_point_read_binary(&grp, &pubkey, ssh_string_data(session->next_crypto->ecdh_server_pubkey), ssh_string_len(session->next_crypto->ecdh_server_pubkey)); } if (rc != 0) { rc = SSH_ERROR; goto out; } session->next_crypto->shared_secret = malloc(sizeof(mbedtls_mpi)); if (session->next_crypto->shared_secret == NULL) { rc = SSH_ERROR; goto out; } mbedtls_mpi_init(session->next_crypto->shared_secret); rc = mbedtls_ecdh_compute_shared(&grp, session->next_crypto->shared_secret, &pubkey, &session->next_crypto->ecdh_privkey->d, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (rc != 0) { rc = SSH_ERROR; goto out; } out: mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey); SAFE_FREE(session->next_crypto->ecdh_privkey); mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&pubkey); return rc; } #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ ssh_string q_c_string = NULL; ssh_string q_s_string = NULL; mbedtls_ecp_group grp; ssh_key privkey = NULL; enum ssh_digest_e digest = SSH_DIGEST_AUTO; ssh_string sig_blob = NULL; ssh_string pubkey_blob = NULL; int rc; mbedtls_ecp_group_id curve; (void)type; (void)user; ssh_packet_remove_callbacks(session, &ssh_ecdh_server_callbacks); curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); if (curve == MBEDTLS_ECP_DP_NONE) { return SSH_ERROR; } q_c_string = ssh_buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet"); return SSH_ERROR; } session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair)); if (session->next_crypto->ecdh_privkey == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } session->next_crypto->ecdh_client_pubkey = q_c_string; mbedtls_ecp_group_init(&grp); mbedtls_ecp_keypair_init(session->next_crypto->ecdh_privkey); rc = mbedtls_ecp_group_load(&grp, curve); if (rc != 0) { rc = SSH_ERROR; goto out; } rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d, &session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (rc != 0) { rc = SSH_ERROR; goto out; } q_s_string = make_ecpoint_string(&grp, &session->next_crypto->ecdh_privkey->Q); if (q_s_string == NULL) { rc = SSH_ERROR; goto out; } session->next_crypto->ecdh_server_pubkey = q_s_string; /* build k and session_id */ rc = ecdh_build_k(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto out; } /* privkey is not allocated */ rc = ssh_get_key_params(session, &privkey, &digest); if (rc == SSH_ERROR) { rc = SSH_ERROR; goto out; } rc = ssh_make_sessionid(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); rc = SSH_ERROR; goto out; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); rc = SSH_ERROR; goto out; } rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not export server public key"); SSH_STRING_FREE(sig_blob); goto out; } rc = ssh_buffer_pack(session->out_buffer, "bSSS", SSH2_MSG_KEXDH_REPLY, pubkey_blob, /* host's pubkey */ q_s_string, /* ecdh public key */ sig_blob); /* signature blob */ SSH_STRING_FREE(sig_blob); SSH_STRING_FREE(pubkey_blob); if (rc != SSH_OK) { ssh_set_error_oom(session); rc = SSH_ERROR; goto out; } SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = ssh_packet_send(session); if (rc != SSH_OK) { rc = SSH_ERROR; goto out; } rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); if (rc < 0) { rc = SSH_ERROR; goto out; } session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; rc = ssh_packet_send(session); SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); out: mbedtls_ecp_group_free(&grp); if (rc == SSH_ERROR) { ssh_buffer_reinit(session->out_buffer); session->session_state = SSH_SESSION_STATE_ERROR; } return SSH_PACKET_USED; } #endif /* WITH_SERVER */ #endif ================================================ FILE: src/libssh/src/error.c ================================================ /* * error.c - functions for ssh error handling * * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include "libssh/priv.h" #include "libssh/session.h" /** * @defgroup libssh_error The SSH error functions. * @ingroup libssh * * Functions for error handling. * * @{ */ /** * @internal * * @brief Registers an error with a description. * * @param error The place to store the error. * * @param code The class of error. * * @param descr The description, which can be a format string. * * @param ... The arguments for the format string. */ void _ssh_set_error(void *error, int code, const char *function, const char *descr, ...) { struct ssh_common_struct *err = error; va_list va; va_start(va, descr); vsnprintf(err->error.error_buffer, ERROR_BUFFERLEN, descr, va); va_end(va); err->error.error_code = code; if (ssh_get_log_level() >= SSH_LOG_WARN) { ssh_log_function(SSH_LOG_WARN, function, err->error.error_buffer); } } /** * @internal * * @brief Registers an out of memory error * * @param error The place to store the error. * */ void _ssh_set_error_oom(void *error, const char *function) { struct error_struct *err = error; snprintf(err->error_buffer, sizeof(err->error_buffer), "%s: Out of memory", function); err->error_code = SSH_FATAL; } /** * @internal * * @brief Registers an invalid argument error * * @param error The place to store the error. * * @param function The function the error happened in. * */ void _ssh_set_error_invalid(void *error, const char *function) { _ssh_set_error(error, SSH_FATAL, function, "Invalid argument in %s", function); } /** * @internal * * @brief Reset the error code and message * * @param error The place to reset the error. */ void ssh_reset_error(void *error) { struct ssh_common_struct *err = error; ZERO_STRUCT(err->error.error_buffer); err->error.error_code = 0; } /** * @brief Retrieve the error text message from the last error. * * @param error An ssh_session or ssh_bind. * * @return A static string describing the error. */ const char *ssh_get_error(void *error) { struct error_struct *err = error; return err->error_buffer; } /** * @brief Retrieve the error code from the last error. * * @param error An ssh_session or ssh_bind. * * \return SSH_NO_ERROR No error occurred\n * SSH_REQUEST_DENIED The last request was denied but situation is * recoverable\n * SSH_FATAL A fatal error occurred. This could be an unexpected * disconnection\n * * Other error codes are internal but can be considered same than * SSH_FATAL. */ int ssh_get_error_code(void *error) { struct error_struct *err = error; return err->error_code; } /** @} */ ================================================ FILE: src/libssh/src/external/bcrypt_pbkdf.c ================================================ /* $OpenBSD: bcrypt_pbkdf.c,v 1.4 2013/07/29 00:55:53 tedu Exp $ */ /* * Copyright (c) 2013 Ted Unangst * * 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. */ //#include "includes.h" #ifndef HAVE_BCRYPT_PBKDF #include "config.h" #include "libssh/priv.h" #include "libssh/wrapper.h" #include #include #ifdef HAVE_SYS_PARAM_H #include #endif #include "libssh/blf.h" #include "libssh/pki_priv.h" #ifndef SHA512_DIGEST_LENGTH #define SHA512_DIGEST_LENGTH SHA512_DIGEST_LEN #endif /* * pkcs #5 pbkdf2 implementation using the "bcrypt" hash * * The bcrypt hash function is derived from the bcrypt password hashing * function with the following modifications: * 1. The input password and salt are preprocessed with SHA512. * 2. The output length is expanded to 256 bits. * 3. Subsequently the magic string to be encrypted is lengthened and modifed * to "OxychromaticBlowfishSwatDynamite" * 4. The hash function is defined to perform 64 rounds of initial state * expansion. (More rounds are performed by iterating the hash.) * * Note that this implementation pulls the SHA512 operations into the caller * as a performance optimization. * * One modification from official pbkdf2. Instead of outputting key material * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to * generate (i.e.) 512 bits of key material for use as two 256 bit keys, an * attacker can merely run once through the outer loop below, but the user * always runs it twice. Shuffling output bytes requires computing the * entirety of the key material to assemble any subkey. This is something a * wise caller could do; we just do it for you. */ #define BCRYPT_BLOCKS 8 #define BCRYPT_HASHSIZE (BCRYPT_BLOCKS * 4) static void bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out) { ssh_blf_ctx state; uint8_t ciphertext[BCRYPT_HASHSIZE] = "OxychromaticBlowfishSwatDynamite"; uint32_t cdata[BCRYPT_BLOCKS]; int i; uint16_t j; uint16_t shalen = SHA512_DIGEST_LENGTH; /* key expansion */ Blowfish_initstate(&state); Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen); for (i = 0; i < 64; i++) { Blowfish_expand0state(&state, sha2salt, shalen); Blowfish_expand0state(&state, sha2pass, shalen); } /* encryption */ j = 0; for (i = 0; i < BCRYPT_BLOCKS; i++) cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext), &j); for (i = 0; i < 64; i++) ssh_blf_enc(&state, cdata, BCRYPT_BLOCKS/2); /* copy out */ for (i = 0; i < BCRYPT_BLOCKS; i++) { out[4 * i + 3] = (cdata[i] >> 24) & 0xff; out[4 * i + 2] = (cdata[i] >> 16) & 0xff; out[4 * i + 1] = (cdata[i] >> 8) & 0xff; out[4 * i + 0] = cdata[i] & 0xff; } /* zap */ explicit_bzero(ciphertext, sizeof(ciphertext)); explicit_bzero(cdata, sizeof(cdata)); ZERO_STRUCT(state); } int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen, uint8_t *key, size_t keylen, unsigned int rounds) { uint8_t sha2pass[SHA512_DIGEST_LENGTH]; uint8_t sha2salt[SHA512_DIGEST_LENGTH]; uint8_t out[BCRYPT_HASHSIZE]; uint8_t tmpout[BCRYPT_HASHSIZE]; uint8_t *countsalt; size_t i, j, amt, stride; uint32_t count; size_t origkeylen = keylen; SHA512CTX ctx; /* nothing crazy */ if (rounds < 1) return -1; if (passlen == 0 || saltlen == 0 || keylen == 0 || keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20) return -1; if ((countsalt = calloc(1, saltlen + 4)) == NULL) return -1; stride = (keylen + sizeof(out) - 1) / sizeof(out); amt = (keylen + stride - 1) / stride; memcpy(countsalt, salt, saltlen); /* collapse password */ ctx = sha512_init(); sha512_update(ctx, pass, passlen); sha512_final(sha2pass, ctx); /* generate key, sizeof(out) at a time */ for (count = 1; keylen > 0; count++) { countsalt[saltlen + 0] = (count >> 24) & 0xff; countsalt[saltlen + 1] = (count >> 16) & 0xff; countsalt[saltlen + 2] = (count >> 8) & 0xff; countsalt[saltlen + 3] = count & 0xff; /* first round, salt is salt */ ctx = sha512_init(); sha512_update(ctx, countsalt, saltlen + 4); sha512_final(sha2salt, ctx); bcrypt_hash(sha2pass, sha2salt, tmpout); memcpy(out, tmpout, sizeof(out)); for (i = 1; i < rounds; i++) { /* subsequent rounds, salt is previous output */ ctx = sha512_init(); sha512_update(ctx, tmpout, sizeof(tmpout)); sha512_final(sha2salt, ctx); bcrypt_hash(sha2pass, sha2salt, tmpout); for (j = 0; j < sizeof(out); j++) out[j] ^= tmpout[j]; } /* * pbkdf2 deviation: ouput the key material non-linearly. */ amt = MIN(amt, keylen); for (i = 0; i < amt; i++) { size_t dest = i * stride + (count - 1); if (dest >= origkeylen) { break; } key[dest] = out[i]; } keylen -= i; } /* zap */ explicit_bzero(out, sizeof(out)); free(countsalt); return 0; } #endif /* HAVE_BCRYPT_PBKDF */ ================================================ FILE: src/libssh/src/external/blowfish.c ================================================ /* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */ /* * Blowfish block cipher for OpenBSD * Copyright 1997 Niels Provos * All rights reserved. * * Implementation advice by David Mazieres . * * 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 Niels Provos. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. */ /* * This code is derived from section 14.3 and the given source * in section V of Applied Cryptography, second edition. * Blowfish is an unpatented fast block cipher designed by * Bruce Schneier. */ #if !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \ !defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC)) #if 0 #include /* used for debugging */ #include #endif #include #include #include "libssh/blf.h" #undef inline #ifdef __GNUC__ #define inline __inline #else /* !__GNUC__ */ #define inline #endif /* !__GNUC__ */ /* Function for Feistel Networks */ #define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \ + (s)[0x100 + (((x)>>16)&0xFF)]) \ ^ (s)[0x200 + (((x)>> 8)&0xFF)]) \ + (s)[0x300 + ( (x) &0xFF)]) #define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n]) void Blowfish_encipher(ssh_blf_ctx *c, uint32_t *xl, uint32_t *xr) { uint32_t Xl; uint32_t Xr; uint32_t *s = c->S[0]; uint32_t *p = c->P; Xl = *xl; Xr = *xr; Xl ^= p[0]; BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2); BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4); BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6); BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8); BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10); BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12); BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14); BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16); *xl = Xr ^ p[17]; *xr = Xl; } void Blowfish_decipher(ssh_blf_ctx *c, uint32_t *xl, uint32_t *xr) { uint32_t Xl; uint32_t Xr; uint32_t *s = c->S[0]; uint32_t *p = c->P; Xl = *xl; Xr = *xr; Xl ^= p[17]; BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15); BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13); BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11); BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9); BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7); BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5); BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3); BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1); *xl = Xr ^ p[0]; *xr = Xl; } void Blowfish_initstate(ssh_blf_ctx *c) { /* P-box and S-box tables initialized with digits of Pi */ static const ssh_blf_ctx initstate = { { { 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a}, { 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}, { 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}, { 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6} }, { 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b } }; *c = initstate; } uint32_t Blowfish_stream2word(const uint8_t *data, uint16_t databytes, uint16_t *current) { uint8_t i; uint16_t j; uint32_t temp; temp = 0x00000000; j = *current; for (i = 0; i < 4; i++, j++) { if (j >= databytes) j = 0; temp = (temp << 8) | data[j]; } *current = j; return temp; } void Blowfish_expand0state(ssh_blf_ctx *c, const uint8_t *key, uint16_t keybytes) { uint16_t i; uint16_t j; uint16_t k; uint32_t temp; uint32_t datal; uint32_t datar; j = 0; for (i = 0; i < BLF_N + 2; i++) { /* Extract 4 int8 to 1 int32 from keystream */ temp = Blowfish_stream2word(key, keybytes, &j); c->P[i] = c->P[i] ^ temp; } j = 0; datal = 0x00000000; datar = 0x00000000; for (i = 0; i < BLF_N + 2; i += 2) { Blowfish_encipher(c, &datal, &datar); c->P[i] = datal; c->P[i + 1] = datar; } for (i = 0; i < 4; i++) { for (k = 0; k < 256; k += 2) { Blowfish_encipher(c, &datal, &datar); c->S[i][k] = datal; c->S[i][k + 1] = datar; } } } void Blowfish_expandstate(ssh_blf_ctx *c, const uint8_t *data, uint16_t databytes, const uint8_t *key, uint16_t keybytes) { uint16_t i; uint16_t j; uint16_t k; uint32_t temp; uint32_t datal; uint32_t datar; j = 0; for (i = 0; i < BLF_N + 2; i++) { /* Extract 4 int8 to 1 int32 from keystream */ temp = Blowfish_stream2word(key, keybytes, &j); c->P[i] = c->P[i] ^ temp; } j = 0; datal = 0x00000000; datar = 0x00000000; for (i = 0; i < BLF_N + 2; i += 2) { datal ^= Blowfish_stream2word(data, databytes, &j); datar ^= Blowfish_stream2word(data, databytes, &j); Blowfish_encipher(c, &datal, &datar); c->P[i] = datal; c->P[i + 1] = datar; } for (i = 0; i < 4; i++) { for (k = 0; k < 256; k += 2) { datal ^= Blowfish_stream2word(data, databytes, &j); datar ^= Blowfish_stream2word(data, databytes, &j); Blowfish_encipher(c, &datal, &datar); c->S[i][k] = datal; c->S[i][k + 1] = datar; } } } void ssh_blf_key(ssh_blf_ctx *c, const uint8_t *k, uint16_t len) { /* Initialize S-boxes and subkeys with Pi */ Blowfish_initstate(c); /* Transform S-boxes and subkeys with key */ Blowfish_expand0state(c, k, len); } void ssh_blf_enc(ssh_blf_ctx *c, uint32_t *data, uint16_t blocks) { uint32_t *d; uint16_t i; d = data; for (i = 0; i < blocks; i++) { Blowfish_encipher(c, d, d + 1); d += 2; } } void ssh_blf_dec(ssh_blf_ctx *c, uint32_t *data, uint16_t blocks) { uint32_t *d; uint16_t i; d = data; for (i = 0; i < blocks; i++) { Blowfish_decipher(c, d, d + 1); d += 2; } } void ssh_blf_ecb_encrypt(ssh_blf_ctx *c, uint8_t *data, uint32_t len) { uint32_t l, r; uint32_t i; for (i = 0; i < len; i += 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_encipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; data += 8; } } void ssh_blf_ecb_decrypt(ssh_blf_ctx *c, uint8_t *data, uint32_t len) { uint32_t l, r; uint32_t i; for (i = 0; i < len; i += 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; data += 8; } } void ssh_blf_cbc_encrypt(ssh_blf_ctx *c, uint8_t *iv, uint8_t *data, uint32_t len) { uint32_t l, r; uint32_t i, j; for (i = 0; i < len; i += 8) { for (j = 0; j < 8; j++) data[j] ^= iv[j]; l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_encipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; iv = data; data += 8; } } void ssh_blf_cbc_decrypt(ssh_blf_ctx *c, uint8_t *iva, uint8_t *data, uint32_t len) { uint32_t l, r; uint8_t *iv; uint32_t i, j; iv = data + len - 16; data = data + len - 8; for (i = len - 8; i >= 8; i -= 8) { l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; for (j = 0; j < 8; j++) data[j] ^= iv[j]; iv -= 8; data -= 8; } l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]; Blowfish_decipher(c, &l, &r); data[0] = l >> 24 & 0xff; data[1] = l >> 16 & 0xff; data[2] = l >> 8 & 0xff; data[3] = l & 0xff; data[4] = r >> 24 & 0xff; data[5] = r >> 16 & 0xff; data[6] = r >> 8 & 0xff; data[7] = r & 0xff; for (j = 0; j < 8; j++) data[j] ^= iva[j]; } #if 0 void report(uint32_t data[], uint16_t len) { uint16_t i; for (i = 0; i < len; i += 2) printf("Block %0hd: %08lx %08lx.\n", i / 2, data[i], data[i + 1]); } void main(void) { ssh_blf_ctx c; char key[] = "AAAAA"; char key2[] = "abcdefghijklmnopqrstuvwxyz"; uint32_t data[10]; uint32_t data2[] = {0x424c4f57l, 0x46495348l}; uint16_t i; /* First test */ for (i = 0; i < 10; i++) data[i] = i; ssh_blf_key(&c, (uint8_t *) key, 5); ssh_blf_enc(&c, data, 5); ssh_blf_dec(&c, data, 1); ssh_blf_dec(&c, data + 2, 4); printf("Should read as 0 - 9.\n"); report(data, 10); /* Second test */ ssh_blf_key(&c, (uint8_t *) key2, strlen(key2)); ssh_blf_enc(&c, data2, 1); printf("\nShould read as: 0x324ed0fe 0xf413a203.\n"); report(data2, 2); ssh_blf_dec(&c, data2, 1); report(data2, 2); } #endif #endif /* !defined(HAVE_BCRYPT_PBKDF) && (!defined(HAVE_BLOWFISH_INITSTATE) || \ !defined(HAVE_BLOWFISH_EXPAND0STATE) || !defined(HAVE_BLF_ENC)) */ ================================================ FILE: src/libssh/src/external/chacha.c ================================================ /* chacha-merged.c version 20080118 D. J. Bernstein Public domain. */ #include #include #include #include "libssh/chacha.h" typedef struct chacha_ctx chacha_ctx; #define U8C(v) (v##U) #define U32C(v) (v##U) #define U8V(v) ((uint8_t)(v) & U8C(0xFF)) #define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF)) #define ROTL32(v, n) \ (U32V((v) << (n)) | ((v) >> (32 - (n)))) #define U8TO32_LITTLE(p) \ (((uint32_t)((p)[0]) ) | \ ((uint32_t)((p)[1]) << 8) | \ ((uint32_t)((p)[2]) << 16) | \ ((uint32_t)((p)[3]) << 24)) #define U32TO8_LITTLE(p, v) \ do { \ (p)[0] = U8V((v) ); \ (p)[1] = U8V((v) >> 8); \ (p)[2] = U8V((v) >> 16); \ (p)[3] = U8V((v) >> 24); \ } while (0) #define ROTATE(v,c) (ROTL32(v,c)) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) (U32V((v) + (w))) #define PLUSONE(v) (PLUS((v),1)) #define QUARTERROUND(a,b,c,d) \ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); static const char sigma[16] = "expand 32-byte k"; static const char tau[16] = "expand 16-byte k"; void chacha_keysetup(chacha_ctx *x,const uint8_t *k,uint32_t kbits) { const char *constants; x->input[4] = U8TO32_LITTLE(k + 0); x->input[5] = U8TO32_LITTLE(k + 4); x->input[6] = U8TO32_LITTLE(k + 8); x->input[7] = U8TO32_LITTLE(k + 12); if (kbits == 256) { /* recommended */ k += 16; constants = sigma; } else { /* kbits == 128 */ constants = tau; } x->input[8] = U8TO32_LITTLE(k + 0); x->input[9] = U8TO32_LITTLE(k + 4); x->input[10] = U8TO32_LITTLE(k + 8); x->input[11] = U8TO32_LITTLE(k + 12); x->input[0] = U8TO32_LITTLE(constants + 0); x->input[1] = U8TO32_LITTLE(constants + 4); x->input[2] = U8TO32_LITTLE(constants + 8); x->input[3] = U8TO32_LITTLE(constants + 12); } void chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter) { x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); x->input[14] = U8TO32_LITTLE(iv + 0); x->input[15] = U8TO32_LITTLE(iv + 4); } void chacha_encrypt_bytes(chacha_ctx *x,const uint8_t *m,uint8_t *c,uint32_t bytes) { uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; uint8_t *ctarget = NULL; uint8_t tmp[64]; uint32_t i; if (!bytes) return; j0 = x->input[0]; j1 = x->input[1]; j2 = x->input[2]; j3 = x->input[3]; j4 = x->input[4]; j5 = x->input[5]; j6 = x->input[6]; j7 = x->input[7]; j8 = x->input[8]; j9 = x->input[9]; j10 = x->input[10]; j11 = x->input[11]; j12 = x->input[12]; j13 = x->input[13]; j14 = x->input[14]; j15 = x->input[15]; for (;;) { if (bytes < 64) { for (i = 0;i < bytes;++i) tmp[i] = m[i]; m = tmp; ctarget = c; c = tmp; } x0 = j0; x1 = j1; x2 = j2; x3 = j3; x4 = j4; x5 = j5; x6 = j6; x7 = j7; x8 = j8; x9 = j9; x10 = j10; x11 = j11; x12 = j12; x13 = j13; x14 = j14; x15 = j15; for (i = 20;i > 0;i -= 2) { QUARTERROUND( x0, x4, x8,x12) QUARTERROUND( x1, x5, x9,x13) QUARTERROUND( x2, x6,x10,x14) QUARTERROUND( x3, x7,x11,x15) QUARTERROUND( x0, x5,x10,x15) QUARTERROUND( x1, x6,x11,x12) QUARTERROUND( x2, x7, x8,x13) QUARTERROUND( x3, x4, x9,x14) } x0 = PLUS(x0,j0); x1 = PLUS(x1,j1); x2 = PLUS(x2,j2); x3 = PLUS(x3,j3); x4 = PLUS(x4,j4); x5 = PLUS(x5,j5); x6 = PLUS(x6,j6); x7 = PLUS(x7,j7); x8 = PLUS(x8,j8); x9 = PLUS(x9,j9); x10 = PLUS(x10,j10); x11 = PLUS(x11,j11); x12 = PLUS(x12,j12); x13 = PLUS(x13,j13); x14 = PLUS(x14,j14); x15 = PLUS(x15,j15); x0 = XOR(x0,U8TO32_LITTLE(m + 0)); x1 = XOR(x1,U8TO32_LITTLE(m + 4)); x2 = XOR(x2,U8TO32_LITTLE(m + 8)); x3 = XOR(x3,U8TO32_LITTLE(m + 12)); x4 = XOR(x4,U8TO32_LITTLE(m + 16)); x5 = XOR(x5,U8TO32_LITTLE(m + 20)); x6 = XOR(x6,U8TO32_LITTLE(m + 24)); x7 = XOR(x7,U8TO32_LITTLE(m + 28)); x8 = XOR(x8,U8TO32_LITTLE(m + 32)); x9 = XOR(x9,U8TO32_LITTLE(m + 36)); x10 = XOR(x10,U8TO32_LITTLE(m + 40)); x11 = XOR(x11,U8TO32_LITTLE(m + 44)); x12 = XOR(x12,U8TO32_LITTLE(m + 48)); x13 = XOR(x13,U8TO32_LITTLE(m + 52)); x14 = XOR(x14,U8TO32_LITTLE(m + 56)); x15 = XOR(x15,U8TO32_LITTLE(m + 60)); j12 = PLUSONE(j12); if (!j12) { j13 = PLUSONE(j13); /* stopping at 2^70 bytes per nonce is user's responsibility */ } U32TO8_LITTLE(c + 0,x0); U32TO8_LITTLE(c + 4,x1); U32TO8_LITTLE(c + 8,x2); U32TO8_LITTLE(c + 12,x3); U32TO8_LITTLE(c + 16,x4); U32TO8_LITTLE(c + 20,x5); U32TO8_LITTLE(c + 24,x6); U32TO8_LITTLE(c + 28,x7); U32TO8_LITTLE(c + 32,x8); U32TO8_LITTLE(c + 36,x9); U32TO8_LITTLE(c + 40,x10); U32TO8_LITTLE(c + 44,x11); U32TO8_LITTLE(c + 48,x12); U32TO8_LITTLE(c + 52,x13); U32TO8_LITTLE(c + 56,x14); U32TO8_LITTLE(c + 60,x15); if (bytes <= 64) { if (bytes < 64) { for (i = 0;i < bytes;++i) ctarget[i] = c[i]; } x->input[12] = j12; x->input[13] = j13; return; } bytes -= 64; c += 64; m += 64; } } ================================================ FILE: src/libssh/src/external/curve25519_ref.c ================================================ /* version 20081011 Matthew Dempsky Public domain. Derived from public domain code by D. J. Bernstein. */ #include "libssh/curve25519.h" static const unsigned char base[32] = {9}; int crypto_scalarmult_base(unsigned char *q, const unsigned char *n) { return crypto_scalarmult(q,n,base); } static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } u += a[31] + b[31]; out[31] = u; } static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int j; unsigned int u; u = 218; for (j = 0;j < 31;++j) { u += a[j] + 65280 - b[j]; out[j] = u & 255; u >>= 8; } u += a[31] - b[31]; out[31] = u; } static void squeeze(unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u & 127; u = 19 * (u >> 7); for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } u += a[31]; a[31] = u; } static const unsigned int minusp[32] = { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128 } ; static void freeze(unsigned int a[32]) { unsigned int aorig[32]; unsigned int j; unsigned int negative; for (j = 0;j < 32;++j) aorig[j] = a[j]; add(a,a,minusp); negative = -((a[31] >> 7) & 1); for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); } static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) { unsigned int i; unsigned int j; unsigned int u; for (i = 0;i < 32;++i) { u = 0; for (j = 0;j <= i;++j) u += a[j] * b[i - j]; for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; out[i] = u; } squeeze(out); } static void mult121665(unsigned int out[32],const unsigned int a[32]) { unsigned int j; unsigned int u; u = 0; for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } u += 121665 * a[31]; out[31] = u & 127; u = 19 * (u >> 7); for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } u += out[j]; out[j] = u; } static void square(unsigned int out[32],const unsigned int a[32]) { unsigned int i; unsigned int j; unsigned int u; for (i = 0;i < 32;++i) { u = 0; for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; u *= 2; if ((i & 1) == 0) { u += a[i / 2] * a[i / 2]; u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; } out[i] = u; } squeeze(out); } static void c_select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) { unsigned int j; unsigned int t; unsigned int bminus1; bminus1 = b - 1; for (j = 0;j < 64;++j) { t = bminus1 & (r[j] ^ s[j]); p[j] = s[j] ^ t; q[j] = r[j] ^ t; } } static void mainloop(unsigned int work[64],const unsigned char e[32]) { unsigned int xzm1[64]; unsigned int xzm[64]; unsigned int xzmb[64]; unsigned int xzm1b[64]; unsigned int xznb[64]; unsigned int xzn1b[64]; unsigned int a0[64]; unsigned int a1[64]; unsigned int b0[64]; unsigned int b1[64]; unsigned int c1[64]; unsigned int r[32]; unsigned int s[32]; unsigned int t[32]; unsigned int u[32]; unsigned int j; unsigned int b; int pos; for (j = 0;j < 32;++j) xzm1[j] = work[j]; xzm1[32] = 1; for (j = 33;j < 64;++j) xzm1[j] = 0; xzm[0] = 1; for (j = 1;j < 64;++j) xzm[j] = 0; for (pos = 254;pos >= 0;--pos) { b = e[pos / 8] >> (pos & 7); b &= 1; c_select(xzmb,xzm1b,xzm,xzm1,b); add(a0,xzmb,xzmb + 32); sub(a0 + 32,xzmb,xzmb + 32); add(a1,xzm1b,xzm1b + 32); sub(a1 + 32,xzm1b,xzm1b + 32); square(b0,a0); square(b0 + 32,a0 + 32); mult(b1,a1,a0 + 32); mult(b1 + 32,a1 + 32,a0); add(c1,b1,b1 + 32); sub(c1 + 32,b1,b1 + 32); square(r,c1 + 32); sub(s,b0,b0 + 32); mult121665(t,s); add(u,t,b0); mult(xznb,b0,b0 + 32); mult(xznb + 32,s,u); square(xzn1b,c1); mult(xzn1b + 32,r,work); c_select(xzm,xzm1,xznb,xzn1b,b); } for (j = 0;j < 64;++j) work[j] = xzm[j]; } static void recip(unsigned int out[32],const unsigned int z[32]) { unsigned int z2[32]; unsigned int z9[32]; unsigned int z11[32]; unsigned int z2_5_0[32]; unsigned int z2_10_0[32]; unsigned int z2_20_0[32]; unsigned int z2_50_0[32]; unsigned int z2_100_0[32]; unsigned int t0[32]; unsigned int t1[32]; int i; /* 2 */ square(z2,z); /* 4 */ square(t1,z2); /* 8 */ square(t0,t1); /* 9 */ mult(z9,t0,z); /* 11 */ mult(z11,z9,z2); /* 22 */ square(t0,z11); /* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); /* 2^6 - 2^1 */ square(t0,z2_5_0); /* 2^7 - 2^2 */ square(t1,t0); /* 2^8 - 2^3 */ square(t0,t1); /* 2^9 - 2^4 */ square(t1,t0); /* 2^10 - 2^5 */ square(t0,t1); /* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); /* 2^11 - 2^1 */ square(t0,z2_10_0); /* 2^12 - 2^2 */ square(t1,t0); /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } /* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); /* 2^21 - 2^1 */ square(t0,z2_20_0); /* 2^22 - 2^2 */ square(t1,t0); /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } /* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); /* 2^41 - 2^1 */ square(t1,t0); /* 2^42 - 2^2 */ square(t0,t1); /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } /* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); /* 2^51 - 2^1 */ square(t0,z2_50_0); /* 2^52 - 2^2 */ square(t1,t0); /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } /* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); /* 2^101 - 2^1 */ square(t1,z2_100_0); /* 2^102 - 2^2 */ square(t0,t1); /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } /* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); /* 2^201 - 2^1 */ square(t0,t1); /* 2^202 - 2^2 */ square(t1,t0); /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } /* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); /* 2^251 - 2^1 */ square(t1,t0); /* 2^252 - 2^2 */ square(t0,t1); /* 2^253 - 2^3 */ square(t1,t0); /* 2^254 - 2^4 */ square(t0,t1); /* 2^255 - 2^5 */ square(t1,t0); /* 2^255 - 21 */ mult(out,t1,z11); } int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p) { unsigned int work[96]; unsigned char e[32]; unsigned int i; for (i = 0;i < 32;++i) e[i] = n[i]; e[0] &= 248; e[31] &= 127; e[31] |= 64; for (i = 0;i < 32;++i) work[i] = p[i]; mainloop(work,e); recip(work + 32,work + 32); mult(work + 64,work,work + 32); freeze(work + 64); for (i = 0;i < 32;++i) q[i] = work[64 + i]; return 0; } ================================================ FILE: src/libssh/src/external/ed25519.c ================================================ /* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c */ #include "config.h" #include "libssh/libcrypto.h" #include "libssh/wrapper.h" #include "libssh/ge25519.h" #include "libssh/sc25519.h" #include "libssh/ed25519.h" /* * Public Domain, Author: Daniel J. Bernstein * Copied from nacl-20110221/crypto_verify/32/ref/verify.c */ static int crypto_verify_32(const unsigned char *x,const unsigned char *y) { unsigned int differentbits = 0; #define F(i) differentbits |= x[i] ^ y[i]; F(0) F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8) F(9) F(10) F(11) F(12) F(13) F(14) F(15) F(16) F(17) F(18) F(19) F(20) F(21) F(22) F(23) F(24) F(25) F(26) F(27) F(28) F(29) F(30) F(31) return (1 & ((differentbits - 1) >> 8)) - 1; } static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, uint64_t smlen) { uint64_t i; SHA512CTX ctx; for (i = 0;i < 32;++i) playground[i] = sm[i]; for (i = 32;i < 64;++i) playground[i] = pk[i-32]; for (i = 64;i < smlen;++i) playground[i] = sm[i]; ctx = sha512_init(); sha512_update(ctx, playground, smlen); sha512_final(hram, ctx); } int crypto_sign_ed25519_keypair(unsigned char *pk, unsigned char *sk) { sc25519 scsk; ge25519 gepk; SHA512CTX ctx; unsigned char extsk[64]; int i; int ok; ok = ssh_get_random(sk, 32, 0); if (!ok) { return -1; } ctx = sha512_init(); sha512_update(ctx, sk, 32); sha512_final(extsk, ctx); extsk[0] &= 248; extsk[31] &= 127; extsk[31] |= 64; sc25519_from32bytes(&scsk,extsk); ge25519_scalarmult_base(&gepk, &scsk); ge25519_pack(pk, &gepk); for(i=0;i<32;i++) { sk[32 + i] = pk[i]; } return 0; } int crypto_sign_ed25519(unsigned char *sm, uint64_t *smlen, const unsigned char *m, uint64_t mlen, const unsigned char *sk) { sc25519 sck, scs, scsk; ge25519 ger; SHA512CTX ctx; unsigned char r[32]; unsigned char s[32]; unsigned char extsk[64]; uint64_t i; unsigned char hmg[SHA512_DIGEST_LEN]; unsigned char hram[SHA512_DIGEST_LEN]; ctx = sha512_init(); sha512_update(ctx, sk, 32); sha512_final(extsk, ctx); extsk[0] &= 248; extsk[31] &= 127; extsk[31] |= 64; *smlen = mlen + 64; for (i = 0;i < mlen; i++) { sm[64 + i] = m[i]; } for (i = 0;i < 32; i++) { sm[32 + i] = extsk[32+i]; } /* Generate k as h(extsk[32],...,extsk[63],m) */ ctx = sha512_init(); sha512_update(ctx, sm + 32, mlen + 32); sha512_final(hmg, ctx); /* Computation of R */ sc25519_from64bytes(&sck, hmg); ge25519_scalarmult_base(&ger, &sck); ge25519_pack(r, &ger); /* Computation of s */ for (i = 0; i < 32; i++) { sm[i] = r[i]; } get_hram(hram, sm, sk+32, sm, mlen+64); sc25519_from64bytes(&scs, hram); sc25519_from32bytes(&scsk, extsk); sc25519_mul(&scs, &scs, &scsk); sc25519_add(&scs, &scs, &sck); sc25519_to32bytes(s,&scs); /* cat s */ for (i = 0;i < 32; i++) { sm[32 + i] = s[i]; } return 0; } int crypto_sign_ed25519_open(unsigned char *m, uint64_t *mlen, const unsigned char *sm, uint64_t smlen, const unsigned char *pk) { unsigned int i; int ret; unsigned char t2[32]; ge25519 get1, get2; sc25519 schram, scs; unsigned char hram[SHA512_DIGEST_LEN]; *mlen = (uint64_t) -1; if (smlen < 64) return -1; if (ge25519_unpackneg_vartime(&get1, pk)) { return -1; } get_hram(hram,sm,pk,m,smlen); sc25519_from64bytes(&schram, hram); sc25519_from32bytes(&scs, sm+32); ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); ge25519_pack(t2, &get2); ret = crypto_verify_32(sm, t2); if (ret != 0) { for (i = 0; i < smlen - 64; i++) { m[i] = sm[i + 64]; } *mlen = smlen-64; } else { for (i = 0; i < smlen - 64; i++) { m[i] = 0; } } return ret; } ================================================ FILE: src/libssh/src/external/fe25519.c ================================================ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.c */ #include "config.h" #define WINDOWSIZE 1 /* Should be 1,2, or 4 */ #define WINDOWMASK ((1<>= 31; /* 1: yes; 0: no */ return x; } static uint32_t ge(uint32_t a,uint32_t b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */ x >>= 31; /* 0: yes; 1: no */ x ^= 1; /* 1: yes; 0: no */ return x; } static uint32_t times19(uint32_t a) { return (a << 4) + (a << 1) + a; } static uint32_t times38(uint32_t a) { return (a << 5) + (a << 2) + (a << 1); } static void reduce_add_sub(fe25519 *r) { uint32_t t; int i,rep; for(rep = 0; rep < 4; rep++) { t = r->v[31] >> 7; r->v[31] &= 127; t = times19(t); r->v[0] += t; for(i = 0; i < 31; i++) { t = r->v[i] >> 8; r->v[i+1] += t; r->v[i] &= 255; } } } static void reduce_mul(fe25519 *r) { uint32_t t; int i,rep; for(rep = 0; rep < 2; rep++) { t = r->v[31] >> 7; r->v[31] &= 127; t = times19(t); r->v[0] += t; for(i = 0; i < 31; i++) { t = r->v[i] >> 8; r->v[i+1] += t; r->v[i] &= 255; } } } /* reduction modulo 2^255-19 */ void fe25519_freeze(fe25519 *r) { int i; uint32_t m = equal(r->v[31],127); for (i = 30; i > 0; i--) { m &= equal(r->v[i],255); } m &= ge(r->v[0],237); m = -m; r->v[31] -= m&127; for (i = 30; i > 0; i--) { r->v[i] -= m&255; } r->v[0] -= m&237; } void fe25519_unpack(fe25519 *r, const unsigned char x[32]) { int i; for (i = 0;i < 32; i++) { r->v[i] = x[i]; } r->v[31] &= 127; } /* Assumes input x being reduced below 2^255 */ void fe25519_pack(unsigned char r[32], const fe25519 *x) { int i; fe25519 y = *x; fe25519_freeze(&y); for (i = 0; i < 32; i++) { r[i] = y.v[i]; } } uint32_t fe25519_iszero(const fe25519 *x) { int i; uint32_t r; fe25519 t = *x; fe25519_freeze(&t); r = equal(t.v[0],0); for (i = 1; i < 32; i++) { r &= equal(t.v[i],0); } return r; } int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y) { int i; fe25519 t1 = *x; fe25519 t2 = *y; fe25519_freeze(&t1); fe25519_freeze(&t2); for (i = 0; i < 32; i++) { if(t1.v[i] != t2.v[i]) { return 0; } } return 1; } void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b) { int i; uint32_t mask = b; mask = -mask; for (i = 0; i < 32; i++) { r->v[i] ^= mask & (x->v[i] ^ r->v[i]); } } unsigned char fe25519_getparity(const fe25519 *x) { fe25519 t = *x; fe25519_freeze(&t); return t.v[0] & 1; } void fe25519_setone(fe25519 *r) { int i; r->v[0] = 1; for (i = 1; i < 32; i++) { r->v[i]=0; } } void fe25519_setzero(fe25519 *r) { int i; for (i = 0; i < 32; i++) { r->v[i]=0; } } void fe25519_neg(fe25519 *r, const fe25519 *x) { fe25519 t; int i; for (i = 0; i < 32; i++) { t.v[i]=x->v[i]; } fe25519_setzero(r); fe25519_sub(r, r, &t); } void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; for (i = 0; i < 32; i++) { r->v[i] = x->v[i] + y->v[i]; } reduce_add_sub(r); } void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i; uint32_t t[32]; t[0] = x->v[0] + 0x1da; t[31] = x->v[31] + 0xfe; for (i = 1; i < 31; i++) { t[i] = x->v[i] + 0x1fe; } for (i = 0; i < 32; i++) { r->v[i] = t[i] - y->v[i]; } reduce_add_sub(r); } void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y) { int i,j; uint32_t t[63]; for (i = 0; i < 63; i++) { t[i] = 0; } for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) { t[i+j] += x->v[i] * y->v[j]; } } for (i = 32; i < 63; i++) { r->v[i-32] = t[i-32] + times38(t[i]); } r->v[31] = t[31]; /* result now in r[0]...r[31] */ reduce_mul(r); } void fe25519_square(fe25519 *r, const fe25519 *x) { fe25519_mul(r, x, x); } void fe25519_invert(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; fe25519 z11; fe25519 z2_5_0; fe25519 z2_10_0; fe25519 z2_20_0; fe25519 z2_50_0; fe25519 z2_100_0; fe25519 t0; fe25519 t1; int i; /* 2 */ fe25519_square(&z2, x); /* 4 */ fe25519_square(&t1, &z2); /* 8 */ fe25519_square(&t0, &t1); /* 9 */ fe25519_mul(&z9, &t0, x); /* 11 */ fe25519_mul(&z11, &z9, &z2); /* 22 */ fe25519_square(&t0, &z11); /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0, &t0, &z9); /* 2^6 - 2^1 */ fe25519_square(&t0, &z2_5_0); /* 2^7 - 2^2 */ fe25519_square(&t1, &t0); /* 2^8 - 2^3 */ fe25519_square(&t0, &t1); /* 2^9 - 2^4 */ fe25519_square(&t1, &t0); /* 2^10 - 2^5 */ fe25519_square(&t0, &t1); /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0, &t0, &z2_5_0); /* 2^11 - 2^1 */ fe25519_square(&t0, &z2_10_0); /* 2^12 - 2^2 */ fe25519_square(&t1, &t0); /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0, &t1); fe25519_square(&t1, &t0); } /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t1, &z2_10_0); /* 2^21 - 2^1 */ fe25519_square(&t0, &z2_20_0); /* 2^22 - 2^2 */ fe25519_square(&t1, &t0); /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0, &t1); fe25519_square(&t1,&t0); } /* 2^40 - 2^0 */ fe25519_mul(&t0, &t1, &z2_20_0); /* 2^41 - 2^1 */ fe25519_square(&t1, &t0); /* 2^42 - 2^2 */ fe25519_square(&t0, &t1); /* 2^50 - 2^10 */ for (i = 2; i < 10;i += 2) { fe25519_square(&t1, &t0); fe25519_square(&t0, &t1); } /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0); /* 2^51 - 2^1 */ fe25519_square(&t0, &z2_50_0); /* 2^52 - 2^2 */ fe25519_square(&t1, &t0); /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) { fe25519_square(&t0, &t1); fe25519_square(&t1,&t0); } /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t1, &z2_50_0); /* 2^101 - 2^1 */ fe25519_square(&t1, &z2_100_0); /* 2^102 - 2^2 */ fe25519_square(&t0, &t1); /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) { fe25519_square(&t1, &t0); fe25519_square(&t0,&t1); } /* 2^200 - 2^0 */ fe25519_mul(&t1, &t0, &z2_100_0); /* 2^201 - 2^1 */ fe25519_square(&t0, &t1); /* 2^202 - 2^2 */ fe25519_square(&t1, &t0); /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0, &t1); fe25519_square(&t1,&t0); } /* 2^250 - 2^0 */ fe25519_mul(&t0, &t1, &z2_50_0); /* 2^251 - 2^1 */ fe25519_square(&t1, &t0); /* 2^252 - 2^2 */ fe25519_square(&t0, &t1); /* 2^253 - 2^3 */ fe25519_square(&t1, &t0); /* 2^254 - 2^4 */ fe25519_square(&t0, &t1); /* 2^255 - 2^5 */ fe25519_square(&t1, &t0); /* 2^255 - 21 */ fe25519_mul(r, &t1, &z11); } void fe25519_pow2523(fe25519 *r, const fe25519 *x) { fe25519 z2; fe25519 z9; fe25519 z11; fe25519 z2_5_0; fe25519 z2_10_0; fe25519 z2_20_0; fe25519 z2_50_0; fe25519 z2_100_0; fe25519 t; int i; /* 2 */ fe25519_square(&z2, x); /* 4 */ fe25519_square(&t, &z2); /* 8 */ fe25519_square(&t, &t); /* 9 */ fe25519_mul(&z9, &t, x); /* 11 */ fe25519_mul(&z11, &z9, &z2); /* 22 */ fe25519_square(&t, &z11); /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0, &t, &z9); /* 2^6 - 2^1 */ fe25519_square(&t, &z2_5_0); /* 2^10 - 2^5 */ for (i = 1; i < 5; i++) { fe25519_square(&t,&t); } /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0, &t, &z2_5_0); /* 2^11 - 2^1 */ fe25519_square(&t, &z2_10_0); /* 2^20 - 2^10 */ for (i = 1; i < 10; i++) { fe25519_square(&t, &t); } /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0, &t, &z2_10_0); /* 2^21 - 2^1 */ fe25519_square(&t, &z2_20_0); /* 2^40 - 2^20 */ for (i = 1; i < 20; i++) { fe25519_square(&t,&t); } /* 2^40 - 2^0 */ fe25519_mul(&t, &t, &z2_20_0); /* 2^41 - 2^1 */ fe25519_square(&t, &t); /* 2^50 - 2^10 */ for (i = 1; i < 10; i++) { fe25519_square(&t,&t); } /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0, &t, &z2_10_0); /* 2^51 - 2^1 */ fe25519_square(&t, &z2_50_0); /* 2^100 - 2^50 */ for (i = 1; i < 50; i++) { fe25519_square(&t, &t); } /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0, &t, &z2_50_0); /* 2^101 - 2^1 */ fe25519_square(&t, &z2_100_0); /* 2^200 - 2^100 */ for (i = 1; i < 100; i++) { fe25519_square(&t, &t); } /* 2^200 - 2^0 */ fe25519_mul(&t, &t, &z2_100_0); /* 2^201 - 2^1 */ fe25519_square(&t, &t); /* 2^250 - 2^50 */ for (i = 1; i < 50; i++) { fe25519_square(&t, &t); } /* 2^250 - 2^0 */ fe25519_mul(&t, &t, &z2_50_0); /* 2^251 - 2^1 */ fe25519_square(&t, &t); /* 2^252 - 2^2 */ fe25519_square(&t, &t); /* 2^252 - 3 */ fe25519_mul(r, &t, x); } ================================================ FILE: src/libssh/src/external/ge25519.c ================================================ /* $OpenBSD: ge25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519.c */ #include "config.h" #include "libssh/fe25519.h" #include "libssh/sc25519.h" #include "libssh/ge25519.h" /* * Arithmetic on the twisted Edwards curve -x^2 + y^2 = 1 + dx^2y^2 * with d = -(121665/121666) = 37095705934669439343138083508754565189542113879843219016388785533085940283555 * Base point: (15112221349535400772501151409588531511454012693041857206046113283949847762202,46316835694926478169428394003475163141307993866256225615783033603165251855960); */ /* d */ static const fe25519 ge25519_ecd = { {0xA3, 0x78, 0x59, 0x13, 0xCA, 0x4D, 0xEB, 0x75, 0xAB, 0xD8, 0x41, 0x41, 0x4D, 0x0A, 0x70, 0x00, 0x98, 0xE8, 0x79, 0x77, 0x79, 0x40, 0xC7, 0x8C, 0x73, 0xFE, 0x6F, 0x2B, 0xEE, 0x6C, 0x03, 0x52} }; /* 2*d */ static const fe25519 ge25519_ec2d = { {0x59, 0xF1, 0xB2, 0x26, 0x94, 0x9B, 0xD6, 0xEB, 0x56, 0xB1, 0x83, 0x82, 0x9A, 0x14, 0xE0, 0x00, 0x30, 0xD1, 0xF3, 0xEE, 0xF2, 0x80, 0x8E, 0x19, 0xE7, 0xFC, 0xDF, 0x56, 0xDC, 0xD9, 0x06, 0x24} }; /* sqrt(-1) */ static const fe25519 ge25519_sqrtm1 = { {0xB0, 0xA0, 0x0E, 0x4A, 0x27, 0x1B, 0xEE, 0xC4, 0x78, 0xE4, 0x2F, 0xAD, 0x06, 0x18, 0x43, 0x2F, 0xA7, 0xD7, 0xFB, 0x3D, 0x99, 0x00, 0x4D, 0x2B, 0x0B, 0xDF, 0xC1, 0x4F, 0x80, 0x24, 0x83, 0x2B} }; #define ge25519_p3 ge25519 typedef struct { fe25519 x; fe25519 z; fe25519 y; fe25519 t; } ge25519_p1p1; typedef struct { fe25519 x; fe25519 y; fe25519 z; } ge25519_p2; typedef struct { fe25519 x; fe25519 y; } ge25519_aff; /* Packed coordinates of the base point */ const ge25519 ge25519_base = { {{0x1A, 0xD5, 0x25, 0x8F, 0x60, 0x2D, 0x56, 0xC9, 0xB2, 0xA7, 0x25, 0x95, 0x60, 0xC7, 0x2C, 0x69, 0x5C, 0xDC, 0xD6, 0xFD, 0x31, 0xE2, 0xA4, 0xC0, 0xFE, 0x53, 0x6E, 0xCD, 0xD3, 0x36, 0x69, 0x21}}, {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0xA3, 0xDD, 0xB7, 0xA5, 0xB3, 0x8A, 0xDE, 0x6D, 0xF5, 0x52, 0x51, 0x77, 0x80, 0x9F, 0xF0, 0x20, 0x7D, 0xE3, 0xAB, 0x64, 0x8E, 0x4E, 0xEA, 0x66, 0x65, 0x76, 0x8B, 0xD7, 0x0F, 0x5F, 0x87, 0x67}} }; /* Multiples of the base point in affine representation */ static const ge25519_aff ge25519_base_multiples_affine[425] = { #include "ge25519_base.data" }; static void p1p1_to_p2(ge25519_p2 *r, const ge25519_p1p1 *p) { fe25519_mul(&r->x, &p->x, &p->t); fe25519_mul(&r->y, &p->y, &p->z); fe25519_mul(&r->z, &p->z, &p->t); } static void p1p1_to_p3(ge25519_p3 *r, const ge25519_p1p1 *p) { p1p1_to_p2((ge25519_p2 *)r, p); fe25519_mul(&r->t, &p->x, &p->y); } static void ge25519_mixadd2(ge25519_p3 *r, const ge25519_aff *q) { fe25519 a,b,t1,t2,c,d,e,f,g,h,qt; fe25519_mul(&qt, &q->x, &q->y); fe25519_sub(&a, &r->y, &r->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_add(&b, &r->y, &r->x); /* B = (Y1+X1)*(Y2+X2) */ fe25519_sub(&t1, &q->y, &q->x); fe25519_add(&t2, &q->y, &q->x); fe25519_mul(&a, &a, &t1); fe25519_mul(&b, &b, &t2); fe25519_sub(&e, &b, &a); /* E = B-A */ fe25519_add(&h, &b, &a); /* H = B+A */ fe25519_mul(&c, &r->t, &qt); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_add(&d, &r->z, &r->z); /* D = Z1*2 */ fe25519_sub(&f, &d, &c); /* F = D-C */ fe25519_add(&g, &d, &c); /* G = D+C */ fe25519_mul(&r->x, &e, &f); fe25519_mul(&r->y, &h, &g); fe25519_mul(&r->z, &g, &f); fe25519_mul(&r->t, &e, &h); } static void add_p1p1(ge25519_p1p1 *r, const ge25519_p3 *p, const ge25519_p3 *q) { fe25519 a, b, c, d, t; fe25519_sub(&a, &p->y, &p->x); /* A = (Y1-X1)*(Y2-X2) */ fe25519_sub(&t, &q->y, &q->x); fe25519_mul(&a, &a, &t); fe25519_add(&b, &p->x, &p->y); /* B = (Y1+X1)*(Y2+X2) */ fe25519_add(&t, &q->x, &q->y); fe25519_mul(&b, &b, &t); fe25519_mul(&c, &p->t, &q->t); /* C = T1*k*T2 */ fe25519_mul(&c, &c, &ge25519_ec2d); fe25519_mul(&d, &p->z, &q->z); /* D = Z1*2*Z2 */ fe25519_add(&d, &d, &d); fe25519_sub(&r->x, &b, &a); /* E = B-A */ fe25519_sub(&r->t, &d, &c); /* F = D-C */ fe25519_add(&r->z, &d, &c); /* G = D+C */ fe25519_add(&r->y, &b, &a); /* H = B+A */ } /* See http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ static void dbl_p1p1(ge25519_p1p1 *r, const ge25519_p2 *p) { fe25519 a,b,c,d; fe25519_square(&a, &p->x); fe25519_square(&b, &p->y); fe25519_square(&c, &p->z); fe25519_add(&c, &c, &c); fe25519_neg(&d, &a); fe25519_add(&r->x, &p->x, &p->y); fe25519_square(&r->x, &r->x); fe25519_sub(&r->x, &r->x, &a); fe25519_sub(&r->x, &r->x, &b); fe25519_add(&r->z, &d, &b); fe25519_sub(&r->t, &r->z, &c); fe25519_sub(&r->y, &d, &b); } /* Constant-time version of: if(b) r = p */ static void cmov_aff(ge25519_aff *r, const ge25519_aff *p, unsigned char b) { fe25519_cmov(&r->x, &p->x, b); fe25519_cmov(&r->y, &p->y, b); } static unsigned char equal(signed char b,signed char c) { unsigned char ub = b; unsigned char uc = c; unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ uint32_t y = x; /* 0: yes; 1..255: no */ y -= 1; /* 4294967295: yes; 0..254: no */ y >>= 31; /* 1: yes; 0: no */ return y; } static unsigned char negative(signed char b) { unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ return x; } static void choose_t(ge25519_aff *t, unsigned long long pos, signed char b) { /* constant time */ fe25519 v; *t = ge25519_base_multiples_affine[5 * pos + 0]; cmov_aff(t, &ge25519_base_multiples_affine[5 * pos + 1], equal(b,1) | equal(b,-1)); cmov_aff(t, &ge25519_base_multiples_affine[5 * pos + 2], equal(b,2) | equal(b,-2)); cmov_aff(t, &ge25519_base_multiples_affine[5 * pos + 3], equal(b,3) | equal(b,-3)); cmov_aff(t, &ge25519_base_multiples_affine[5 * pos + 4], equal(b,-4)); fe25519_neg(&v, &t->x); fe25519_cmov(&t->x, &v, negative(b)); } static void setneutral(ge25519 *r) { fe25519_setzero(&r->x); fe25519_setone(&r->y); fe25519_setone(&r->z); fe25519_setzero(&r->t); } /* ******************************************************************** * EXPORTED FUNCTIONS ******************************************************************** */ /* return 0 on success, -1 otherwise */ int ge25519_unpackneg_vartime(ge25519_p3 *r, const unsigned char p[32]) { unsigned char par; fe25519 t, chk, num, den, den2, den4, den6; fe25519_setone(&r->z); par = p[31] >> 7; fe25519_unpack(&r->y, p); fe25519_square(&num, &r->y); /* x = y^2 */ fe25519_mul(&den, &num, &ge25519_ecd); /* den = dy^2 */ fe25519_sub(&num, &num, &r->z); /* x = y^2-1 */ fe25519_add(&den, &r->z, &den); /* den = dy^2+1 */ /* Computation of sqrt(num/den) */ /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */ fe25519_square(&den2, &den); fe25519_square(&den4, &den2); fe25519_mul(&den6, &den4, &den2); fe25519_mul(&t, &den6, &num); fe25519_mul(&t, &t, &den); fe25519_pow2523(&t, &t); /* 2. computation of r->x = t * num * den^3 */ fe25519_mul(&t, &t, &num); fe25519_mul(&t, &t, &den); fe25519_mul(&t, &t, &den); fe25519_mul(&r->x, &t, &den); /* 3. Check whether sqrt computation gave correct result, multiply by sqrt(-1) if not: */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) { fe25519_mul(&r->x, &r->x, &ge25519_sqrtm1); } /* 4. Now we have one of the two square roots, except if input was not a square */ fe25519_square(&chk, &r->x); fe25519_mul(&chk, &chk, &den); if (!fe25519_iseq_vartime(&chk, &num)) { return -1; } /* 5. Choose the desired square root according to parity: */ if(fe25519_getparity(&r->x) != (1-par)) { fe25519_neg(&r->x, &r->x); } fe25519_mul(&r->t, &r->x, &r->y); return 0; } void ge25519_pack(unsigned char r[32], const ge25519_p3 *p) { fe25519 tx, ty, zi; fe25519_invert(&zi, &p->z); fe25519_mul(&tx, &p->x, &zi); fe25519_mul(&ty, &p->y, &zi); fe25519_pack(r, &ty); r[31] ^= fe25519_getparity(&tx) << 7; } int ge25519_isneutral_vartime(const ge25519_p3 *p) { int ret = 1; if (!fe25519_iszero(&p->x)) { ret = 0; } if (!fe25519_iseq_vartime(&p->y, &p->z)) { ret = 0; } return ret; } /* computes [s1]p1 + [s2]p2 */ void ge25519_double_scalarmult_vartime(ge25519_p3 *r, const ge25519_p3 *p1, const sc25519 *s1, const ge25519_p3 *p2, const sc25519 *s2) { ge25519_p1p1 tp1p1; ge25519_p3 pre[16]; unsigned char b[127]; int i; /* precomputation s2 s1 */ setneutral(pre); /* 00 00 */ pre[1] = *p1; /* 00 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p1); p1p1_to_p3( &pre[2], &tp1p1); /* 00 10 */ add_p1p1(&tp1p1,&pre[1], &pre[2]); p1p1_to_p3( &pre[3], &tp1p1); /* 00 11 */ pre[4] = *p2; /* 01 00 */ add_p1p1(&tp1p1,&pre[1], &pre[4]); p1p1_to_p3( &pre[5], &tp1p1); /* 01 01 */ add_p1p1(&tp1p1,&pre[2], &pre[4]); p1p1_to_p3( &pre[6], &tp1p1); /* 01 10 */ add_p1p1(&tp1p1,&pre[3], &pre[4]); p1p1_to_p3( &pre[7], &tp1p1); /* 01 11 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)p2); p1p1_to_p3( &pre[8], &tp1p1); /* 10 00 */ add_p1p1(&tp1p1,&pre[1], &pre[8]); p1p1_to_p3( &pre[9], &tp1p1); /* 10 01 */ dbl_p1p1(&tp1p1,(ge25519_p2 *)&pre[5]); p1p1_to_p3(&pre[10], &tp1p1); /* 10 10 */ add_p1p1(&tp1p1,&pre[3], &pre[8]); p1p1_to_p3(&pre[11], &tp1p1); /* 10 11 */ add_p1p1(&tp1p1,&pre[4], &pre[8]); p1p1_to_p3(&pre[12], &tp1p1); /* 11 00 */ add_p1p1(&tp1p1,&pre[1],&pre[12]); p1p1_to_p3(&pre[13], &tp1p1); /* 11 01 */ add_p1p1(&tp1p1,&pre[2],&pre[12]); p1p1_to_p3(&pre[14], &tp1p1); /* 11 10 */ add_p1p1(&tp1p1,&pre[3],&pre[12]); p1p1_to_p3(&pre[15], &tp1p1); /* 11 11 */ sc25519_2interleave2(b,s1,s2); /* scalar multiplication */ *r = pre[b[126]]; for (i = 125; i >= 0; i--) { dbl_p1p1(&tp1p1, (ge25519_p2 *)r); p1p1_to_p2((ge25519_p2 *) r, &tp1p1); dbl_p1p1(&tp1p1, (ge25519_p2 *)r); if(b[i] != 0) { p1p1_to_p3(r, &tp1p1); add_p1p1(&tp1p1, r, &pre[b[i]]); } if (i != 0) { p1p1_to_p2((ge25519_p2 *)r, &tp1p1); } else { p1p1_to_p3(r, &tp1p1); } } } void ge25519_scalarmult_base(ge25519_p3 *r, const sc25519 *s) { signed char b[85]; int i; ge25519_aff t; sc25519_window3(b,s); choose_t((ge25519_aff *)r, 0, b[0]); fe25519_setone(&r->z); fe25519_mul(&r->t, &r->x, &r->y); for (i = 1; i < 85; i++) { choose_t(&t, (unsigned long long) i, b[i]); ge25519_mixadd2(r, &t); } } ================================================ FILE: src/libssh/src/external/ge25519_base.data ================================================ /* $OpenBSD: ge25519_base.data,v 1.3 2013/12/09 11:03:45 markus Exp $ */ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519_base.data */ {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}} , {{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}}}, {{{0x0e, 0xce, 0x43, 0x28, 0x4e, 0xa1, 0xc5, 0x83, 0x5f, 0xa4, 0xd7, 0x15, 0x45, 0x8e, 0x0d, 0x08, 0xac, 0xe7, 0x33, 0x18, 0x7d, 0x3b, 0x04, 0x3d, 0x6c, 0x04, 0x5a, 0x9f, 0x4c, 0x38, 0xab, 0x36}} , {{0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0x0e, 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22}}}, {{{0x5c, 0xe2, 0xf8, 0xd3, 0x5f, 0x48, 0x62, 0xac, 0x86, 0x48, 0x62, 0x81, 0x19, 0x98, 0x43, 0x63, 0x3a, 0xc8, 0xda, 0x3e, 0x74, 0xae, 0xf4, 0x1f, 0x49, 0x8f, 0x92, 0x22, 0x4a, 0x9c, 0xae, 0x67}} , {{0xd4, 0xb4, 0xf5, 0x78, 0x48, 0x68, 0xc3, 0x02, 0x04, 0x03, 0x24, 0x67, 0x17, 0xec, 0x16, 0x9f, 0xf7, 0x9e, 0x26, 0x60, 0x8e, 0xa1, 0x26, 0xa1, 0xab, 0x69, 0xee, 0x77, 0xd1, 0xb1, 0x67, 0x12}}}, {{{0x70, 0xf8, 0xc9, 0xc4, 0x57, 0xa6, 0x3a, 0x49, 0x47, 0x15, 0xce, 0x93, 0xc1, 0x9e, 0x73, 0x1a, 0xf9, 0x20, 0x35, 0x7a, 0xb8, 0xd4, 0x25, 0x83, 0x46, 0xf1, 0xcf, 0x56, 0xdb, 0xa8, 0x3d, 0x20}} , {{0x2f, 0x11, 0x32, 0xca, 0x61, 0xab, 0x38, 0xdf, 0xf0, 0x0f, 0x2f, 0xea, 0x32, 0x28, 0xf2, 0x4c, 0x6c, 0x71, 0xd5, 0x80, 0x85, 0xb8, 0x0e, 0x47, 0xe1, 0x95, 0x15, 0xcb, 0x27, 0xe8, 0xd0, 0x47}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc8, 0x84, 0xa5, 0x08, 0xbc, 0xfd, 0x87, 0x3b, 0x99, 0x8b, 0x69, 0x80, 0x7b, 0xc6, 0x3a, 0xeb, 0x93, 0xcf, 0x4e, 0xf8, 0x5c, 0x2d, 0x86, 0x42, 0xb6, 0x71, 0xd7, 0x97, 0x5f, 0xe1, 0x42, 0x67}} , {{0xb4, 0xb9, 0x37, 0xfc, 0xa9, 0x5b, 0x2f, 0x1e, 0x93, 0xe4, 0x1e, 0x62, 0xfc, 0x3c, 0x78, 0x81, 0x8f, 0xf3, 0x8a, 0x66, 0x09, 0x6f, 0xad, 0x6e, 0x79, 0x73, 0xe5, 0xc9, 0x00, 0x06, 0xd3, 0x21}}}, {{{0xf8, 0xf9, 0x28, 0x6c, 0x6d, 0x59, 0xb2, 0x59, 0x74, 0x23, 0xbf, 0xe7, 0x33, 0x8d, 0x57, 0x09, 0x91, 0x9c, 0x24, 0x08, 0x15, 0x2b, 0xe2, 0xb8, 0xee, 0x3a, 0xe5, 0x27, 0x06, 0x86, 0xa4, 0x23}} , {{0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70}}}, {{{0x81, 0x6b, 0x88, 0xe8, 0x1e, 0xc7, 0x77, 0x96, 0x0e, 0xa1, 0xa9, 0x52, 0xe0, 0xd8, 0x0e, 0x61, 0x9e, 0x79, 0x2d, 0x95, 0x9c, 0x8d, 0x96, 0xe0, 0x06, 0x40, 0x5d, 0x87, 0x28, 0x5f, 0x98, 0x70}} , {{0xf1, 0x79, 0x7b, 0xed, 0x4f, 0x44, 0xb2, 0xe7, 0x08, 0x0d, 0xc2, 0x08, 0x12, 0xd2, 0x9f, 0xdf, 0xcd, 0x93, 0x20, 0x8a, 0xcf, 0x33, 0xca, 0x6d, 0x89, 0xb9, 0x77, 0xc8, 0x93, 0x1b, 0x4e, 0x60}}}, {{{0x26, 0x4f, 0x7e, 0x97, 0xf6, 0x40, 0xdd, 0x4f, 0xfc, 0x52, 0x78, 0xf9, 0x90, 0x31, 0x03, 0xe6, 0x7d, 0x56, 0x39, 0x0b, 0x1d, 0x56, 0x82, 0x85, 0xf9, 0x1a, 0x42, 0x17, 0x69, 0x6c, 0xcf, 0x39}} , {{0x69, 0xd2, 0x06, 0x3a, 0x4f, 0x39, 0x2d, 0xf9, 0x38, 0x40, 0x8c, 0x4c, 0xe7, 0x05, 0x12, 0xb4, 0x78, 0x8b, 0xf8, 0xc0, 0xec, 0x93, 0xde, 0x7a, 0x6b, 0xce, 0x2c, 0xe1, 0x0e, 0xa9, 0x34, 0x44}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0b, 0xa4, 0x3c, 0xb0, 0x0f, 0x7a, 0x51, 0xf1, 0x78, 0xd6, 0xd9, 0x6a, 0xfd, 0x46, 0xe8, 0xb8, 0xa8, 0x79, 0x1d, 0x87, 0xf9, 0x90, 0xf2, 0x9c, 0x13, 0x29, 0xf8, 0x0b, 0x20, 0x64, 0xfa, 0x05}} , {{0x26, 0x09, 0xda, 0x17, 0xaf, 0x95, 0xd6, 0xfb, 0x6a, 0x19, 0x0d, 0x6e, 0x5e, 0x12, 0xf1, 0x99, 0x4c, 0xaa, 0xa8, 0x6f, 0x79, 0x86, 0xf4, 0x72, 0x28, 0x00, 0x26, 0xf9, 0xea, 0x9e, 0x19, 0x3d}}}, {{{0x87, 0xdd, 0xcf, 0xf0, 0x5b, 0x49, 0xa2, 0x5d, 0x40, 0x7a, 0x23, 0x26, 0xa4, 0x7a, 0x83, 0x8a, 0xb7, 0x8b, 0xd2, 0x1a, 0xbf, 0xea, 0x02, 0x24, 0x08, 0x5f, 0x7b, 0xa9, 0xb1, 0xbe, 0x9d, 0x37}} , {{0xfc, 0x86, 0x4b, 0x08, 0xee, 0xe7, 0xa0, 0xfd, 0x21, 0x45, 0x09, 0x34, 0xc1, 0x61, 0x32, 0x23, 0xfc, 0x9b, 0x55, 0x48, 0x53, 0x99, 0xf7, 0x63, 0xd0, 0x99, 0xce, 0x01, 0xe0, 0x9f, 0xeb, 0x28}}}, {{{0x47, 0xfc, 0xab, 0x5a, 0x17, 0xf0, 0x85, 0x56, 0x3a, 0x30, 0x86, 0x20, 0x28, 0x4b, 0x8e, 0x44, 0x74, 0x3a, 0x6e, 0x02, 0xf1, 0x32, 0x8f, 0x9f, 0x3f, 0x08, 0x35, 0xe9, 0xca, 0x16, 0x5f, 0x6e}} , {{0x1c, 0x59, 0x1c, 0x65, 0x5d, 0x34, 0xa4, 0x09, 0xcd, 0x13, 0x9c, 0x70, 0x7d, 0xb1, 0x2a, 0xc5, 0x88, 0xaf, 0x0b, 0x60, 0xc7, 0x9f, 0x34, 0x8d, 0xd6, 0xb7, 0x7f, 0xea, 0x78, 0x65, 0x8d, 0x77}}}, {{{0x56, 0xa5, 0xc2, 0x0c, 0xdd, 0xbc, 0xb8, 0x20, 0x6d, 0x57, 0x61, 0xb5, 0xfb, 0x78, 0xb5, 0xd4, 0x49, 0x54, 0x90, 0x26, 0xc1, 0xcb, 0xe9, 0xe6, 0xbf, 0xec, 0x1d, 0x4e, 0xed, 0x07, 0x7e, 0x5e}} , {{0xc7, 0xf6, 0x6c, 0x56, 0x31, 0x20, 0x14, 0x0e, 0xa8, 0xd9, 0x27, 0xc1, 0x9a, 0x3d, 0x1b, 0x7d, 0x0e, 0x26, 0xd3, 0x81, 0xaa, 0xeb, 0xf5, 0x6b, 0x79, 0x02, 0xf1, 0x51, 0x5c, 0x75, 0x55, 0x0f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0a, 0x34, 0xcd, 0x82, 0x3c, 0x33, 0x09, 0x54, 0xd2, 0x61, 0x39, 0x30, 0x9b, 0xfd, 0xef, 0x21, 0x26, 0xd4, 0x70, 0xfa, 0xee, 0xf9, 0x31, 0x33, 0x73, 0x84, 0xd0, 0xb3, 0x81, 0xbf, 0xec, 0x2e}} , {{0xe8, 0x93, 0x8b, 0x00, 0x64, 0xf7, 0x9c, 0xb8, 0x74, 0xe0, 0xe6, 0x49, 0x48, 0x4d, 0x4d, 0x48, 0xb6, 0x19, 0xa1, 0x40, 0xb7, 0xd9, 0x32, 0x41, 0x7c, 0x82, 0x37, 0xa1, 0x2d, 0xdc, 0xd2, 0x54}}}, {{{0x68, 0x2b, 0x4a, 0x5b, 0xd5, 0xc7, 0x51, 0x91, 0x1d, 0xe1, 0x2a, 0x4b, 0xc4, 0x47, 0xf1, 0xbc, 0x7a, 0xb3, 0xcb, 0xc8, 0xb6, 0x7c, 0xac, 0x90, 0x05, 0xfd, 0xf3, 0xf9, 0x52, 0x3a, 0x11, 0x6b}} , {{0x3d, 0xc1, 0x27, 0xf3, 0x59, 0x43, 0x95, 0x90, 0xc5, 0x96, 0x79, 0xf5, 0xf4, 0x95, 0x65, 0x29, 0x06, 0x9c, 0x51, 0x05, 0x18, 0xda, 0xb8, 0x2e, 0x79, 0x7e, 0x69, 0x59, 0x71, 0x01, 0xeb, 0x1a}}}, {{{0x15, 0x06, 0x49, 0xb6, 0x8a, 0x3c, 0xea, 0x2f, 0x34, 0x20, 0x14, 0xc3, 0xaa, 0xd6, 0xaf, 0x2c, 0x3e, 0xbd, 0x65, 0x20, 0xe2, 0x4d, 0x4b, 0x3b, 0xeb, 0x9f, 0x4a, 0xc3, 0xad, 0xa4, 0x3b, 0x60}} , {{0xbc, 0x58, 0xe6, 0xc0, 0x95, 0x2a, 0x2a, 0x81, 0x9a, 0x7a, 0xf3, 0xd2, 0x06, 0xbe, 0x48, 0xbc, 0x0c, 0xc5, 0x46, 0xe0, 0x6a, 0xd4, 0xac, 0x0f, 0xd9, 0xcc, 0x82, 0x34, 0x2c, 0xaf, 0xdb, 0x1f}}}, {{{0xf7, 0x17, 0x13, 0xbd, 0xfb, 0xbc, 0xd2, 0xec, 0x45, 0xb3, 0x15, 0x31, 0xe9, 0xaf, 0x82, 0x84, 0x3d, 0x28, 0xc6, 0xfc, 0x11, 0xf5, 0x41, 0xb5, 0x8b, 0xd3, 0x12, 0x76, 0x52, 0xe7, 0x1a, 0x3c}} , {{0x4e, 0x36, 0x11, 0x07, 0xa2, 0x15, 0x20, 0x51, 0xc4, 0x2a, 0xc3, 0x62, 0x8b, 0x5e, 0x7f, 0xa6, 0x0f, 0xf9, 0x45, 0x85, 0x6c, 0x11, 0x86, 0xb7, 0x7e, 0xe5, 0xd7, 0xf9, 0xc3, 0x91, 0x1c, 0x05}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xd6, 0xde, 0x29, 0x3a, 0x00, 0xb9, 0x02, 0x59, 0xcb, 0x26, 0xc4, 0xba, 0x99, 0xb1, 0x97, 0x2f, 0x8e, 0x00, 0x92, 0x26, 0x4f, 0x52, 0xeb, 0x47, 0x1b, 0x89, 0x8b, 0x24, 0xc0, 0x13, 0x7d}} , {{0xd5, 0x20, 0x5b, 0x80, 0xa6, 0x80, 0x20, 0x95, 0xc3, 0xe9, 0x9f, 0x8e, 0x87, 0x9e, 0x1e, 0x9e, 0x7a, 0xc7, 0xcc, 0x75, 0x6c, 0xa5, 0xf1, 0x91, 0x1a, 0xa8, 0x01, 0x2c, 0xab, 0x76, 0xa9, 0x59}}}, {{{0xde, 0xc9, 0xb1, 0x31, 0x10, 0x16, 0xaa, 0x35, 0x14, 0x6a, 0xd4, 0xb5, 0x34, 0x82, 0x71, 0xd2, 0x4a, 0x5d, 0x9a, 0x1f, 0x53, 0x26, 0x3c, 0xe5, 0x8e, 0x8d, 0x33, 0x7f, 0xff, 0xa9, 0xd5, 0x17}} , {{0x89, 0xaf, 0xf6, 0xa4, 0x64, 0xd5, 0x10, 0xe0, 0x1d, 0xad, 0xef, 0x44, 0xbd, 0xda, 0x83, 0xac, 0x7a, 0xa8, 0xf0, 0x1c, 0x07, 0xf9, 0xc3, 0x43, 0x6c, 0x3f, 0xb7, 0xd3, 0x87, 0x22, 0x02, 0x73}}}, {{{0x64, 0x1d, 0x49, 0x13, 0x2f, 0x71, 0xec, 0x69, 0x87, 0xd0, 0x42, 0xee, 0x13, 0xec, 0xe3, 0xed, 0x56, 0x7b, 0xbf, 0xbd, 0x8c, 0x2f, 0x7d, 0x7b, 0x9d, 0x28, 0xec, 0x8e, 0x76, 0x2f, 0x6f, 0x08}} , {{0x22, 0xf5, 0x5f, 0x4d, 0x15, 0xef, 0xfc, 0x4e, 0x57, 0x03, 0x36, 0x89, 0xf0, 0xeb, 0x5b, 0x91, 0xd6, 0xe2, 0xca, 0x01, 0xa5, 0xee, 0x52, 0xec, 0xa0, 0x3c, 0x8f, 0x33, 0x90, 0x5a, 0x94, 0x72}}}, {{{0x8a, 0x4b, 0xe7, 0x38, 0xbc, 0xda, 0xc2, 0xb0, 0x85, 0xe1, 0x4a, 0xfe, 0x2d, 0x44, 0x84, 0xcb, 0x20, 0x6b, 0x2d, 0xbf, 0x11, 0x9c, 0xd7, 0xbe, 0xd3, 0x3e, 0x5f, 0xbf, 0x68, 0xbc, 0xa8, 0x07}} , {{0x01, 0x89, 0x28, 0x22, 0x6a, 0x78, 0xaa, 0x29, 0x03, 0xc8, 0x74, 0x95, 0x03, 0x3e, 0xdc, 0xbd, 0x07, 0x13, 0xa8, 0xa2, 0x20, 0x2d, 0xb3, 0x18, 0x70, 0x42, 0xfd, 0x7a, 0xc4, 0xd7, 0x49, 0x72}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xff, 0x32, 0x2b, 0x5c, 0x93, 0x54, 0x32, 0xe8, 0x57, 0x54, 0x1a, 0x8b, 0x33, 0x60, 0x65, 0xd3, 0x67, 0xa4, 0xc1, 0x26, 0xc4, 0xa4, 0x34, 0x1f, 0x9b, 0xa7, 0xa9, 0xf4, 0xd9, 0x4f, 0x5b}} , {{0x46, 0x8d, 0xb0, 0x33, 0x54, 0x26, 0x5b, 0x68, 0xdf, 0xbb, 0xc5, 0xec, 0xc2, 0xf9, 0x3c, 0x5a, 0x37, 0xc1, 0x8e, 0x27, 0x47, 0xaa, 0x49, 0x5a, 0xf8, 0xfb, 0x68, 0x04, 0x23, 0xd1, 0xeb, 0x40}}}, {{{0x65, 0xa5, 0x11, 0x84, 0x8a, 0x67, 0x9d, 0x9e, 0xd1, 0x44, 0x68, 0x7a, 0x34, 0xe1, 0x9f, 0xa3, 0x54, 0xcd, 0x07, 0xca, 0x79, 0x1f, 0x54, 0x2f, 0x13, 0x70, 0x4e, 0xee, 0xa2, 0xfa, 0xe7, 0x5d}} , {{0x36, 0xec, 0x54, 0xf8, 0xce, 0xe4, 0x85, 0xdf, 0xf6, 0x6f, 0x1d, 0x90, 0x08, 0xbc, 0xe8, 0xc0, 0x92, 0x2d, 0x43, 0x6b, 0x92, 0xa9, 0x8e, 0xab, 0x0a, 0x2e, 0x1c, 0x1e, 0x64, 0x23, 0x9f, 0x2c}}}, {{{0xa7, 0xd6, 0x2e, 0xd5, 0xcc, 0xd4, 0xcb, 0x5a, 0x3b, 0xa7, 0xf9, 0x46, 0x03, 0x1d, 0xad, 0x2b, 0x34, 0x31, 0x90, 0x00, 0x46, 0x08, 0x82, 0x14, 0xc4, 0xe0, 0x9c, 0xf0, 0xe3, 0x55, 0x43, 0x31}} , {{0x60, 0xd6, 0xdd, 0x78, 0xe6, 0xd4, 0x22, 0x42, 0x1f, 0x00, 0xf9, 0xb1, 0x6a, 0x63, 0xe2, 0x92, 0x59, 0xd1, 0x1a, 0xb7, 0x00, 0x54, 0x29, 0xc9, 0xc1, 0xf6, 0x6f, 0x7a, 0xc5, 0x3c, 0x5f, 0x65}}}, {{{0x27, 0x4f, 0xd0, 0x72, 0xb1, 0x11, 0x14, 0x27, 0x15, 0x94, 0x48, 0x81, 0x7e, 0x74, 0xd8, 0x32, 0xd5, 0xd1, 0x11, 0x28, 0x60, 0x63, 0x36, 0x32, 0x37, 0xb5, 0x13, 0x1c, 0xa0, 0x37, 0xe3, 0x74}} , {{0xf1, 0x25, 0x4e, 0x11, 0x96, 0x67, 0xe6, 0x1c, 0xc2, 0xb2, 0x53, 0xe2, 0xda, 0x85, 0xee, 0xb2, 0x9f, 0x59, 0xf3, 0xba, 0xbd, 0xfa, 0xcf, 0x6e, 0xf9, 0xda, 0xa4, 0xb3, 0x02, 0x8f, 0x64, 0x08}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x94, 0xf2, 0x64, 0x54, 0x47, 0x37, 0x07, 0x40, 0x8a, 0x20, 0xba, 0x4a, 0x55, 0xd7, 0x3f, 0x47, 0xba, 0x25, 0x23, 0x14, 0xb0, 0x2c, 0xe8, 0x55, 0xa8, 0xa6, 0xef, 0x51, 0xbd, 0x6f, 0x6a}} , {{0x71, 0xd6, 0x16, 0x76, 0xb2, 0x06, 0xea, 0x79, 0xf5, 0xc4, 0xc3, 0x52, 0x7e, 0x61, 0xd1, 0xe1, 0xad, 0x70, 0x78, 0x1d, 0x16, 0x11, 0xf8, 0x7c, 0x2b, 0xfc, 0x55, 0x9f, 0x52, 0xf8, 0xf5, 0x16}}}, {{{0x34, 0x96, 0x9a, 0xf6, 0xc5, 0xe0, 0x14, 0x03, 0x24, 0x0e, 0x4c, 0xad, 0x9e, 0x9a, 0x70, 0x23, 0x96, 0xb2, 0xf1, 0x2e, 0x9d, 0xc3, 0x32, 0x9b, 0x54, 0xa5, 0x73, 0xde, 0x88, 0xb1, 0x3e, 0x24}} , {{0xf6, 0xe2, 0x4c, 0x1f, 0x5b, 0xb2, 0xaf, 0x82, 0xa5, 0xcf, 0x81, 0x10, 0x04, 0xef, 0xdb, 0xa2, 0xcc, 0x24, 0xb2, 0x7e, 0x0b, 0x7a, 0xeb, 0x01, 0xd8, 0x52, 0xf4, 0x51, 0x89, 0x29, 0x79, 0x37}}}, {{{0x74, 0xde, 0x12, 0xf3, 0x68, 0xb7, 0x66, 0xc3, 0xee, 0x68, 0xdc, 0x81, 0xb5, 0x55, 0x99, 0xab, 0xd9, 0x28, 0x63, 0x6d, 0x8b, 0x40, 0x69, 0x75, 0x6c, 0xcd, 0x5c, 0x2a, 0x7e, 0x32, 0x7b, 0x29}} , {{0x02, 0xcc, 0x22, 0x74, 0x4d, 0x19, 0x07, 0xc0, 0xda, 0xb5, 0x76, 0x51, 0x2a, 0xaa, 0xa6, 0x0a, 0x5f, 0x26, 0xd4, 0xbc, 0xaf, 0x48, 0x88, 0x7f, 0x02, 0xbc, 0xf2, 0xe1, 0xcf, 0xe9, 0xdd, 0x15}}}, {{{0xed, 0xb5, 0x9a, 0x8c, 0x9a, 0xdd, 0x27, 0xf4, 0x7f, 0x47, 0xd9, 0x52, 0xa7, 0xcd, 0x65, 0xa5, 0x31, 0x22, 0xed, 0xa6, 0x63, 0x5b, 0x80, 0x4a, 0xad, 0x4d, 0xed, 0xbf, 0xee, 0x49, 0xb3, 0x06}} , {{0xf8, 0x64, 0x8b, 0x60, 0x90, 0xe9, 0xde, 0x44, 0x77, 0xb9, 0x07, 0x36, 0x32, 0xc2, 0x50, 0xf5, 0x65, 0xdf, 0x48, 0x4c, 0x37, 0xaa, 0x68, 0xab, 0x9a, 0x1f, 0x3e, 0xff, 0x89, 0x92, 0xa0, 0x07}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7d, 0x4f, 0x9c, 0x19, 0xc0, 0x4a, 0x31, 0xec, 0xf9, 0xaa, 0xeb, 0xb2, 0x16, 0x9c, 0xa3, 0x66, 0x5f, 0xd1, 0xd4, 0xed, 0xb8, 0x92, 0x1c, 0xab, 0xda, 0xea, 0xd9, 0x57, 0xdf, 0x4c, 0x2a, 0x48}} , {{0x4b, 0xb0, 0x4e, 0x6e, 0x11, 0x3b, 0x51, 0xbd, 0x6a, 0xfd, 0xe4, 0x25, 0xa5, 0x5f, 0x11, 0x3f, 0x98, 0x92, 0x51, 0x14, 0xc6, 0x5f, 0x3c, 0x0b, 0xa8, 0xf7, 0xc2, 0x81, 0x43, 0xde, 0x91, 0x73}}}, {{{0x3c, 0x8f, 0x9f, 0x33, 0x2a, 0x1f, 0x43, 0x33, 0x8f, 0x68, 0xff, 0x1f, 0x3d, 0x73, 0x6b, 0xbf, 0x68, 0xcc, 0x7d, 0x13, 0x6c, 0x24, 0x4b, 0xcc, 0x4d, 0x24, 0x0d, 0xfe, 0xde, 0x86, 0xad, 0x3b}} , {{0x79, 0x51, 0x81, 0x01, 0xdc, 0x73, 0x53, 0xe0, 0x6e, 0x9b, 0xea, 0x68, 0x3f, 0x5c, 0x14, 0x84, 0x53, 0x8d, 0x4b, 0xc0, 0x9f, 0x9f, 0x89, 0x2b, 0x8c, 0xba, 0x86, 0xfa, 0xf2, 0xcd, 0xe3, 0x2d}}}, {{{0x06, 0xf9, 0x29, 0x5a, 0xdb, 0x3d, 0x84, 0x52, 0xab, 0xcc, 0x6b, 0x60, 0x9d, 0xb7, 0x4a, 0x0e, 0x36, 0x63, 0x91, 0xad, 0xa0, 0x95, 0xb0, 0x97, 0x89, 0x4e, 0xcf, 0x7d, 0x3c, 0xe5, 0x7c, 0x28}} , {{0x2e, 0x69, 0x98, 0xfd, 0xc6, 0xbd, 0xcc, 0xca, 0xdf, 0x9a, 0x44, 0x7e, 0x9d, 0xca, 0x89, 0x6d, 0xbf, 0x27, 0xc2, 0xf8, 0xcd, 0x46, 0x00, 0x2b, 0xb5, 0x58, 0x4e, 0xb7, 0x89, 0x09, 0xe9, 0x2d}}}, {{{0x54, 0xbe, 0x75, 0xcb, 0x05, 0xb0, 0x54, 0xb7, 0xe7, 0x26, 0x86, 0x4a, 0xfc, 0x19, 0xcf, 0x27, 0x46, 0xd4, 0x22, 0x96, 0x5a, 0x11, 0xe8, 0xd5, 0x1b, 0xed, 0x71, 0xc5, 0x5d, 0xc8, 0xaf, 0x45}} , {{0x40, 0x7b, 0x77, 0x57, 0x49, 0x9e, 0x80, 0x39, 0x23, 0xee, 0x81, 0x0b, 0x22, 0xcf, 0xdb, 0x7a, 0x2f, 0x14, 0xb8, 0x57, 0x8f, 0xa1, 0x39, 0x1e, 0x77, 0xfc, 0x0b, 0xa6, 0xbf, 0x8a, 0x0c, 0x6c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x77, 0x3a, 0xd4, 0xd8, 0x27, 0xcf, 0xe8, 0xa1, 0x72, 0x9d, 0xca, 0xdd, 0x0d, 0x96, 0xda, 0x79, 0xed, 0x56, 0x42, 0x15, 0x60, 0xc7, 0x1c, 0x6b, 0x26, 0x30, 0xf6, 0x6a, 0x95, 0x67, 0xf3, 0x0a}} , {{0xc5, 0x08, 0xa4, 0x2b, 0x2f, 0xbd, 0x31, 0x81, 0x2a, 0xa6, 0xb6, 0xe4, 0x00, 0x91, 0xda, 0x3d, 0xb2, 0xb0, 0x96, 0xce, 0x8a, 0xd2, 0x8d, 0x70, 0xb3, 0xd3, 0x34, 0x01, 0x90, 0x8d, 0x10, 0x21}}}, {{{0x33, 0x0d, 0xe7, 0xba, 0x4f, 0x07, 0xdf, 0x8d, 0xea, 0x7d, 0xa0, 0xc5, 0xd6, 0xb1, 0xb0, 0xe5, 0x57, 0x1b, 0x5b, 0xf5, 0x45, 0x13, 0x14, 0x64, 0x5a, 0xeb, 0x5c, 0xfc, 0x54, 0x01, 0x76, 0x2b}} , {{0x02, 0x0c, 0xc2, 0xaf, 0x96, 0x36, 0xfe, 0x4a, 0xe2, 0x54, 0x20, 0x6a, 0xeb, 0xb2, 0x9f, 0x62, 0xd7, 0xce, 0xa2, 0x3f, 0x20, 0x11, 0x34, 0x37, 0xe0, 0x42, 0xed, 0x6f, 0xf9, 0x1a, 0xc8, 0x7d}}}, {{{0xd8, 0xb9, 0x11, 0xe8, 0x36, 0x3f, 0x42, 0xc1, 0xca, 0xdc, 0xd3, 0xf1, 0xc8, 0x23, 0x3d, 0x4f, 0x51, 0x7b, 0x9d, 0x8d, 0xd8, 0xe4, 0xa0, 0xaa, 0xf3, 0x04, 0xd6, 0x11, 0x93, 0xc8, 0x35, 0x45}} , {{0x61, 0x36, 0xd6, 0x08, 0x90, 0xbf, 0xa7, 0x7a, 0x97, 0x6c, 0x0f, 0x84, 0xd5, 0x33, 0x2d, 0x37, 0xc9, 0x6a, 0x80, 0x90, 0x3d, 0x0a, 0xa2, 0xaa, 0xe1, 0xb8, 0x84, 0xba, 0x61, 0x36, 0xdd, 0x69}}}, {{{0x6b, 0xdb, 0x5b, 0x9c, 0xc6, 0x92, 0xbc, 0x23, 0xaf, 0xc5, 0xb8, 0x75, 0xf8, 0x42, 0xfa, 0xd6, 0xb6, 0x84, 0x94, 0x63, 0x98, 0x93, 0x48, 0x78, 0x38, 0xcd, 0xbb, 0x18, 0x34, 0xc3, 0xdb, 0x67}} , {{0x96, 0xf3, 0x3a, 0x09, 0x56, 0xb0, 0x6f, 0x7c, 0x51, 0x1e, 0x1b, 0x39, 0x48, 0xea, 0xc9, 0x0c, 0x25, 0xa2, 0x7a, 0xca, 0xe7, 0x92, 0xfc, 0x59, 0x30, 0xa3, 0x89, 0x85, 0xdf, 0x6f, 0x43, 0x38}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x79, 0x84, 0x44, 0x19, 0xbd, 0xe9, 0x54, 0xc4, 0xc0, 0x6e, 0x2a, 0xa8, 0xa8, 0x9b, 0x43, 0xd5, 0x71, 0x22, 0x5f, 0xdc, 0x01, 0xfa, 0xdf, 0xb3, 0xb8, 0x47, 0x4b, 0x0a, 0xa5, 0x44, 0xea, 0x29}} , {{0x05, 0x90, 0x50, 0xaf, 0x63, 0x5f, 0x9d, 0x9e, 0xe1, 0x9d, 0x38, 0x97, 0x1f, 0x6c, 0xac, 0x30, 0x46, 0xb2, 0x6a, 0x19, 0xd1, 0x4b, 0xdb, 0xbb, 0x8c, 0xda, 0x2e, 0xab, 0xc8, 0x5a, 0x77, 0x6c}}}, {{{0x2b, 0xbe, 0xaf, 0xa1, 0x6d, 0x2f, 0x0b, 0xb1, 0x8f, 0xe3, 0xe0, 0x38, 0xcd, 0x0b, 0x41, 0x1b, 0x4a, 0x15, 0x07, 0xf3, 0x6f, 0xdc, 0xb8, 0xe9, 0xde, 0xb2, 0xa3, 0x40, 0x01, 0xa6, 0x45, 0x1e}} , {{0x76, 0x0a, 0xda, 0x8d, 0x2c, 0x07, 0x3f, 0x89, 0x7d, 0x04, 0xad, 0x43, 0x50, 0x6e, 0xd2, 0x47, 0xcb, 0x8a, 0xe6, 0x85, 0x1a, 0x24, 0xf3, 0xd2, 0x60, 0xfd, 0xdf, 0x73, 0xa4, 0x0d, 0x73, 0x0e}}}, {{{0xfd, 0x67, 0x6b, 0x71, 0x9b, 0x81, 0x53, 0x39, 0x39, 0xf4, 0xb8, 0xd5, 0xc3, 0x30, 0x9b, 0x3b, 0x7c, 0xa3, 0xf0, 0xd0, 0x84, 0x21, 0xd6, 0xbf, 0xb7, 0x4c, 0x87, 0x13, 0x45, 0x2d, 0xa7, 0x55}} , {{0x5d, 0x04, 0xb3, 0x40, 0x28, 0x95, 0x2d, 0x30, 0x83, 0xec, 0x5e, 0xe4, 0xff, 0x75, 0xfe, 0x79, 0x26, 0x9d, 0x1d, 0x36, 0xcd, 0x0a, 0x15, 0xd2, 0x24, 0x14, 0x77, 0x71, 0xd7, 0x8a, 0x1b, 0x04}}}, {{{0x5d, 0x93, 0xc9, 0xbe, 0xaa, 0x90, 0xcd, 0x9b, 0xfb, 0x73, 0x7e, 0xb0, 0x64, 0x98, 0x57, 0x44, 0x42, 0x41, 0xb1, 0xaf, 0xea, 0xc1, 0xc3, 0x22, 0xff, 0x60, 0x46, 0xcb, 0x61, 0x81, 0x70, 0x61}} , {{0x0d, 0x82, 0xb9, 0xfe, 0x21, 0xcd, 0xc4, 0xf5, 0x98, 0x0c, 0x4e, 0x72, 0xee, 0x87, 0x49, 0xf8, 0xa1, 0x95, 0xdf, 0x8f, 0x2d, 0xbd, 0x21, 0x06, 0x7c, 0x15, 0xe8, 0x12, 0x6d, 0x93, 0xd6, 0x38}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0xf7, 0x51, 0xd9, 0xef, 0x7d, 0x42, 0x01, 0x13, 0xe9, 0xb8, 0x7f, 0xa6, 0x49, 0x17, 0x64, 0x21, 0x80, 0x83, 0x2c, 0x63, 0x4c, 0x60, 0x09, 0x59, 0x91, 0x92, 0x77, 0x39, 0x51, 0xf4, 0x48}} , {{0x60, 0xd5, 0x22, 0x83, 0x08, 0x2f, 0xff, 0x99, 0x3e, 0x69, 0x6d, 0x88, 0xda, 0xe7, 0x5b, 0x52, 0x26, 0x31, 0x2a, 0xe5, 0x89, 0xde, 0x68, 0x90, 0xb6, 0x22, 0x5a, 0xbd, 0xd3, 0x85, 0x53, 0x31}}}, {{{0xd8, 0xce, 0xdc, 0xf9, 0x3c, 0x4b, 0xa2, 0x1d, 0x2c, 0x2f, 0x36, 0xbe, 0x7a, 0xfc, 0xcd, 0xbc, 0xdc, 0xf9, 0x30, 0xbd, 0xff, 0x05, 0xc7, 0xe4, 0x8e, 0x17, 0x62, 0xf8, 0x4d, 0xa0, 0x56, 0x79}} , {{0x82, 0xe7, 0xf6, 0xba, 0x53, 0x84, 0x0a, 0xa3, 0x34, 0xff, 0x3c, 0xa3, 0x6a, 0xa1, 0x37, 0xea, 0xdd, 0xb6, 0x95, 0xb3, 0x78, 0x19, 0x76, 0x1e, 0x55, 0x2f, 0x77, 0x2e, 0x7f, 0xc1, 0xea, 0x5e}}}, {{{0x83, 0xe1, 0x6e, 0xa9, 0x07, 0x33, 0x3e, 0x83, 0xff, 0xcb, 0x1c, 0x9f, 0xb1, 0xa3, 0xb4, 0xc9, 0xe1, 0x07, 0x97, 0xff, 0xf8, 0x23, 0x8f, 0xce, 0x40, 0xfd, 0x2e, 0x5e, 0xdb, 0x16, 0x43, 0x2d}} , {{0xba, 0x38, 0x02, 0xf7, 0x81, 0x43, 0x83, 0xa3, 0x20, 0x4f, 0x01, 0x3b, 0x8a, 0x04, 0x38, 0x31, 0xc6, 0x0f, 0xc8, 0xdf, 0xd7, 0xfa, 0x2f, 0x88, 0x3f, 0xfc, 0x0c, 0x76, 0xc4, 0xa6, 0x45, 0x72}}}, {{{0xbb, 0x0c, 0xbc, 0x6a, 0xa4, 0x97, 0x17, 0x93, 0x2d, 0x6f, 0xde, 0x72, 0x10, 0x1c, 0x08, 0x2c, 0x0f, 0x80, 0x32, 0x68, 0x27, 0xd4, 0xab, 0xdd, 0xc5, 0x58, 0x61, 0x13, 0x6d, 0x11, 0x1e, 0x4d}} , {{0x1a, 0xb9, 0xc9, 0x10, 0xfb, 0x1e, 0x4e, 0xf4, 0x84, 0x4b, 0x8a, 0x5e, 0x7b, 0x4b, 0xe8, 0x43, 0x8c, 0x8f, 0x00, 0xb5, 0x54, 0x13, 0xc5, 0x5c, 0xb6, 0x35, 0x4e, 0x9d, 0xe4, 0x5b, 0x41, 0x6d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x15, 0x7d, 0x12, 0x48, 0x82, 0x14, 0x42, 0xcd, 0x32, 0xd4, 0x4b, 0xc1, 0x72, 0x61, 0x2a, 0x8c, 0xec, 0xe2, 0xf8, 0x24, 0x45, 0x94, 0xe3, 0xbe, 0xdd, 0x67, 0xa8, 0x77, 0x5a, 0xae, 0x5b, 0x4b}} , {{0xcb, 0x77, 0x9a, 0x20, 0xde, 0xb8, 0x23, 0xd9, 0xa0, 0x0f, 0x8c, 0x7b, 0xa5, 0xcb, 0xae, 0xb6, 0xec, 0x42, 0x67, 0x0e, 0x58, 0xa4, 0x75, 0x98, 0x21, 0x71, 0x84, 0xb3, 0xe0, 0x76, 0x94, 0x73}}}, {{{0xdf, 0xfc, 0x69, 0x28, 0x23, 0x3f, 0x5b, 0xf8, 0x3b, 0x24, 0x37, 0xf3, 0x1d, 0xd5, 0x22, 0x6b, 0xd0, 0x98, 0xa8, 0x6c, 0xcf, 0xff, 0x06, 0xe1, 0x13, 0xdf, 0xb9, 0xc1, 0x0c, 0xa9, 0xbf, 0x33}} , {{0xd9, 0x81, 0xda, 0xb2, 0x4f, 0x82, 0x9d, 0x43, 0x81, 0x09, 0xf1, 0xd2, 0x01, 0xef, 0xac, 0xf4, 0x2d, 0x7d, 0x01, 0x09, 0xf1, 0xff, 0xa5, 0x9f, 0xe5, 0xca, 0x27, 0x63, 0xdb, 0x20, 0xb1, 0x53}}}, {{{0x67, 0x02, 0xe8, 0xad, 0xa9, 0x34, 0xd4, 0xf0, 0x15, 0x81, 0xaa, 0xc7, 0x4d, 0x87, 0x94, 0xea, 0x75, 0xe7, 0x4c, 0x94, 0x04, 0x0e, 0x69, 0x87, 0xe7, 0x51, 0x91, 0x10, 0x03, 0xc7, 0xbe, 0x56}} , {{0x32, 0xfb, 0x86, 0xec, 0x33, 0x6b, 0x2e, 0x51, 0x2b, 0xc8, 0xfa, 0x6c, 0x70, 0x47, 0x7e, 0xce, 0x05, 0x0c, 0x71, 0xf3, 0xb4, 0x56, 0xa6, 0xdc, 0xcc, 0x78, 0x07, 0x75, 0xd0, 0xdd, 0xb2, 0x6a}}}, {{{0xc6, 0xef, 0xb9, 0xc0, 0x2b, 0x22, 0x08, 0x1e, 0x71, 0x70, 0xb3, 0x35, 0x9c, 0x7a, 0x01, 0x92, 0x44, 0x9a, 0xf6, 0xb0, 0x58, 0x95, 0xc1, 0x9b, 0x02, 0xed, 0x2d, 0x7c, 0x34, 0x29, 0x49, 0x44}} , {{0x45, 0x62, 0x1d, 0x2e, 0xff, 0x2a, 0x1c, 0x21, 0xa4, 0x25, 0x7b, 0x0d, 0x8c, 0x15, 0x39, 0xfc, 0x8f, 0x7c, 0xa5, 0x7d, 0x1e, 0x25, 0xa3, 0x45, 0xd6, 0xab, 0xbd, 0xcb, 0xc5, 0x5e, 0x78, 0x77}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xd3, 0x42, 0xed, 0x1d, 0x00, 0x3c, 0x15, 0x2c, 0x9c, 0x77, 0x81, 0xd2, 0x73, 0xd1, 0x06, 0xd5, 0xc4, 0x7f, 0x94, 0xbb, 0x92, 0x2d, 0x2c, 0x4b, 0x45, 0x4b, 0xe9, 0x2a, 0x89, 0x6b, 0x2b}} , {{0xd2, 0x0c, 0x88, 0xc5, 0x48, 0x4d, 0xea, 0x0d, 0x4a, 0xc9, 0x52, 0x6a, 0x61, 0x79, 0xe9, 0x76, 0xf3, 0x85, 0x52, 0x5c, 0x1b, 0x2c, 0xe1, 0xd6, 0xc4, 0x0f, 0x18, 0x0e, 0x4e, 0xf6, 0x1c, 0x7f}}}, {{{0xb4, 0x04, 0x2e, 0x42, 0xcb, 0x1f, 0x2b, 0x11, 0x51, 0x7b, 0x08, 0xac, 0xaa, 0x3e, 0x9e, 0x52, 0x60, 0xb7, 0xc2, 0x61, 0x57, 0x8c, 0x84, 0xd5, 0x18, 0xa6, 0x19, 0xfc, 0xb7, 0x75, 0x91, 0x1b}} , {{0xe8, 0x68, 0xca, 0x44, 0xc8, 0x38, 0x38, 0xcc, 0x53, 0x0a, 0x32, 0x35, 0xcc, 0x52, 0xcb, 0x0e, 0xf7, 0xc5, 0xe7, 0xec, 0x3d, 0x85, 0xcc, 0x58, 0xe2, 0x17, 0x47, 0xff, 0x9f, 0xa5, 0x30, 0x17}}}, {{{0xe3, 0xae, 0xc8, 0xc1, 0x71, 0x75, 0x31, 0x00, 0x37, 0x41, 0x5c, 0x0e, 0x39, 0xda, 0x73, 0xa0, 0xc7, 0x97, 0x36, 0x6c, 0x5b, 0xf2, 0xee, 0x64, 0x0a, 0x3d, 0x89, 0x1e, 0x1d, 0x49, 0x8c, 0x37}} , {{0x4c, 0xe6, 0xb0, 0xc1, 0xa5, 0x2a, 0x82, 0x09, 0x08, 0xad, 0x79, 0x9c, 0x56, 0xf6, 0xf9, 0xc1, 0xd7, 0x7c, 0x39, 0x7f, 0x93, 0xca, 0x11, 0x55, 0xbf, 0x07, 0x1b, 0x82, 0x29, 0x69, 0x95, 0x5c}}}, {{{0x87, 0xee, 0xa6, 0x56, 0x9e, 0xc2, 0x9a, 0x56, 0x24, 0x42, 0x85, 0x4d, 0x98, 0x31, 0x1e, 0x60, 0x4d, 0x87, 0x85, 0x04, 0xae, 0x46, 0x12, 0xf9, 0x8e, 0x7f, 0xe4, 0x7f, 0xf6, 0x1c, 0x37, 0x01}} , {{0x73, 0x4c, 0xb6, 0xc5, 0xc4, 0xe9, 0x6c, 0x85, 0x48, 0x4a, 0x5a, 0xac, 0xd9, 0x1f, 0x43, 0xf8, 0x62, 0x5b, 0xee, 0x98, 0x2a, 0x33, 0x8e, 0x79, 0xce, 0x61, 0x06, 0x35, 0xd8, 0xd7, 0xca, 0x71}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x72, 0xd3, 0xae, 0xa6, 0xca, 0x8f, 0xcd, 0xcc, 0x78, 0x8e, 0x19, 0x4d, 0xa7, 0xd2, 0x27, 0xe9, 0xa4, 0x3c, 0x16, 0x5b, 0x84, 0x80, 0xf9, 0xd0, 0xcc, 0x6a, 0x1e, 0xca, 0x1e, 0x67, 0xbd, 0x63}} , {{0x7b, 0x6e, 0x2a, 0xd2, 0x87, 0x48, 0xff, 0xa1, 0xca, 0xe9, 0x15, 0x85, 0xdc, 0xdb, 0x2c, 0x39, 0x12, 0x91, 0xa9, 0x20, 0xaa, 0x4f, 0x29, 0xf4, 0x15, 0x7a, 0xd2, 0xf5, 0x32, 0xcc, 0x60, 0x04}}}, {{{0xe5, 0x10, 0x47, 0x3b, 0xfa, 0x90, 0xfc, 0x30, 0xb5, 0xea, 0x6f, 0x56, 0x8f, 0xfb, 0x0e, 0xa7, 0x3b, 0xc8, 0xb2, 0xff, 0x02, 0x7a, 0x33, 0x94, 0x93, 0x2a, 0x03, 0xe0, 0x96, 0x3a, 0x6c, 0x0f}} , {{0x5a, 0x63, 0x67, 0xe1, 0x9b, 0x47, 0x78, 0x9f, 0x38, 0x79, 0xac, 0x97, 0x66, 0x1d, 0x5e, 0x51, 0xee, 0x24, 0x42, 0xe8, 0x58, 0x4b, 0x8a, 0x03, 0x75, 0x86, 0x37, 0x86, 0xe2, 0x97, 0x4e, 0x3d}}}, {{{0x3f, 0x75, 0x8e, 0xb4, 0xff, 0xd8, 0xdd, 0xd6, 0x37, 0x57, 0x9d, 0x6d, 0x3b, 0xbd, 0xd5, 0x60, 0x88, 0x65, 0x9a, 0xb9, 0x4a, 0x68, 0x84, 0xa2, 0x67, 0xdd, 0x17, 0x25, 0x97, 0x04, 0x8b, 0x5e}} , {{0xbb, 0x40, 0x5e, 0xbc, 0x16, 0x92, 0x05, 0xc4, 0xc0, 0x4e, 0x72, 0x90, 0x0e, 0xab, 0xcf, 0x8a, 0xed, 0xef, 0xb9, 0x2d, 0x3b, 0xf8, 0x43, 0x5b, 0xba, 0x2d, 0xeb, 0x2f, 0x52, 0xd2, 0xd1, 0x5a}}}, {{{0x40, 0xb4, 0xab, 0xe6, 0xad, 0x9f, 0x46, 0x69, 0x4a, 0xb3, 0x8e, 0xaa, 0xea, 0x9c, 0x8a, 0x20, 0x16, 0x5d, 0x8c, 0x13, 0xbd, 0xf6, 0x1d, 0xc5, 0x24, 0xbd, 0x90, 0x2a, 0x1c, 0xc7, 0x13, 0x3b}} , {{0x54, 0xdc, 0x16, 0x0d, 0x18, 0xbe, 0x35, 0x64, 0x61, 0x52, 0x02, 0x80, 0xaf, 0x05, 0xf7, 0xa6, 0x42, 0xd3, 0x8f, 0x2e, 0x79, 0x26, 0xa8, 0xbb, 0xb2, 0x17, 0x48, 0xb2, 0x7a, 0x0a, 0x89, 0x14}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x20, 0xa8, 0x88, 0xe3, 0x91, 0xc0, 0x6e, 0xbb, 0x8a, 0x27, 0x82, 0x51, 0x83, 0xb2, 0x28, 0xa9, 0x83, 0xeb, 0xa6, 0xa9, 0x4d, 0x17, 0x59, 0x22, 0x54, 0x00, 0x50, 0x45, 0xcb, 0x48, 0x4b, 0x18}} , {{0x33, 0x7c, 0xe7, 0x26, 0xba, 0x4d, 0x32, 0xfe, 0x53, 0xf4, 0xfa, 0x83, 0xe3, 0xa5, 0x79, 0x66, 0x73, 0xef, 0x80, 0x23, 0x68, 0xc2, 0x60, 0xdd, 0xa9, 0x33, 0xdc, 0x03, 0x7a, 0xe0, 0xe0, 0x3e}}}, {{{0x34, 0x5c, 0x13, 0xfb, 0xc0, 0xe3, 0x78, 0x2b, 0x54, 0x58, 0x22, 0x9b, 0x76, 0x81, 0x7f, 0x93, 0x9c, 0x25, 0x3c, 0xd2, 0xe9, 0x96, 0x21, 0x26, 0x08, 0xf5, 0xed, 0x95, 0x11, 0xae, 0x04, 0x5a}} , {{0xb9, 0xe8, 0xc5, 0x12, 0x97, 0x1f, 0x83, 0xfe, 0x3e, 0x94, 0x99, 0xd4, 0x2d, 0xf9, 0x52, 0x59, 0x5c, 0x82, 0xa6, 0xf0, 0x75, 0x7e, 0xe8, 0xec, 0xcc, 0xac, 0x18, 0x21, 0x09, 0x67, 0x66, 0x67}}}, {{{0xb3, 0x40, 0x29, 0xd1, 0xcb, 0x1b, 0x08, 0x9e, 0x9c, 0xb7, 0x53, 0xb9, 0x3b, 0x71, 0x08, 0x95, 0x12, 0x1a, 0x58, 0xaf, 0x7e, 0x82, 0x52, 0x43, 0x4f, 0x11, 0x39, 0xf4, 0x93, 0x1a, 0x26, 0x05}} , {{0x6e, 0x44, 0xa3, 0xf9, 0x64, 0xaf, 0xe7, 0x6d, 0x7d, 0xdf, 0x1e, 0xac, 0x04, 0xea, 0x3b, 0x5f, 0x9b, 0xe8, 0x24, 0x9d, 0x0e, 0xe5, 0x2e, 0x3e, 0xdf, 0xa9, 0xf7, 0xd4, 0x50, 0x71, 0xf0, 0x78}}}, {{{0x3e, 0xa8, 0x38, 0xc2, 0x57, 0x56, 0x42, 0x9a, 0xb1, 0xe2, 0xf8, 0x45, 0xaa, 0x11, 0x48, 0x5f, 0x17, 0xc4, 0x54, 0x27, 0xdc, 0x5d, 0xaa, 0xdd, 0x41, 0xbc, 0xdf, 0x81, 0xb9, 0x53, 0xee, 0x52}} , {{0xc3, 0xf1, 0xa7, 0x6d, 0xb3, 0x5f, 0x92, 0x6f, 0xcc, 0x91, 0xb8, 0x95, 0x05, 0xdf, 0x3c, 0x64, 0x57, 0x39, 0x61, 0x51, 0xad, 0x8c, 0x38, 0x7b, 0xc8, 0xde, 0x00, 0x34, 0xbe, 0xa1, 0xb0, 0x7e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x24, 0x1d, 0x8a, 0x67, 0x20, 0xee, 0x42, 0xeb, 0x38, 0xed, 0x0b, 0x8b, 0xcd, 0x46, 0x9d, 0x5e, 0x6b, 0x1e, 0x24, 0x9d, 0x12, 0x05, 0x1a, 0xcc, 0x05, 0x4e, 0x92, 0x38, 0xe1, 0x1f, 0x50}} , {{0x4e, 0xee, 0x1c, 0x91, 0xe6, 0x11, 0xbd, 0x8e, 0x55, 0x1a, 0x18, 0x75, 0x66, 0xaf, 0x4d, 0x7b, 0x0f, 0xae, 0x6d, 0x85, 0xca, 0x82, 0x58, 0x21, 0x9c, 0x18, 0xe0, 0xed, 0xec, 0x22, 0x80, 0x2f}}}, {{{0x68, 0x3b, 0x0a, 0x39, 0x1d, 0x6a, 0x15, 0x57, 0xfc, 0xf0, 0x63, 0x54, 0xdb, 0x39, 0xdb, 0xe8, 0x5c, 0x64, 0xff, 0xa0, 0x09, 0x4f, 0x3b, 0xb7, 0x32, 0x60, 0x99, 0x94, 0xfd, 0x94, 0x82, 0x2d}} , {{0x24, 0xf6, 0x5a, 0x44, 0xf1, 0x55, 0x2c, 0xdb, 0xea, 0x7c, 0x84, 0x7c, 0x01, 0xac, 0xe3, 0xfd, 0xc9, 0x27, 0xc1, 0x5a, 0xb9, 0xde, 0x4f, 0x5a, 0x90, 0xdd, 0xc6, 0x67, 0xaa, 0x6f, 0x8a, 0x3a}}}, {{{0x78, 0x52, 0x87, 0xc9, 0x97, 0x63, 0xb1, 0xdd, 0x54, 0x5f, 0xc1, 0xf8, 0xf1, 0x06, 0xa6, 0xa8, 0xa3, 0x88, 0x82, 0xd4, 0xcb, 0xa6, 0x19, 0xdd, 0xd1, 0x11, 0x87, 0x08, 0x17, 0x4c, 0x37, 0x2a}} , {{0xa1, 0x0c, 0xf3, 0x08, 0x43, 0xd9, 0x24, 0x1e, 0x83, 0xa7, 0xdf, 0x91, 0xca, 0xbd, 0x69, 0x47, 0x8d, 0x1b, 0xe2, 0xb9, 0x4e, 0xb5, 0xe1, 0x76, 0xb3, 0x1c, 0x93, 0x03, 0xce, 0x5f, 0xb3, 0x5a}}}, {{{0x1d, 0xda, 0xe4, 0x61, 0x03, 0x50, 0xa9, 0x8b, 0x68, 0x18, 0xef, 0xb2, 0x1c, 0x84, 0x3b, 0xa2, 0x44, 0x95, 0xa3, 0x04, 0x3b, 0xd6, 0x99, 0x00, 0xaf, 0x76, 0x42, 0x67, 0x02, 0x7d, 0x85, 0x56}} , {{0xce, 0x72, 0x0e, 0x29, 0x84, 0xb2, 0x7d, 0xd2, 0x45, 0xbe, 0x57, 0x06, 0xed, 0x7f, 0xcf, 0xed, 0xcd, 0xef, 0x19, 0xd6, 0xbc, 0x15, 0x79, 0x64, 0xd2, 0x18, 0xe3, 0x20, 0x67, 0x3a, 0x54, 0x0b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x52, 0xfd, 0x04, 0xc5, 0xfb, 0x99, 0xe7, 0xe8, 0xfb, 0x8c, 0xe1, 0x42, 0x03, 0xef, 0x9d, 0xd9, 0x9e, 0x4d, 0xf7, 0x80, 0xcf, 0x2e, 0xcc, 0x9b, 0x45, 0xc9, 0x7b, 0x7a, 0xbc, 0x37, 0xa8, 0x52}} , {{0x96, 0x11, 0x41, 0x8a, 0x47, 0x91, 0xfe, 0xb6, 0xda, 0x7a, 0x54, 0x63, 0xd1, 0x14, 0x35, 0x05, 0x86, 0x8c, 0xa9, 0x36, 0x3f, 0xf2, 0x85, 0x54, 0x4e, 0x92, 0xd8, 0x85, 0x01, 0x46, 0xd6, 0x50}}}, {{{0x53, 0xcd, 0xf3, 0x86, 0x40, 0xe6, 0x39, 0x42, 0x95, 0xd6, 0xcb, 0x45, 0x1a, 0x20, 0xc8, 0x45, 0x4b, 0x32, 0x69, 0x04, 0xb1, 0xaf, 0x20, 0x46, 0xc7, 0x6b, 0x23, 0x5b, 0x69, 0xee, 0x30, 0x3f}} , {{0x70, 0x83, 0x47, 0xc0, 0xdb, 0x55, 0x08, 0xa8, 0x7b, 0x18, 0x6d, 0xf5, 0x04, 0x5a, 0x20, 0x0c, 0x4a, 0x8c, 0x60, 0xae, 0xae, 0x0f, 0x64, 0x55, 0x55, 0x2e, 0xd5, 0x1d, 0x53, 0x31, 0x42, 0x41}}}, {{{0xca, 0xfc, 0x88, 0x6b, 0x96, 0x78, 0x0a, 0x8b, 0x83, 0xdc, 0xbc, 0xaf, 0x40, 0xb6, 0x8d, 0x7f, 0xef, 0xb4, 0xd1, 0x3f, 0xcc, 0xa2, 0x74, 0xc9, 0xc2, 0x92, 0x55, 0x00, 0xab, 0xdb, 0xbf, 0x4f}} , {{0x93, 0x1c, 0x06, 0x2d, 0x66, 0x65, 0x02, 0xa4, 0x97, 0x18, 0xfd, 0x00, 0xe7, 0xab, 0x03, 0xec, 0xce, 0xc1, 0xbf, 0x37, 0xf8, 0x13, 0x53, 0xa5, 0xe5, 0x0c, 0x3a, 0xa8, 0x55, 0xb9, 0xff, 0x68}}}, {{{0xe4, 0xe6, 0x6d, 0x30, 0x7d, 0x30, 0x35, 0xc2, 0x78, 0x87, 0xf9, 0xfc, 0x6b, 0x5a, 0xc3, 0xb7, 0x65, 0xd8, 0x2e, 0xc7, 0xa5, 0x0c, 0xc6, 0xdc, 0x12, 0xaa, 0xd6, 0x4f, 0xc5, 0x38, 0xbc, 0x0e}} , {{0xe2, 0x3c, 0x76, 0x86, 0x38, 0xf2, 0x7b, 0x2c, 0x16, 0x78, 0x8d, 0xf5, 0xa4, 0x15, 0xda, 0xdb, 0x26, 0x85, 0xa0, 0x56, 0xdd, 0x1d, 0xe3, 0xb3, 0xfd, 0x40, 0xef, 0xf2, 0xd9, 0xa1, 0xb3, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x49, 0x0e, 0xe6, 0x58, 0x10, 0x7a, 0x52, 0xda, 0xb5, 0x7d, 0x37, 0x6a, 0x3e, 0xa1, 0x78, 0xce, 0xc7, 0x1c, 0x24, 0x23, 0xdb, 0x7d, 0xfb, 0x8c, 0x8d, 0xdc, 0x30, 0x67, 0x69, 0x75, 0x3b}} , {{0xa9, 0xea, 0x6d, 0x16, 0x16, 0x60, 0xf4, 0x60, 0x87, 0x19, 0x44, 0x8c, 0x4a, 0x8b, 0x3e, 0xfb, 0x16, 0x00, 0x00, 0x54, 0xa6, 0x9e, 0x9f, 0xef, 0xcf, 0xd9, 0xd2, 0x4c, 0x74, 0x31, 0xd0, 0x34}}}, {{{0xa4, 0xeb, 0x04, 0xa4, 0x8c, 0x8f, 0x71, 0x27, 0x95, 0x85, 0x5d, 0x55, 0x4b, 0xb1, 0x26, 0x26, 0xc8, 0xae, 0x6a, 0x7d, 0xa2, 0x21, 0xca, 0xce, 0x38, 0xab, 0x0f, 0xd0, 0xd5, 0x2b, 0x6b, 0x00}} , {{0xe5, 0x67, 0x0c, 0xf1, 0x3a, 0x9a, 0xea, 0x09, 0x39, 0xef, 0xd1, 0x30, 0xbc, 0x33, 0xba, 0xb1, 0x6a, 0xc5, 0x27, 0x08, 0x7f, 0x54, 0x80, 0x3d, 0xab, 0xf6, 0x15, 0x7a, 0xc2, 0x40, 0x73, 0x72}}}, {{{0x84, 0x56, 0x82, 0xb6, 0x12, 0x70, 0x7f, 0xf7, 0xf0, 0xbd, 0x5b, 0xa9, 0xd5, 0xc5, 0x5f, 0x59, 0xbf, 0x7f, 0xb3, 0x55, 0x22, 0x02, 0xc9, 0x44, 0x55, 0x87, 0x8f, 0x96, 0x98, 0x64, 0x6d, 0x15}} , {{0xb0, 0x8b, 0xaa, 0x1e, 0xec, 0xc7, 0xa5, 0x8f, 0x1f, 0x92, 0x04, 0xc6, 0x05, 0xf6, 0xdf, 0xa1, 0xcc, 0x1f, 0x81, 0xf5, 0x0e, 0x9c, 0x57, 0xdc, 0xe3, 0xbb, 0x06, 0x87, 0x1e, 0xfe, 0x23, 0x6c}}}, {{{0xd8, 0x2b, 0x5b, 0x16, 0xea, 0x20, 0xf1, 0xd3, 0x68, 0x8f, 0xae, 0x5b, 0xd0, 0xa9, 0x1a, 0x19, 0xa8, 0x36, 0xfb, 0x2b, 0x57, 0x88, 0x7d, 0x90, 0xd5, 0xa6, 0xf3, 0xdc, 0x38, 0x89, 0x4e, 0x1f}} , {{0xcc, 0x19, 0xda, 0x9b, 0x3b, 0x43, 0x48, 0x21, 0x2e, 0x23, 0x4d, 0x3d, 0xae, 0xf8, 0x8c, 0xfc, 0xdd, 0xa6, 0x74, 0x37, 0x65, 0xca, 0xee, 0x1a, 0x19, 0x8e, 0x9f, 0x64, 0x6f, 0x0c, 0x8b, 0x5a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0xb9, 0xc2, 0xf0, 0x72, 0xb8, 0x15, 0x16, 0xcc, 0x8d, 0x3c, 0x6f, 0x25, 0xed, 0xf4, 0x46, 0x2e, 0x0c, 0x60, 0x0f, 0xe2, 0x84, 0x34, 0x55, 0x89, 0x59, 0x34, 0x1b, 0xf5, 0x8d, 0xfe, 0x08}} , {{0xf8, 0xab, 0x93, 0xbc, 0x44, 0xba, 0x1b, 0x75, 0x4b, 0x49, 0x6f, 0xd0, 0x54, 0x2e, 0x63, 0xba, 0xb5, 0xea, 0xed, 0x32, 0x14, 0xc9, 0x94, 0xd8, 0xc5, 0xce, 0xf4, 0x10, 0x68, 0xe0, 0x38, 0x27}}}, {{{0x74, 0x1c, 0x14, 0x9b, 0xd4, 0x64, 0x61, 0x71, 0x5a, 0xb6, 0x21, 0x33, 0x4f, 0xf7, 0x8e, 0xba, 0xa5, 0x48, 0x9a, 0xc7, 0xfa, 0x9a, 0xf0, 0xb4, 0x62, 0xad, 0xf2, 0x5e, 0xcc, 0x03, 0x24, 0x1a}} , {{0xf5, 0x76, 0xfd, 0xe4, 0xaf, 0xb9, 0x03, 0x59, 0xce, 0x63, 0xd2, 0x3b, 0x1f, 0xcd, 0x21, 0x0c, 0xad, 0x44, 0xa5, 0x97, 0xac, 0x80, 0x11, 0x02, 0x9b, 0x0c, 0xe5, 0x8b, 0xcd, 0xfb, 0x79, 0x77}}}, {{{0x15, 0xbe, 0x9a, 0x0d, 0xba, 0x38, 0x72, 0x20, 0x8a, 0xf5, 0xbe, 0x59, 0x93, 0x79, 0xb7, 0xf6, 0x6a, 0x0c, 0x38, 0x27, 0x1a, 0x60, 0xf4, 0x86, 0x3b, 0xab, 0x5a, 0x00, 0xa0, 0xce, 0x21, 0x7d}} , {{0x6c, 0xba, 0x14, 0xc5, 0xea, 0x12, 0x9e, 0x2e, 0x82, 0x63, 0xce, 0x9b, 0x4a, 0xe7, 0x1d, 0xec, 0xf1, 0x2e, 0x51, 0x1c, 0xf4, 0xd0, 0x69, 0x15, 0x42, 0x9d, 0xa3, 0x3f, 0x0e, 0xbf, 0xe9, 0x5c}}}, {{{0xe4, 0x0d, 0xf4, 0xbd, 0xee, 0x31, 0x10, 0xed, 0xcb, 0x12, 0x86, 0xad, 0xd4, 0x2f, 0x90, 0x37, 0x32, 0xc3, 0x0b, 0x73, 0xec, 0x97, 0x85, 0xa4, 0x01, 0x1c, 0x76, 0x35, 0xfe, 0x75, 0xdd, 0x71}} , {{0x11, 0xa4, 0x88, 0x9f, 0x3e, 0x53, 0x69, 0x3b, 0x1b, 0xe0, 0xf7, 0xba, 0x9b, 0xad, 0x4e, 0x81, 0x5f, 0xb5, 0x5c, 0xae, 0xbe, 0x67, 0x86, 0x37, 0x34, 0x8e, 0x07, 0x32, 0x45, 0x4a, 0x67, 0x39}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x70, 0x58, 0x20, 0x03, 0x1e, 0x67, 0xb2, 0xc8, 0x9b, 0x58, 0xc5, 0xb1, 0xeb, 0x2d, 0x4a, 0xde, 0x82, 0x8c, 0xf2, 0xd2, 0x14, 0xb8, 0x70, 0x61, 0x4e, 0x73, 0xd6, 0x0b, 0x6b, 0x0d, 0x30}} , {{0x81, 0xfc, 0x55, 0x5c, 0xbf, 0xa7, 0xc4, 0xbd, 0xe2, 0xf0, 0x4b, 0x8f, 0xe9, 0x7d, 0x99, 0xfa, 0xd3, 0xab, 0xbc, 0xc7, 0x83, 0x2b, 0x04, 0x7f, 0x0c, 0x19, 0x43, 0x03, 0x3d, 0x07, 0xca, 0x40}}}, {{{0xf9, 0xc8, 0xbe, 0x8c, 0x16, 0x81, 0x39, 0x96, 0xf6, 0x17, 0x58, 0xc8, 0x30, 0x58, 0xfb, 0xc2, 0x03, 0x45, 0xd2, 0x52, 0x76, 0xe0, 0x6a, 0x26, 0x28, 0x5c, 0x88, 0x59, 0x6a, 0x5a, 0x54, 0x42}} , {{0x07, 0xb5, 0x2e, 0x2c, 0x67, 0x15, 0x9b, 0xfb, 0x83, 0x69, 0x1e, 0x0f, 0xda, 0xd6, 0x29, 0xb1, 0x60, 0xe0, 0xb2, 0xba, 0x69, 0xa2, 0x9e, 0xbd, 0xbd, 0xe0, 0x1c, 0xbd, 0xcd, 0x06, 0x64, 0x70}}}, {{{0x41, 0xfa, 0x8c, 0xe1, 0x89, 0x8f, 0x27, 0xc8, 0x25, 0x8f, 0x6f, 0x5f, 0x55, 0xf8, 0xde, 0x95, 0x6d, 0x2f, 0x75, 0x16, 0x2b, 0x4e, 0x44, 0xfd, 0x86, 0x6e, 0xe9, 0x70, 0x39, 0x76, 0x97, 0x7e}} , {{0x17, 0x62, 0x6b, 0x14, 0xa1, 0x7c, 0xd0, 0x79, 0x6e, 0xd8, 0x8a, 0xa5, 0x6d, 0x8c, 0x93, 0xd2, 0x3f, 0xec, 0x44, 0x8d, 0x6e, 0x91, 0x01, 0x8c, 0x8f, 0xee, 0x01, 0x8f, 0xc0, 0xb4, 0x85, 0x0e}}}, {{{0x02, 0x3a, 0x70, 0x41, 0xe4, 0x11, 0x57, 0x23, 0xac, 0xe6, 0xfc, 0x54, 0x7e, 0xcd, 0xd7, 0x22, 0xcb, 0x76, 0x9f, 0x20, 0xce, 0xa0, 0x73, 0x76, 0x51, 0x3b, 0xa4, 0xf8, 0xe3, 0x62, 0x12, 0x6c}} , {{0x7f, 0x00, 0x9c, 0x26, 0x0d, 0x6f, 0x48, 0x7f, 0x3a, 0x01, 0xed, 0xc5, 0x96, 0xb0, 0x1f, 0x4f, 0xa8, 0x02, 0x62, 0x27, 0x8a, 0x50, 0x8d, 0x9a, 0x8b, 0x52, 0x0f, 0x1e, 0xcf, 0x41, 0x38, 0x19}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf5, 0x6c, 0xd4, 0x2f, 0x0f, 0x69, 0x0f, 0x87, 0x3f, 0x61, 0x65, 0x1e, 0x35, 0x34, 0x85, 0xba, 0x02, 0x30, 0xac, 0x25, 0x3d, 0xe2, 0x62, 0xf1, 0xcc, 0xe9, 0x1b, 0xc2, 0xef, 0x6a, 0x42, 0x57}} , {{0x34, 0x1f, 0x2e, 0xac, 0xd1, 0xc7, 0x04, 0x52, 0x32, 0x66, 0xb2, 0x33, 0x73, 0x21, 0x34, 0x54, 0xf7, 0x71, 0xed, 0x06, 0xb0, 0xff, 0xa6, 0x59, 0x6f, 0x8a, 0x4e, 0xfb, 0x02, 0xb0, 0x45, 0x6b}}}, {{{0xf5, 0x48, 0x0b, 0x03, 0xc5, 0x22, 0x7d, 0x80, 0x08, 0x53, 0xfe, 0x32, 0xb1, 0xa1, 0x8a, 0x74, 0x6f, 0xbd, 0x3f, 0x85, 0xf4, 0xcf, 0xf5, 0x60, 0xaf, 0x41, 0x7e, 0x3e, 0x46, 0xa3, 0x5a, 0x20}} , {{0xaa, 0x35, 0x87, 0x44, 0x63, 0x66, 0x97, 0xf8, 0x6e, 0x55, 0x0c, 0x04, 0x3e, 0x35, 0x50, 0xbf, 0x93, 0x69, 0xd2, 0x8b, 0x05, 0x55, 0x99, 0xbe, 0xe2, 0x53, 0x61, 0xec, 0xe8, 0x08, 0x0b, 0x32}}}, {{{0xb3, 0x10, 0x45, 0x02, 0x69, 0x59, 0x2e, 0x97, 0xd9, 0x64, 0xf8, 0xdb, 0x25, 0x80, 0xdc, 0xc4, 0xd5, 0x62, 0x3c, 0xed, 0x65, 0x91, 0xad, 0xd1, 0x57, 0x81, 0x94, 0xaa, 0xa1, 0x29, 0xfc, 0x68}} , {{0xdd, 0xb5, 0x7d, 0xab, 0x5a, 0x21, 0x41, 0x53, 0xbb, 0x17, 0x79, 0x0d, 0xd1, 0xa8, 0x0c, 0x0c, 0x20, 0x88, 0x09, 0xe9, 0x84, 0xe8, 0x25, 0x11, 0x67, 0x7a, 0x8b, 0x1a, 0xe4, 0x5d, 0xe1, 0x5d}}}, {{{0x37, 0xea, 0xfe, 0x65, 0x3b, 0x25, 0xe8, 0xe1, 0xc2, 0xc5, 0x02, 0xa4, 0xbe, 0x98, 0x0a, 0x2b, 0x61, 0xc1, 0x9b, 0xe2, 0xd5, 0x92, 0xe6, 0x9e, 0x7d, 0x1f, 0xca, 0x43, 0x88, 0x8b, 0x2c, 0x59}} , {{0xe0, 0xb5, 0x00, 0x1d, 0x2a, 0x6f, 0xaf, 0x79, 0x86, 0x2f, 0xa6, 0x5a, 0x93, 0xd1, 0xfe, 0xae, 0x3a, 0xee, 0xdb, 0x7c, 0x61, 0xbe, 0x7c, 0x01, 0xf9, 0xfe, 0x52, 0xdc, 0xd8, 0x52, 0xa3, 0x42}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x22, 0xaf, 0x13, 0x37, 0xbd, 0x37, 0x71, 0xac, 0x04, 0x46, 0x63, 0xac, 0xa4, 0x77, 0xed, 0x25, 0x38, 0xe0, 0x15, 0xa8, 0x64, 0x00, 0x0d, 0xce, 0x51, 0x01, 0xa9, 0xbc, 0x0f, 0x03, 0x1c, 0x04}} , {{0x89, 0xf9, 0x80, 0x07, 0xcf, 0x3f, 0xb3, 0xe9, 0xe7, 0x45, 0x44, 0x3d, 0x2a, 0x7c, 0xe9, 0xe4, 0x16, 0x5c, 0x5e, 0x65, 0x1c, 0xc7, 0x7d, 0xc6, 0x7a, 0xfb, 0x43, 0xee, 0x25, 0x76, 0x46, 0x72}}}, {{{0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62}} , {{0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03}}}, {{{0x51, 0x16, 0x50, 0x7c, 0xd5, 0x5d, 0xf6, 0x99, 0xe8, 0x77, 0x72, 0x4e, 0xfa, 0x62, 0xcb, 0x76, 0x75, 0x0c, 0xe2, 0x71, 0x98, 0x92, 0xd5, 0xfa, 0x45, 0xdf, 0x5c, 0x6f, 0x1e, 0x9e, 0x28, 0x69}} , {{0x0d, 0xac, 0x66, 0x6d, 0xc3, 0x8b, 0xba, 0x16, 0xb5, 0xe2, 0xa0, 0x0d, 0x0c, 0xbd, 0xa4, 0x8e, 0x18, 0x6c, 0xf2, 0xdc, 0xf9, 0xdc, 0x4a, 0x86, 0x25, 0x95, 0x14, 0xcb, 0xd8, 0x1a, 0x04, 0x0f}}}, {{{0x97, 0xa5, 0xdb, 0x8b, 0x2d, 0xaa, 0x42, 0x11, 0x09, 0xf2, 0x93, 0xbb, 0xd9, 0x06, 0x84, 0x4e, 0x11, 0xa8, 0xa0, 0x25, 0x2b, 0xa6, 0x5f, 0xae, 0xc4, 0xb4, 0x4c, 0xc8, 0xab, 0xc7, 0x3b, 0x02}} , {{0xee, 0xc9, 0x29, 0x0f, 0xdf, 0x11, 0x85, 0xed, 0xce, 0x0d, 0x62, 0x2c, 0x8f, 0x4b, 0xf9, 0x04, 0xe9, 0x06, 0x72, 0x1d, 0x37, 0x20, 0x50, 0xc9, 0x14, 0xeb, 0xec, 0x39, 0xa7, 0x97, 0x2b, 0x4d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x69, 0xd1, 0x39, 0xbd, 0xfb, 0x33, 0xbe, 0xc4, 0xf0, 0x5c, 0xef, 0xf0, 0x56, 0x68, 0xfc, 0x97, 0x47, 0xc8, 0x72, 0xb6, 0x53, 0xa4, 0x0a, 0x98, 0xa5, 0xb4, 0x37, 0x71, 0xcf, 0x66, 0x50, 0x6d}} , {{0x17, 0xa4, 0x19, 0x52, 0x11, 0x47, 0xb3, 0x5c, 0x5b, 0xa9, 0x2e, 0x22, 0xb4, 0x00, 0x52, 0xf9, 0x57, 0x18, 0xb8, 0xbe, 0x5a, 0xe3, 0xab, 0x83, 0xc8, 0x87, 0x0a, 0x2a, 0xd8, 0x8c, 0xbb, 0x54}}}, {{{0xa9, 0x62, 0x93, 0x85, 0xbe, 0xe8, 0x73, 0x4a, 0x0e, 0xb0, 0xb5, 0x2d, 0x94, 0x50, 0xaa, 0xd3, 0xb2, 0xea, 0x9d, 0x62, 0x76, 0x3b, 0x07, 0x34, 0x4e, 0x2d, 0x70, 0xc8, 0x9a, 0x15, 0x66, 0x6b}} , {{0xc5, 0x96, 0xca, 0xc8, 0x22, 0x1a, 0xee, 0x5f, 0xe7, 0x31, 0x60, 0x22, 0x83, 0x08, 0x63, 0xce, 0xb9, 0x32, 0x44, 0x58, 0x5d, 0x3a, 0x9b, 0xe4, 0x04, 0xd5, 0xef, 0x38, 0xef, 0x4b, 0xdd, 0x19}}}, {{{0x4d, 0xc2, 0x17, 0x75, 0xa1, 0x68, 0xcd, 0xc3, 0xc6, 0x03, 0x44, 0xe3, 0x78, 0x09, 0x91, 0x47, 0x3f, 0x0f, 0xe4, 0x92, 0x58, 0xfa, 0x7d, 0x1f, 0x20, 0x94, 0x58, 0x5e, 0xbc, 0x19, 0x02, 0x6f}} , {{0x20, 0xd6, 0xd8, 0x91, 0x54, 0xa7, 0xf3, 0x20, 0x4b, 0x34, 0x06, 0xfa, 0x30, 0xc8, 0x6f, 0x14, 0x10, 0x65, 0x74, 0x13, 0x4e, 0xf0, 0x69, 0x26, 0xce, 0xcf, 0x90, 0xf4, 0xd0, 0xc5, 0xc8, 0x64}}}, {{{0x26, 0xa2, 0x50, 0x02, 0x24, 0x72, 0xf1, 0xf0, 0x4e, 0x2d, 0x93, 0xd5, 0x08, 0xe7, 0xae, 0x38, 0xf7, 0x18, 0xa5, 0x32, 0x34, 0xc2, 0xf0, 0xa6, 0xec, 0xb9, 0x61, 0x7b, 0x64, 0x99, 0xac, 0x71}} , {{0x25, 0xcf, 0x74, 0x55, 0x1b, 0xaa, 0xa9, 0x38, 0x41, 0x40, 0xd5, 0x95, 0x95, 0xab, 0x1c, 0x5e, 0xbc, 0x41, 0x7e, 0x14, 0x30, 0xbe, 0x13, 0x89, 0xf4, 0xe5, 0xeb, 0x28, 0xc0, 0xc2, 0x96, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x77, 0x45, 0xec, 0x67, 0x76, 0x32, 0x4c, 0xb9, 0xdf, 0x25, 0x32, 0x6b, 0xcb, 0xe7, 0x14, 0x61, 0x43, 0xee, 0xba, 0x9b, 0x71, 0xef, 0xd2, 0x48, 0x65, 0xbb, 0x1b, 0x8a, 0x13, 0x1b, 0x22}} , {{0x84, 0xad, 0x0c, 0x18, 0x38, 0x5a, 0xba, 0xd0, 0x98, 0x59, 0xbf, 0x37, 0xb0, 0x4f, 0x97, 0x60, 0x20, 0xb3, 0x9b, 0x97, 0xf6, 0x08, 0x6c, 0xa4, 0xff, 0xfb, 0xb7, 0xfa, 0x95, 0xb2, 0x51, 0x79}}}, {{{0x28, 0x5c, 0x3f, 0xdb, 0x6b, 0x18, 0x3b, 0x5c, 0xd1, 0x04, 0x28, 0xde, 0x85, 0x52, 0x31, 0xb5, 0xbb, 0xf6, 0xa9, 0xed, 0xbe, 0x28, 0x4f, 0xb3, 0x7e, 0x05, 0x6a, 0xdb, 0x95, 0x0d, 0x1b, 0x1c}} , {{0xd5, 0xc5, 0xc3, 0x9a, 0x0a, 0xd0, 0x31, 0x3e, 0x07, 0x36, 0x8e, 0xc0, 0x8a, 0x62, 0xb1, 0xca, 0xd6, 0x0e, 0x1e, 0x9d, 0xef, 0xab, 0x98, 0x4d, 0xbb, 0x6c, 0x05, 0xe0, 0xe4, 0x5d, 0xbd, 0x57}}}, {{{0xcc, 0x21, 0x27, 0xce, 0xfd, 0xa9, 0x94, 0x8e, 0xe1, 0xab, 0x49, 0xe0, 0x46, 0x26, 0xa1, 0xa8, 0x8c, 0xa1, 0x99, 0x1d, 0xb4, 0x27, 0x6d, 0x2d, 0xc8, 0x39, 0x30, 0x5e, 0x37, 0x52, 0xc4, 0x6e}} , {{0xa9, 0x85, 0xf4, 0xe7, 0xb0, 0x15, 0x33, 0x84, 0x1b, 0x14, 0x1a, 0x02, 0xd9, 0x3b, 0xad, 0x0f, 0x43, 0x6c, 0xea, 0x3e, 0x0f, 0x7e, 0xda, 0xdd, 0x6b, 0x4c, 0x7f, 0x6e, 0xd4, 0x6b, 0xbf, 0x0f}}}, {{{0x47, 0x9f, 0x7c, 0x56, 0x7c, 0x43, 0x91, 0x1c, 0xbb, 0x4e, 0x72, 0x3e, 0x64, 0xab, 0xa0, 0xa0, 0xdf, 0xb4, 0xd8, 0x87, 0x3a, 0xbd, 0xa8, 0x48, 0xc9, 0xb8, 0xef, 0x2e, 0xad, 0x6f, 0x84, 0x4f}} , {{0x2d, 0x2d, 0xf0, 0x1b, 0x7e, 0x2a, 0x6c, 0xf8, 0xa9, 0x6a, 0xe1, 0xf0, 0x99, 0xa1, 0x67, 0x9a, 0xd4, 0x13, 0xca, 0xca, 0xba, 0x27, 0x92, 0xaa, 0xa1, 0x5d, 0x50, 0xde, 0xcc, 0x40, 0x26, 0x0a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9f, 0x3e, 0xf2, 0xb2, 0x90, 0xce, 0xdb, 0x64, 0x3e, 0x03, 0xdd, 0x37, 0x36, 0x54, 0x70, 0x76, 0x24, 0xb5, 0x69, 0x03, 0xfc, 0xa0, 0x2b, 0x74, 0xb2, 0x05, 0x0e, 0xcc, 0xd8, 0x1f, 0x6a, 0x1f}} , {{0x19, 0x5e, 0x60, 0x69, 0x58, 0x86, 0xa0, 0x31, 0xbd, 0x32, 0xe9, 0x2c, 0x5c, 0xd2, 0x85, 0xba, 0x40, 0x64, 0xa8, 0x74, 0xf8, 0x0e, 0x1c, 0xb3, 0xa9, 0x69, 0xe8, 0x1e, 0x40, 0x64, 0x99, 0x77}}}, {{{0x6c, 0x32, 0x4f, 0xfd, 0xbb, 0x5c, 0xbb, 0x8d, 0x64, 0x66, 0x4a, 0x71, 0x1f, 0x79, 0xa3, 0xad, 0x8d, 0xf9, 0xd4, 0xec, 0xcf, 0x67, 0x70, 0xfa, 0x05, 0x4a, 0x0f, 0x6e, 0xaf, 0x87, 0x0a, 0x6f}} , {{0xc6, 0x36, 0x6e, 0x6c, 0x8c, 0x24, 0x09, 0x60, 0xbe, 0x26, 0xd2, 0x4c, 0x5e, 0x17, 0xca, 0x5f, 0x1d, 0xcc, 0x87, 0xe8, 0x42, 0x6a, 0xcb, 0xcb, 0x7d, 0x92, 0x05, 0x35, 0x81, 0x13, 0x60, 0x6b}}}, {{{0xf4, 0x15, 0xcd, 0x0f, 0x0a, 0xaf, 0x4e, 0x6b, 0x51, 0xfd, 0x14, 0xc4, 0x2e, 0x13, 0x86, 0x74, 0x44, 0xcb, 0x66, 0x6b, 0xb6, 0x9d, 0x74, 0x56, 0x32, 0xac, 0x8d, 0x8e, 0x8c, 0x8c, 0x8c, 0x39}} , {{0xca, 0x59, 0x74, 0x1a, 0x11, 0xef, 0x6d, 0xf7, 0x39, 0x5c, 0x3b, 0x1f, 0xfa, 0xe3, 0x40, 0x41, 0x23, 0x9e, 0xf6, 0xd1, 0x21, 0xa2, 0xbf, 0xad, 0x65, 0x42, 0x6b, 0x59, 0x8a, 0xe8, 0xc5, 0x7f}}}, {{{0x64, 0x05, 0x7a, 0x84, 0x4a, 0x13, 0xc3, 0xf6, 0xb0, 0x6e, 0x9a, 0x6b, 0x53, 0x6b, 0x32, 0xda, 0xd9, 0x74, 0x75, 0xc4, 0xba, 0x64, 0x3d, 0x3b, 0x08, 0xdd, 0x10, 0x46, 0xef, 0xc7, 0x90, 0x1f}} , {{0x7b, 0x2f, 0x3a, 0xce, 0xc8, 0xa1, 0x79, 0x3c, 0x30, 0x12, 0x44, 0x28, 0xf6, 0xbc, 0xff, 0xfd, 0xf4, 0xc0, 0x97, 0xb0, 0xcc, 0xc3, 0x13, 0x7a, 0xb9, 0x9a, 0x16, 0xe4, 0xcb, 0x4c, 0x34, 0x63}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x07, 0x4e, 0xd3, 0x2d, 0x09, 0x33, 0x0e, 0xd2, 0x0d, 0xbe, 0x3e, 0xe7, 0xe4, 0xaa, 0xb7, 0x00, 0x8b, 0xe8, 0xad, 0xaa, 0x7a, 0x8d, 0x34, 0x28, 0xa9, 0x81, 0x94, 0xc5, 0xe7, 0x42, 0xac, 0x47}} , {{0x24, 0x89, 0x7a, 0x8f, 0xb5, 0x9b, 0xf0, 0xc2, 0x03, 0x64, 0xd0, 0x1e, 0xf5, 0xa4, 0xb2, 0xf3, 0x74, 0xe9, 0x1a, 0x16, 0xfd, 0xcb, 0x15, 0xea, 0xeb, 0x10, 0x6c, 0x35, 0xd1, 0xc1, 0xa6, 0x28}}}, {{{0xcc, 0xd5, 0x39, 0xfc, 0xa5, 0xa4, 0xad, 0x32, 0x15, 0xce, 0x19, 0xe8, 0x34, 0x2b, 0x1c, 0x60, 0x91, 0xfc, 0x05, 0xa9, 0xb3, 0xdc, 0x80, 0x29, 0xc4, 0x20, 0x79, 0x06, 0x39, 0xc0, 0xe2, 0x22}} , {{0xbb, 0xa8, 0xe1, 0x89, 0x70, 0x57, 0x18, 0x54, 0x3c, 0xf6, 0x0d, 0x82, 0x12, 0x05, 0x87, 0x96, 0x06, 0x39, 0xe3, 0xf8, 0xb3, 0x95, 0xe5, 0xd7, 0x26, 0xbf, 0x09, 0x5a, 0x94, 0xf9, 0x1c, 0x63}}}, {{{0x2b, 0x8c, 0x2d, 0x9a, 0x8b, 0x84, 0xf2, 0x56, 0xfb, 0xad, 0x2e, 0x7f, 0xb7, 0xfc, 0x30, 0xe1, 0x35, 0x89, 0xba, 0x4d, 0xa8, 0x6d, 0xce, 0x8c, 0x8b, 0x30, 0xe0, 0xda, 0x29, 0x18, 0x11, 0x17}} , {{0x19, 0xa6, 0x5a, 0x65, 0x93, 0xc3, 0xb5, 0x31, 0x22, 0x4f, 0xf3, 0xf6, 0x0f, 0xeb, 0x28, 0xc3, 0x7c, 0xeb, 0xce, 0x86, 0xec, 0x67, 0x76, 0x6e, 0x35, 0x45, 0x7b, 0xd8, 0x6b, 0x92, 0x01, 0x65}}}, {{{0x3d, 0xd5, 0x9a, 0x64, 0x73, 0x36, 0xb1, 0xd6, 0x86, 0x98, 0x42, 0x3f, 0x8a, 0xf1, 0xc7, 0xf5, 0x42, 0xa8, 0x9c, 0x52, 0xa8, 0xdc, 0xf9, 0x24, 0x3f, 0x4a, 0xa1, 0xa4, 0x5b, 0xe8, 0x62, 0x1a}} , {{0xc5, 0xbd, 0xc8, 0x14, 0xd5, 0x0d, 0xeb, 0xe1, 0xa5, 0xe6, 0x83, 0x11, 0x09, 0x00, 0x1d, 0x55, 0x83, 0x51, 0x7e, 0x75, 0x00, 0x81, 0xb9, 0xcb, 0xd8, 0xc5, 0xe5, 0xa1, 0xd9, 0x17, 0x6d, 0x1f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xea, 0xf9, 0xe4, 0xe9, 0xe1, 0x52, 0x3f, 0x51, 0x19, 0x0d, 0xdd, 0xd9, 0x9d, 0x93, 0x31, 0x87, 0x23, 0x09, 0xd5, 0x83, 0xeb, 0x92, 0x09, 0x76, 0x6e, 0xe3, 0xf8, 0xc0, 0xa2, 0x66, 0xb5, 0x36}} , {{0x3a, 0xbb, 0x39, 0xed, 0x32, 0x02, 0xe7, 0x43, 0x7a, 0x38, 0x14, 0x84, 0xe3, 0x44, 0xd2, 0x5e, 0x94, 0xdd, 0x78, 0x89, 0x55, 0x4c, 0x73, 0x9e, 0xe1, 0xe4, 0x3e, 0x43, 0xd0, 0x4a, 0xde, 0x1b}}}, {{{0xb2, 0xe7, 0x8f, 0xe3, 0xa3, 0xc5, 0xcb, 0x72, 0xee, 0x79, 0x41, 0xf8, 0xdf, 0xee, 0x65, 0xc5, 0x45, 0x77, 0x27, 0x3c, 0xbd, 0x58, 0xd3, 0x75, 0xe2, 0x04, 0x4b, 0xbb, 0x65, 0xf3, 0xc8, 0x0f}} , {{0x24, 0x7b, 0x93, 0x34, 0xb5, 0xe2, 0x74, 0x48, 0xcd, 0xa0, 0x0b, 0x92, 0x97, 0x66, 0x39, 0xf4, 0xb0, 0xe2, 0x5d, 0x39, 0x6a, 0x5b, 0x45, 0x17, 0x78, 0x1e, 0xdb, 0x91, 0x81, 0x1c, 0xf9, 0x16}}}, {{{0x16, 0xdf, 0xd1, 0x5a, 0xd5, 0xe9, 0x4e, 0x58, 0x95, 0x93, 0x5f, 0x51, 0x09, 0xc3, 0x2a, 0xc9, 0xd4, 0x55, 0x48, 0x79, 0xa4, 0xa3, 0xb2, 0xc3, 0x62, 0xaa, 0x8c, 0xe8, 0xad, 0x47, 0x39, 0x1b}} , {{0x46, 0xda, 0x9e, 0x51, 0x3a, 0xe6, 0xd1, 0xa6, 0xbb, 0x4d, 0x7b, 0x08, 0xbe, 0x8c, 0xd5, 0xf3, 0x3f, 0xfd, 0xf7, 0x44, 0x80, 0x2d, 0x53, 0x4b, 0xd0, 0x87, 0x68, 0xc1, 0xb5, 0xd8, 0xf7, 0x07}}}, {{{0xf4, 0x10, 0x46, 0xbe, 0xb7, 0xd2, 0xd1, 0xce, 0x5e, 0x76, 0xa2, 0xd7, 0x03, 0xdc, 0xe4, 0x81, 0x5a, 0xf6, 0x3c, 0xde, 0xae, 0x7a, 0x9d, 0x21, 0x34, 0xa5, 0xf6, 0xa9, 0x73, 0xe2, 0x8d, 0x60}} , {{0xfa, 0x44, 0x71, 0xf6, 0x41, 0xd8, 0xc6, 0x58, 0x13, 0x37, 0xeb, 0x84, 0x0f, 0x96, 0xc7, 0xdc, 0xc8, 0xa9, 0x7a, 0x83, 0xb2, 0x2f, 0x31, 0xb1, 0x1a, 0xd8, 0x98, 0x3f, 0x11, 0xd0, 0x31, 0x3b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x81, 0xd5, 0x34, 0x16, 0x01, 0xa3, 0x93, 0xea, 0x52, 0x94, 0xec, 0x93, 0xb7, 0x81, 0x11, 0x2d, 0x58, 0xf9, 0xb5, 0x0a, 0xaa, 0x4f, 0xf6, 0x2e, 0x3f, 0x36, 0xbf, 0x33, 0x5a, 0xe7, 0xd1, 0x08}} , {{0x1a, 0xcf, 0x42, 0xae, 0xcc, 0xb5, 0x77, 0x39, 0xc4, 0x5b, 0x5b, 0xd0, 0x26, 0x59, 0x27, 0xd0, 0x55, 0x71, 0x12, 0x9d, 0x88, 0x3d, 0x9c, 0xea, 0x41, 0x6a, 0xf0, 0x50, 0x93, 0x93, 0xdd, 0x47}}}, {{{0x6f, 0xc9, 0x51, 0x6d, 0x1c, 0xaa, 0xf5, 0xa5, 0x90, 0x3f, 0x14, 0xe2, 0x6e, 0x8e, 0x64, 0xfd, 0xac, 0xe0, 0x4e, 0x22, 0xe5, 0xc1, 0xbc, 0x29, 0x0a, 0x6a, 0x9e, 0xa1, 0x60, 0xcb, 0x2f, 0x0b}} , {{0xdc, 0x39, 0x32, 0xf3, 0xa1, 0x44, 0xe9, 0xc5, 0xc3, 0x78, 0xfb, 0x95, 0x47, 0x34, 0x35, 0x34, 0xe8, 0x25, 0xde, 0x93, 0xc6, 0xb4, 0x76, 0x6d, 0x86, 0x13, 0xc6, 0xe9, 0x68, 0xb5, 0x01, 0x63}}}, {{{0x1f, 0x9a, 0x52, 0x64, 0x97, 0xd9, 0x1c, 0x08, 0x51, 0x6f, 0x26, 0x9d, 0xaa, 0x93, 0x33, 0x43, 0xfa, 0x77, 0xe9, 0x62, 0x9b, 0x5d, 0x18, 0x75, 0xeb, 0x78, 0xf7, 0x87, 0x8f, 0x41, 0xb4, 0x4d}} , {{0x13, 0xa8, 0x82, 0x3e, 0xe9, 0x13, 0xad, 0xeb, 0x01, 0xca, 0xcf, 0xda, 0xcd, 0xf7, 0x6c, 0xc7, 0x7a, 0xdc, 0x1e, 0x6e, 0xc8, 0x4e, 0x55, 0x62, 0x80, 0xea, 0x78, 0x0c, 0x86, 0xb9, 0x40, 0x51}}}, {{{0x27, 0xae, 0xd3, 0x0d, 0x4c, 0x8f, 0x34, 0xea, 0x7d, 0x3c, 0xe5, 0x8a, 0xcf, 0x5b, 0x92, 0xd8, 0x30, 0x16, 0xb4, 0xa3, 0x75, 0xff, 0xeb, 0x27, 0xc8, 0x5c, 0x6c, 0xc2, 0xee, 0x6c, 0x21, 0x0b}} , {{0xc3, 0xba, 0x12, 0x53, 0x2a, 0xaa, 0x77, 0xad, 0x19, 0x78, 0x55, 0x8a, 0x2e, 0x60, 0x87, 0xc2, 0x6e, 0x91, 0x38, 0x91, 0x3f, 0x7a, 0xc5, 0x24, 0x8f, 0x51, 0xc5, 0xde, 0xb0, 0x53, 0x30, 0x56}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x02, 0xfe, 0x54, 0x12, 0x18, 0xca, 0x7d, 0xa5, 0x68, 0x43, 0xa3, 0x6d, 0x14, 0x2a, 0x6a, 0xa5, 0x8e, 0x32, 0xe7, 0x63, 0x4f, 0xe3, 0xc6, 0x44, 0x3e, 0xab, 0x63, 0xca, 0x17, 0x86, 0x74, 0x3f}} , {{0x1e, 0x64, 0xc1, 0x7d, 0x52, 0xdc, 0x13, 0x5a, 0xa1, 0x9c, 0x4e, 0xee, 0x99, 0x28, 0xbb, 0x4c, 0xee, 0xac, 0xa9, 0x1b, 0x89, 0xa2, 0x38, 0x39, 0x7b, 0xc4, 0x0f, 0x42, 0xe6, 0x89, 0xed, 0x0f}}}, {{{0xf3, 0x3c, 0x8c, 0x80, 0x83, 0x10, 0x8a, 0x37, 0x50, 0x9c, 0xb4, 0xdf, 0x3f, 0x8c, 0xf7, 0x23, 0x07, 0xd6, 0xff, 0xa0, 0x82, 0x6c, 0x75, 0x3b, 0xe4, 0xb5, 0xbb, 0xe4, 0xe6, 0x50, 0xf0, 0x08}} , {{0x62, 0xee, 0x75, 0x48, 0x92, 0x33, 0xf2, 0xf4, 0xad, 0x15, 0x7a, 0xa1, 0x01, 0x46, 0xa9, 0x32, 0x06, 0x88, 0xb6, 0x36, 0x47, 0x35, 0xb9, 0xb4, 0x42, 0x85, 0x76, 0xf0, 0x48, 0x00, 0x90, 0x38}}}, {{{0x51, 0x15, 0x9d, 0xc3, 0x95, 0xd1, 0x39, 0xbb, 0x64, 0x9d, 0x15, 0x81, 0xc1, 0x68, 0xd0, 0xb6, 0xa4, 0x2c, 0x7d, 0x5e, 0x02, 0x39, 0x00, 0xe0, 0x3b, 0xa4, 0xcc, 0xca, 0x1d, 0x81, 0x24, 0x10}} , {{0xe7, 0x29, 0xf9, 0x37, 0xd9, 0x46, 0x5a, 0xcd, 0x70, 0xfe, 0x4d, 0x5b, 0xbf, 0xa5, 0xcf, 0x91, 0xf4, 0xef, 0xee, 0x8a, 0x29, 0xd0, 0xe7, 0xc4, 0x25, 0x92, 0x8a, 0xff, 0x36, 0xfc, 0xe4, 0x49}}}, {{{0xbd, 0x00, 0xb9, 0x04, 0x7d, 0x35, 0xfc, 0xeb, 0xd0, 0x0b, 0x05, 0x32, 0x52, 0x7a, 0x89, 0x24, 0x75, 0x50, 0xe1, 0x63, 0x02, 0x82, 0x8e, 0xe7, 0x85, 0x0c, 0xf2, 0x56, 0x44, 0x37, 0x83, 0x25}} , {{0x8f, 0xa1, 0xce, 0xcb, 0x60, 0xda, 0x12, 0x02, 0x1e, 0x29, 0x39, 0x2a, 0x03, 0xb7, 0xeb, 0x77, 0x40, 0xea, 0xc9, 0x2b, 0x2c, 0xd5, 0x7d, 0x7e, 0x2c, 0xc7, 0x5a, 0xfd, 0xff, 0xc4, 0xd1, 0x62}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x1d, 0x88, 0x98, 0x5b, 0x4e, 0xfc, 0x41, 0x24, 0x05, 0xe6, 0x50, 0x2b, 0xae, 0x96, 0x51, 0xd9, 0x6b, 0x72, 0xb2, 0x33, 0x42, 0x98, 0x68, 0xbb, 0x10, 0x5a, 0x7a, 0x8c, 0x9d, 0x07, 0xb4, 0x05}} , {{0x2f, 0x61, 0x9f, 0xd7, 0xa8, 0x3f, 0x83, 0x8c, 0x10, 0x69, 0x90, 0xe6, 0xcf, 0xd2, 0x63, 0xa3, 0xe4, 0x54, 0x7e, 0xe5, 0x69, 0x13, 0x1c, 0x90, 0x57, 0xaa, 0xe9, 0x53, 0x22, 0x43, 0x29, 0x23}}}, {{{0xe5, 0x1c, 0xf8, 0x0a, 0xfd, 0x2d, 0x7e, 0xf5, 0xf5, 0x70, 0x7d, 0x41, 0x6b, 0x11, 0xfe, 0xbe, 0x99, 0xd1, 0x55, 0x29, 0x31, 0xbf, 0xc0, 0x97, 0x6c, 0xd5, 0x35, 0xcc, 0x5e, 0x8b, 0xd9, 0x69}} , {{0x8e, 0x4e, 0x9f, 0x25, 0xf8, 0x81, 0x54, 0x2d, 0x0e, 0xd5, 0x54, 0x81, 0x9b, 0xa6, 0x92, 0xce, 0x4b, 0xe9, 0x8f, 0x24, 0x3b, 0xca, 0xe0, 0x44, 0xab, 0x36, 0xfe, 0xfb, 0x87, 0xd4, 0x26, 0x3e}}}, {{{0x0f, 0x93, 0x9c, 0x11, 0xe7, 0xdb, 0xf1, 0xf0, 0x85, 0x43, 0x28, 0x15, 0x37, 0xdd, 0xde, 0x27, 0xdf, 0xad, 0x3e, 0x49, 0x4f, 0xe0, 0x5b, 0xf6, 0x80, 0x59, 0x15, 0x3c, 0x85, 0xb7, 0x3e, 0x12}} , {{0xf5, 0xff, 0xcc, 0xf0, 0xb4, 0x12, 0x03, 0x5f, 0xc9, 0x84, 0xcb, 0x1d, 0x17, 0xe0, 0xbc, 0xcc, 0x03, 0x62, 0xa9, 0x8b, 0x94, 0xa6, 0xaa, 0x18, 0xcb, 0x27, 0x8d, 0x49, 0xa6, 0x17, 0x15, 0x07}}}, {{{0xd9, 0xb6, 0xd4, 0x9d, 0xd4, 0x6a, 0xaf, 0x70, 0x07, 0x2c, 0x10, 0x9e, 0xbd, 0x11, 0xad, 0xe4, 0x26, 0x33, 0x70, 0x92, 0x78, 0x1c, 0x74, 0x9f, 0x75, 0x60, 0x56, 0xf4, 0x39, 0xa8, 0xa8, 0x62}} , {{0x3b, 0xbf, 0x55, 0x35, 0x61, 0x8b, 0x44, 0x97, 0xe8, 0x3a, 0x55, 0xc1, 0xc8, 0x3b, 0xfd, 0x95, 0x29, 0x11, 0x60, 0x96, 0x1e, 0xcb, 0x11, 0x9d, 0xc2, 0x03, 0x8a, 0x1b, 0xc6, 0xd6, 0x45, 0x3d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x7e, 0x0e, 0x50, 0xb2, 0xcc, 0x0d, 0x6b, 0xa6, 0x71, 0x5b, 0x42, 0xed, 0xbd, 0xaf, 0xac, 0xf0, 0xfc, 0x12, 0xa2, 0x3f, 0x4e, 0xda, 0xe8, 0x11, 0xf3, 0x23, 0xe1, 0x04, 0x62, 0x03, 0x1c, 0x4e}} , {{0xc8, 0xb1, 0x1b, 0x6f, 0x73, 0x61, 0x3d, 0x27, 0x0d, 0x7d, 0x7a, 0x25, 0x5f, 0x73, 0x0e, 0x2f, 0x93, 0xf6, 0x24, 0xd8, 0x4f, 0x90, 0xac, 0xa2, 0x62, 0x0a, 0xf0, 0x61, 0xd9, 0x08, 0x59, 0x6a}}}, {{{0x6f, 0x2d, 0x55, 0xf8, 0x2f, 0x8e, 0xf0, 0x18, 0x3b, 0xea, 0xdd, 0x26, 0x72, 0xd1, 0xf5, 0xfe, 0xe5, 0xb8, 0xe6, 0xd3, 0x10, 0x48, 0x46, 0x49, 0x3a, 0x9f, 0x5e, 0x45, 0x6b, 0x90, 0xe8, 0x7f}} , {{0xd3, 0x76, 0x69, 0x33, 0x7b, 0xb9, 0x40, 0x70, 0xee, 0xa6, 0x29, 0x6b, 0xdd, 0xd0, 0x5d, 0x8d, 0xc1, 0x3e, 0x4a, 0xea, 0x37, 0xb1, 0x03, 0x02, 0x03, 0x35, 0xf1, 0x28, 0x9d, 0xff, 0x00, 0x13}}}, {{{0x7a, 0xdb, 0x12, 0xd2, 0x8a, 0x82, 0x03, 0x1b, 0x1e, 0xaf, 0xf9, 0x4b, 0x9c, 0xbe, 0xae, 0x7c, 0xe4, 0x94, 0x2a, 0x23, 0xb3, 0x62, 0x86, 0xe7, 0xfd, 0x23, 0xaa, 0x99, 0xbd, 0x2b, 0x11, 0x6c}} , {{0x8d, 0xa6, 0xd5, 0xac, 0x9d, 0xcc, 0x68, 0x75, 0x7f, 0xc3, 0x4d, 0x4b, 0xdd, 0x6c, 0xbb, 0x11, 0x5a, 0x60, 0xe5, 0xbd, 0x7d, 0x27, 0x8b, 0xda, 0xb4, 0x95, 0xf6, 0x03, 0x27, 0xa4, 0x92, 0x3f}}}, {{{0x22, 0xd6, 0xb5, 0x17, 0x84, 0xbf, 0x12, 0xcc, 0x23, 0x14, 0x4a, 0xdf, 0x14, 0x31, 0xbc, 0xa1, 0xac, 0x6e, 0xab, 0xfa, 0x57, 0x11, 0x53, 0xb3, 0x27, 0xe6, 0xf9, 0x47, 0x33, 0x44, 0x34, 0x1e}} , {{0x79, 0xfc, 0xa6, 0xb4, 0x0b, 0x35, 0x20, 0xc9, 0x4d, 0x22, 0x84, 0xc4, 0xa9, 0x20, 0xec, 0x89, 0x94, 0xba, 0x66, 0x56, 0x48, 0xb9, 0x87, 0x7f, 0xca, 0x1e, 0x06, 0xed, 0xa5, 0x55, 0x59, 0x29}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x56, 0xe1, 0xf5, 0xf1, 0xd5, 0xab, 0xa8, 0x2b, 0xae, 0x89, 0xf3, 0xcf, 0x56, 0x9f, 0xf2, 0x4b, 0x31, 0xbc, 0x18, 0xa9, 0x06, 0x5b, 0xbe, 0xb4, 0x61, 0xf8, 0xb2, 0x06, 0x9c, 0x81, 0xab, 0x4c}} , {{0x1f, 0x68, 0x76, 0x01, 0x16, 0x38, 0x2b, 0x0f, 0x77, 0x97, 0x92, 0x67, 0x4e, 0x86, 0x6a, 0x8b, 0xe5, 0xe8, 0x0c, 0xf7, 0x36, 0x39, 0xb5, 0x33, 0xe6, 0xcf, 0x5e, 0xbd, 0x18, 0xfb, 0x10, 0x1f}}}, {{{0x83, 0xf0, 0x0d, 0x63, 0xef, 0x53, 0x6b, 0xb5, 0x6b, 0xf9, 0x83, 0xcf, 0xde, 0x04, 0x22, 0x9b, 0x2c, 0x0a, 0xe0, 0xa5, 0xd8, 0xc7, 0x9c, 0xa5, 0xa3, 0xf6, 0x6f, 0xcf, 0x90, 0x6b, 0x68, 0x7c}} , {{0x33, 0x15, 0xd7, 0x7f, 0x1a, 0xd5, 0x21, 0x58, 0xc4, 0x18, 0xa5, 0xf0, 0xcc, 0x73, 0xa8, 0xfd, 0xfa, 0x18, 0xd1, 0x03, 0x91, 0x8d, 0x52, 0xd2, 0xa3, 0xa4, 0xd3, 0xb1, 0xea, 0x1d, 0x0f, 0x00}}}, {{{0xcc, 0x48, 0x83, 0x90, 0xe5, 0xfd, 0x3f, 0x84, 0xaa, 0xf9, 0x8b, 0x82, 0x59, 0x24, 0x34, 0x68, 0x4f, 0x1c, 0x23, 0xd9, 0xcc, 0x71, 0xe1, 0x7f, 0x8c, 0xaf, 0xf1, 0xee, 0x00, 0xb6, 0xa0, 0x77}} , {{0xf5, 0x1a, 0x61, 0xf7, 0x37, 0x9d, 0x00, 0xf4, 0xf2, 0x69, 0x6f, 0x4b, 0x01, 0x85, 0x19, 0x45, 0x4d, 0x7f, 0x02, 0x7c, 0x6a, 0x05, 0x47, 0x6c, 0x1f, 0x81, 0x20, 0xd4, 0xe8, 0x50, 0x27, 0x72}}}, {{{0x2c, 0x3a, 0xe5, 0xad, 0xf4, 0xdd, 0x2d, 0xf7, 0x5c, 0x44, 0xb5, 0x5b, 0x21, 0xa3, 0x89, 0x5f, 0x96, 0x45, 0xca, 0x4d, 0xa4, 0x21, 0x99, 0x70, 0xda, 0xc4, 0xc4, 0xa0, 0xe5, 0xf4, 0xec, 0x0a}} , {{0x07, 0x68, 0x21, 0x65, 0xe9, 0x08, 0xa0, 0x0b, 0x6a, 0x4a, 0xba, 0xb5, 0x80, 0xaf, 0xd0, 0x1b, 0xc5, 0xf5, 0x4b, 0x73, 0x50, 0x60, 0x2d, 0x71, 0x69, 0x61, 0x0e, 0xc0, 0x20, 0x40, 0x30, 0x19}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0x75, 0x57, 0x3b, 0xeb, 0x5c, 0x14, 0x56, 0x50, 0xc9, 0x4f, 0xb8, 0xb8, 0x1e, 0xa3, 0xf4, 0xab, 0xf5, 0xa9, 0x20, 0x15, 0x94, 0x82, 0xda, 0x96, 0x1c, 0x9b, 0x59, 0x8c, 0xff, 0xf4, 0x51}} , {{0xc1, 0x3a, 0x86, 0xd7, 0xb0, 0x06, 0x84, 0x7f, 0x1b, 0xbd, 0xd4, 0x07, 0x78, 0x80, 0x2e, 0xb1, 0xb4, 0xee, 0x52, 0x38, 0xee, 0x9a, 0xf9, 0xf6, 0xf3, 0x41, 0x6e, 0xd4, 0x88, 0x95, 0xac, 0x35}}}, {{{0x41, 0x97, 0xbf, 0x71, 0x6a, 0x9b, 0x72, 0xec, 0xf3, 0xf8, 0x6b, 0xe6, 0x0e, 0x6c, 0x69, 0xa5, 0x2f, 0x68, 0x52, 0xd8, 0x61, 0x81, 0xc0, 0x63, 0x3f, 0xa6, 0x3c, 0x13, 0x90, 0xe6, 0x8d, 0x56}} , {{0xe8, 0x39, 0x30, 0x77, 0x23, 0xb1, 0xfd, 0x1b, 0x3d, 0x3e, 0x74, 0x4d, 0x7f, 0xae, 0x5b, 0x3a, 0xb4, 0x65, 0x0e, 0x3a, 0x43, 0xdc, 0xdc, 0x41, 0x47, 0xe6, 0xe8, 0x92, 0x09, 0x22, 0x48, 0x4c}}}, {{{0x85, 0x57, 0x9f, 0xb5, 0xc8, 0x06, 0xb2, 0x9f, 0x47, 0x3f, 0xf0, 0xfa, 0xe6, 0xa9, 0xb1, 0x9b, 0x6f, 0x96, 0x7d, 0xf9, 0xa4, 0x65, 0x09, 0x75, 0x32, 0xa6, 0x6c, 0x7f, 0x47, 0x4b, 0x2f, 0x4f}} , {{0x34, 0xe9, 0x59, 0x93, 0x9d, 0x26, 0x80, 0x54, 0xf2, 0xcc, 0x3c, 0xc2, 0x25, 0x85, 0xe3, 0x6a, 0xc1, 0x62, 0x04, 0xa7, 0x08, 0x32, 0x6d, 0xa1, 0x39, 0x84, 0x8a, 0x3b, 0x87, 0x5f, 0x11, 0x13}}}, {{{0xda, 0x03, 0x34, 0x66, 0xc4, 0x0c, 0x73, 0x6e, 0xbc, 0x24, 0xb5, 0xf9, 0x70, 0x81, 0x52, 0xe9, 0xf4, 0x7c, 0x23, 0xdd, 0x9f, 0xb8, 0x46, 0xef, 0x1d, 0x22, 0x55, 0x7d, 0x71, 0xc4, 0x42, 0x33}} , {{0xc5, 0x37, 0x69, 0x5b, 0xa8, 0xc6, 0x9d, 0xa4, 0xfc, 0x61, 0x6e, 0x68, 0x46, 0xea, 0xd7, 0x1c, 0x67, 0xd2, 0x7d, 0xfa, 0xf1, 0xcc, 0x54, 0x8d, 0x36, 0x35, 0xc9, 0x00, 0xdf, 0x6c, 0x67, 0x50}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9a, 0x4d, 0x42, 0x29, 0x5d, 0xa4, 0x6b, 0x6f, 0xa8, 0x8a, 0x4d, 0x91, 0x7b, 0xd2, 0xdf, 0x36, 0xef, 0x01, 0x22, 0xc5, 0xcc, 0x8d, 0xeb, 0x58, 0x3d, 0xb3, 0x50, 0xfc, 0x8b, 0x97, 0x96, 0x33}} , {{0x93, 0x33, 0x07, 0xc8, 0x4a, 0xca, 0xd0, 0xb1, 0xab, 0xbd, 0xdd, 0xa7, 0x7c, 0xac, 0x3e, 0x45, 0xcb, 0xcc, 0x07, 0x91, 0xbf, 0x35, 0x9d, 0xcb, 0x7d, 0x12, 0x3c, 0x11, 0x59, 0x13, 0xcf, 0x5c}}}, {{{0x45, 0xb8, 0x41, 0xd7, 0xab, 0x07, 0x15, 0x00, 0x8e, 0xce, 0xdf, 0xb2, 0x43, 0x5c, 0x01, 0xdc, 0xf4, 0x01, 0x51, 0x95, 0x10, 0x5a, 0xf6, 0x24, 0x24, 0xa0, 0x19, 0x3a, 0x09, 0x2a, 0xaa, 0x3f}} , {{0xdc, 0x8e, 0xeb, 0xc6, 0xbf, 0xdd, 0x11, 0x7b, 0xe7, 0x47, 0xe6, 0xce, 0xe7, 0xb6, 0xc5, 0xe8, 0x8a, 0xdc, 0x4b, 0x57, 0x15, 0x3b, 0x66, 0xca, 0x89, 0xa3, 0xfd, 0xac, 0x0d, 0xe1, 0x1d, 0x7a}}}, {{{0x89, 0xef, 0xbf, 0x03, 0x75, 0xd0, 0x29, 0x50, 0xcb, 0x7d, 0xd6, 0xbe, 0xad, 0x5f, 0x7b, 0x00, 0x32, 0xaa, 0x98, 0xed, 0x3f, 0x8f, 0x92, 0xcb, 0x81, 0x56, 0x01, 0x63, 0x64, 0xa3, 0x38, 0x39}} , {{0x8b, 0xa4, 0xd6, 0x50, 0xb4, 0xaa, 0x5d, 0x64, 0x64, 0x76, 0x2e, 0xa1, 0xa6, 0xb3, 0xb8, 0x7c, 0x7a, 0x56, 0xf5, 0x5c, 0x4e, 0x84, 0x5c, 0xfb, 0xdd, 0xca, 0x48, 0x8b, 0x48, 0xb9, 0xba, 0x34}}}, {{{0xc5, 0xe3, 0xe8, 0xae, 0x17, 0x27, 0xe3, 0x64, 0x60, 0x71, 0x47, 0x29, 0x02, 0x0f, 0x92, 0x5d, 0x10, 0x93, 0xc8, 0x0e, 0xa1, 0xed, 0xba, 0xa9, 0x96, 0x1c, 0xc5, 0x76, 0x30, 0xcd, 0xf9, 0x30}} , {{0x95, 0xb0, 0xbd, 0x8c, 0xbc, 0xa7, 0x4f, 0x7e, 0xfd, 0x4e, 0x3a, 0xbf, 0x5f, 0x04, 0x79, 0x80, 0x2b, 0x5a, 0x9f, 0x4f, 0x68, 0x21, 0x19, 0x71, 0xc6, 0x20, 0x01, 0x42, 0xaa, 0xdf, 0xae, 0x2c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x90, 0x6e, 0x7e, 0x4b, 0x71, 0x93, 0xc0, 0x72, 0xed, 0xeb, 0x71, 0x24, 0x97, 0x26, 0x9c, 0xfe, 0xcb, 0x3e, 0x59, 0x19, 0xa8, 0x0f, 0x75, 0x7d, 0xbe, 0x18, 0xe6, 0x96, 0x1e, 0x95, 0x70, 0x60}} , {{0x89, 0x66, 0x3e, 0x1d, 0x4c, 0x5f, 0xfe, 0xc0, 0x04, 0x43, 0xd6, 0x44, 0x19, 0xb5, 0xad, 0xc7, 0x22, 0xdc, 0x71, 0x28, 0x64, 0xde, 0x41, 0x38, 0x27, 0x8f, 0x2c, 0x6b, 0x08, 0xb8, 0xb8, 0x7b}}}, {{{0x3d, 0x70, 0x27, 0x9d, 0xd9, 0xaf, 0xb1, 0x27, 0xaf, 0xe3, 0x5d, 0x1e, 0x3a, 0x30, 0x54, 0x61, 0x60, 0xe8, 0xc3, 0x26, 0x3a, 0xbc, 0x7e, 0xf5, 0x81, 0xdd, 0x64, 0x01, 0x04, 0xeb, 0xc0, 0x1e}} , {{0xda, 0x2c, 0xa4, 0xd1, 0xa1, 0xc3, 0x5c, 0x6e, 0x32, 0x07, 0x1f, 0xb8, 0x0e, 0x19, 0x9e, 0x99, 0x29, 0x33, 0x9a, 0xae, 0x7a, 0xed, 0x68, 0x42, 0x69, 0x7c, 0x07, 0xb3, 0x38, 0x2c, 0xf6, 0x3d}}}, {{{0x64, 0xaa, 0xb5, 0x88, 0x79, 0x65, 0x38, 0x8c, 0x94, 0xd6, 0x62, 0x37, 0x7d, 0x64, 0xcd, 0x3a, 0xeb, 0xff, 0xe8, 0x81, 0x09, 0xc7, 0x6a, 0x50, 0x09, 0x0d, 0x28, 0x03, 0x0d, 0x9a, 0x93, 0x0a}} , {{0x42, 0xa3, 0xf1, 0xc5, 0xb4, 0x0f, 0xd8, 0xc8, 0x8d, 0x15, 0x31, 0xbd, 0xf8, 0x07, 0x8b, 0xcd, 0x08, 0x8a, 0xfb, 0x18, 0x07, 0xfe, 0x8e, 0x52, 0x86, 0xef, 0xbe, 0xec, 0x49, 0x52, 0x99, 0x08}}}, {{{0x0f, 0xa9, 0xd5, 0x01, 0xaa, 0x48, 0x4f, 0x28, 0x66, 0x32, 0x1a, 0xba, 0x7c, 0xea, 0x11, 0x80, 0x17, 0x18, 0x9b, 0x56, 0x88, 0x25, 0x06, 0x69, 0x12, 0x2c, 0xea, 0x56, 0x69, 0x41, 0x24, 0x19}} , {{0xde, 0x21, 0xf0, 0xda, 0x8a, 0xfb, 0xb1, 0xb8, 0xcd, 0xc8, 0x6a, 0x82, 0x19, 0x73, 0xdb, 0xc7, 0xcf, 0x88, 0xeb, 0x96, 0xee, 0x6f, 0xfb, 0x06, 0xd2, 0xcd, 0x7d, 0x7b, 0x12, 0x28, 0x8e, 0x0c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x93, 0x44, 0x97, 0xce, 0x28, 0xff, 0x3a, 0x40, 0xc4, 0xf5, 0xf6, 0x9b, 0xf4, 0x6b, 0x07, 0x84, 0xfb, 0x98, 0xd8, 0xec, 0x8c, 0x03, 0x57, 0xec, 0x49, 0xed, 0x63, 0xb6, 0xaa, 0xff, 0x98, 0x28}} , {{0x3d, 0x16, 0x35, 0xf3, 0x46, 0xbc, 0xb3, 0xf4, 0xc6, 0xb6, 0x4f, 0xfa, 0xf4, 0xa0, 0x13, 0xe6, 0x57, 0x45, 0x93, 0xb9, 0xbc, 0xd6, 0x59, 0xe7, 0x77, 0x94, 0x6c, 0xab, 0x96, 0x3b, 0x4f, 0x09}}}, {{{0x5a, 0xf7, 0x6b, 0x01, 0x12, 0x4f, 0x51, 0xc1, 0x70, 0x84, 0x94, 0x47, 0xb2, 0x01, 0x6c, 0x71, 0xd7, 0xcc, 0x17, 0x66, 0x0f, 0x59, 0x5d, 0x5d, 0x10, 0x01, 0x57, 0x11, 0xf5, 0xdd, 0xe2, 0x34}} , {{0x26, 0xd9, 0x1f, 0x5c, 0x58, 0xac, 0x8b, 0x03, 0xd2, 0xc3, 0x85, 0x0f, 0x3a, 0xc3, 0x7f, 0x6d, 0x8e, 0x86, 0xcd, 0x52, 0x74, 0x8f, 0x55, 0x77, 0x17, 0xb7, 0x8e, 0xb7, 0x88, 0xea, 0xda, 0x1b}}}, {{{0xb6, 0xea, 0x0e, 0x40, 0x93, 0x20, 0x79, 0x35, 0x6a, 0x61, 0x84, 0x5a, 0x07, 0x6d, 0xf9, 0x77, 0x6f, 0xed, 0x69, 0x1c, 0x0d, 0x25, 0x76, 0xcc, 0xf0, 0xdb, 0xbb, 0xc5, 0xad, 0xe2, 0x26, 0x57}} , {{0xcf, 0xe8, 0x0e, 0x6b, 0x96, 0x7d, 0xed, 0x27, 0xd1, 0x3c, 0xa9, 0xd9, 0x50, 0xa9, 0x98, 0x84, 0x5e, 0x86, 0xef, 0xd6, 0xf0, 0xf8, 0x0e, 0x89, 0x05, 0x2f, 0xd9, 0x5f, 0x15, 0x5f, 0x73, 0x79}}}, {{{0xc8, 0x5c, 0x16, 0xfe, 0xed, 0x9f, 0x26, 0x56, 0xf6, 0x4b, 0x9f, 0xa7, 0x0a, 0x85, 0xfe, 0xa5, 0x8c, 0x87, 0xdd, 0x98, 0xce, 0x4e, 0xc3, 0x58, 0x55, 0xb2, 0x7b, 0x3d, 0xd8, 0x6b, 0xb5, 0x4c}} , {{0x65, 0x38, 0xa0, 0x15, 0xfa, 0xa7, 0xb4, 0x8f, 0xeb, 0xc4, 0x86, 0x9b, 0x30, 0xa5, 0x5e, 0x4d, 0xea, 0x8a, 0x9a, 0x9f, 0x1a, 0xd8, 0x5b, 0x53, 0x14, 0x19, 0x25, 0x63, 0xb4, 0x6f, 0x1f, 0x5d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xac, 0x8f, 0xbc, 0x1e, 0x7d, 0x8b, 0x5a, 0x0b, 0x8d, 0xaf, 0x76, 0x2e, 0x71, 0xe3, 0x3b, 0x6f, 0x53, 0x2f, 0x3e, 0x90, 0x95, 0xd4, 0x35, 0x14, 0x4f, 0x8c, 0x3c, 0xce, 0x57, 0x1c, 0x76, 0x49}} , {{0xa8, 0x50, 0xe1, 0x61, 0x6b, 0x57, 0x35, 0xeb, 0x44, 0x0b, 0x0c, 0x6e, 0xf9, 0x25, 0x80, 0x74, 0xf2, 0x8f, 0x6f, 0x7a, 0x3e, 0x7f, 0x2d, 0xf3, 0x4e, 0x09, 0x65, 0x10, 0x5e, 0x03, 0x25, 0x32}}}, {{{0xa9, 0x60, 0xdc, 0x0f, 0x64, 0xe5, 0x1d, 0xe2, 0x8d, 0x4f, 0x79, 0x2f, 0x0e, 0x24, 0x02, 0x00, 0x05, 0x77, 0x43, 0x25, 0x3d, 0x6a, 0xc7, 0xb7, 0xbf, 0x04, 0x08, 0x65, 0xf4, 0x39, 0x4b, 0x65}} , {{0x96, 0x19, 0x12, 0x6b, 0x6a, 0xb7, 0xe3, 0xdc, 0x45, 0x9b, 0xdb, 0xb4, 0xa8, 0xae, 0xdc, 0xa8, 0x14, 0x44, 0x65, 0x62, 0xce, 0x34, 0x9a, 0x84, 0x18, 0x12, 0x01, 0xf1, 0xe2, 0x7b, 0xce, 0x50}}}, {{{0x41, 0x21, 0x30, 0x53, 0x1b, 0x47, 0x01, 0xb7, 0x18, 0xd8, 0x82, 0x57, 0xbd, 0xa3, 0x60, 0xf0, 0x32, 0xf6, 0x5b, 0xf0, 0x30, 0x88, 0x91, 0x59, 0xfd, 0x90, 0xa2, 0xb9, 0x55, 0x93, 0x21, 0x34}} , {{0x97, 0x67, 0x9e, 0xeb, 0x6a, 0xf9, 0x6e, 0xd6, 0x73, 0xe8, 0x6b, 0x29, 0xec, 0x63, 0x82, 0x00, 0xa8, 0x99, 0x1c, 0x1d, 0x30, 0xc8, 0x90, 0x52, 0x90, 0xb6, 0x6a, 0x80, 0x4e, 0xff, 0x4b, 0x51}}}, {{{0x0f, 0x7d, 0x63, 0x8c, 0x6e, 0x5c, 0xde, 0x30, 0xdf, 0x65, 0xfa, 0x2e, 0xb0, 0xa3, 0x25, 0x05, 0x54, 0xbd, 0x25, 0xba, 0x06, 0xae, 0xdf, 0x8b, 0xd9, 0x1b, 0xea, 0x38, 0xb3, 0x05, 0x16, 0x09}} , {{0xc7, 0x8c, 0xbf, 0x64, 0x28, 0xad, 0xf8, 0xa5, 0x5a, 0x6f, 0xc9, 0xba, 0xd5, 0x7f, 0xd5, 0xd6, 0xbd, 0x66, 0x2f, 0x3d, 0xaa, 0x54, 0xf6, 0xba, 0x32, 0x22, 0x9a, 0x1e, 0x52, 0x05, 0xf4, 0x1d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xaa, 0x1f, 0xbb, 0xeb, 0xfe, 0xe4, 0x87, 0xfc, 0xb1, 0x2c, 0xb7, 0x88, 0xf4, 0xc6, 0xb9, 0xf5, 0x24, 0x46, 0xf2, 0xa5, 0x9f, 0x8f, 0x8a, 0x93, 0x70, 0x69, 0xd4, 0x56, 0xec, 0xfd, 0x06, 0x46}} , {{0x4e, 0x66, 0xcf, 0x4e, 0x34, 0xce, 0x0c, 0xd9, 0xa6, 0x50, 0xd6, 0x5e, 0x95, 0xaf, 0xe9, 0x58, 0xfa, 0xee, 0x9b, 0xb8, 0xa5, 0x0f, 0x35, 0xe0, 0x43, 0x82, 0x6d, 0x65, 0xe6, 0xd9, 0x00, 0x0f}}}, {{{0x7b, 0x75, 0x3a, 0xfc, 0x64, 0xd3, 0x29, 0x7e, 0xdd, 0x49, 0x9a, 0x59, 0x53, 0xbf, 0xb4, 0xa7, 0x52, 0xb3, 0x05, 0xab, 0xc3, 0xaf, 0x16, 0x1a, 0x85, 0x42, 0x32, 0xa2, 0x86, 0xfa, 0x39, 0x43}} , {{0x0e, 0x4b, 0xa3, 0x63, 0x8a, 0xfe, 0xa5, 0x58, 0xf1, 0x13, 0xbd, 0x9d, 0xaa, 0x7f, 0x76, 0x40, 0x70, 0x81, 0x10, 0x75, 0x99, 0xbb, 0xbe, 0x0b, 0x16, 0xe9, 0xba, 0x62, 0x34, 0xcc, 0x07, 0x6d}}}, {{{0xc3, 0xf1, 0xc6, 0x93, 0x65, 0xee, 0x0b, 0xbc, 0xea, 0x14, 0xf0, 0xc1, 0xf8, 0x84, 0x89, 0xc2, 0xc9, 0xd7, 0xea, 0x34, 0xca, 0xa7, 0xc4, 0x99, 0xd5, 0x50, 0x69, 0xcb, 0xd6, 0x21, 0x63, 0x7c}} , {{0x99, 0xeb, 0x7c, 0x31, 0x73, 0x64, 0x67, 0x7f, 0x0c, 0x66, 0xaa, 0x8c, 0x69, 0x91, 0xe2, 0x26, 0xd3, 0x23, 0xe2, 0x76, 0x5d, 0x32, 0x52, 0xdf, 0x5d, 0xc5, 0x8f, 0xb7, 0x7c, 0x84, 0xb3, 0x70}}}, {{{0xeb, 0x01, 0xc7, 0x36, 0x97, 0x4e, 0xb6, 0xab, 0x5f, 0x0d, 0x2c, 0xba, 0x67, 0x64, 0x55, 0xde, 0xbc, 0xff, 0xa6, 0xec, 0x04, 0xd3, 0x8d, 0x39, 0x56, 0x5e, 0xee, 0xf8, 0xe4, 0x2e, 0x33, 0x62}} , {{0x65, 0xef, 0xb8, 0x9f, 0xc8, 0x4b, 0xa7, 0xfd, 0x21, 0x49, 0x9b, 0x92, 0x35, 0x82, 0xd6, 0x0a, 0x9b, 0xf2, 0x79, 0xf1, 0x47, 0x2f, 0x6a, 0x7e, 0x9f, 0xcf, 0x18, 0x02, 0x3c, 0xfb, 0x1b, 0x3e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2f, 0x8b, 0xc8, 0x40, 0x51, 0xd1, 0xac, 0x1a, 0x0b, 0xe4, 0xa9, 0xa2, 0x42, 0x21, 0x19, 0x2f, 0x7b, 0x97, 0xbf, 0xf7, 0x57, 0x6d, 0x3f, 0x3d, 0x4f, 0x0f, 0xe2, 0xb2, 0x81, 0x00, 0x9e, 0x7b}} , {{0x8c, 0x85, 0x2b, 0xc4, 0xfc, 0xf1, 0xab, 0xe8, 0x79, 0x22, 0xc4, 0x84, 0x17, 0x3a, 0xfa, 0x86, 0xa6, 0x7d, 0xf9, 0xf3, 0x6f, 0x03, 0x57, 0x20, 0x4d, 0x79, 0xf9, 0x6e, 0x71, 0x54, 0x38, 0x09}}}, {{{0x40, 0x29, 0x74, 0xa8, 0x2f, 0x5e, 0xf9, 0x79, 0xa4, 0xf3, 0x3e, 0xb9, 0xfd, 0x33, 0x31, 0xac, 0x9a, 0x69, 0x88, 0x1e, 0x77, 0x21, 0x2d, 0xf3, 0x91, 0x52, 0x26, 0x15, 0xb2, 0xa6, 0xcf, 0x7e}} , {{0xc6, 0x20, 0x47, 0x6c, 0xa4, 0x7d, 0xcb, 0x63, 0xea, 0x5b, 0x03, 0xdf, 0x3e, 0x88, 0x81, 0x6d, 0xce, 0x07, 0x42, 0x18, 0x60, 0x7e, 0x7b, 0x55, 0xfe, 0x6a, 0xf3, 0xda, 0x5c, 0x8b, 0x95, 0x10}}}, {{{0x62, 0xe4, 0x0d, 0x03, 0xb4, 0xd7, 0xcd, 0xfa, 0xbd, 0x46, 0xdf, 0x93, 0x71, 0x10, 0x2c, 0xa8, 0x3b, 0xb6, 0x09, 0x05, 0x70, 0x84, 0x43, 0x29, 0xa8, 0x59, 0xf5, 0x8e, 0x10, 0xe4, 0xd7, 0x20}} , {{0x57, 0x82, 0x1c, 0xab, 0xbf, 0x62, 0x70, 0xe8, 0xc4, 0xcf, 0xf0, 0x28, 0x6e, 0x16, 0x3c, 0x08, 0x78, 0x89, 0x85, 0x46, 0x0f, 0xf6, 0x7f, 0xcf, 0xcb, 0x7e, 0xb8, 0x25, 0xe9, 0x5a, 0xfa, 0x03}}}, {{{0xfb, 0x95, 0x92, 0x63, 0x50, 0xfc, 0x62, 0xf0, 0xa4, 0x5e, 0x8c, 0x18, 0xc2, 0x17, 0x24, 0xb7, 0x78, 0xc2, 0xa9, 0xe7, 0x6a, 0x32, 0xd6, 0x29, 0x85, 0xaf, 0xcb, 0x8d, 0x91, 0x13, 0xda, 0x6b}} , {{0x36, 0x0a, 0xc2, 0xb6, 0x4b, 0xa5, 0x5d, 0x07, 0x17, 0x41, 0x31, 0x5f, 0x62, 0x46, 0xf8, 0x92, 0xf9, 0x66, 0x48, 0x73, 0xa6, 0x97, 0x0d, 0x7d, 0x88, 0xee, 0x62, 0xb1, 0x03, 0xa8, 0x3f, 0x2c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4a, 0xb1, 0x70, 0x8a, 0xa9, 0xe8, 0x63, 0x79, 0x00, 0xe2, 0x25, 0x16, 0xca, 0x4b, 0x0f, 0xa4, 0x66, 0xad, 0x19, 0x9f, 0x88, 0x67, 0x0c, 0x8b, 0xc2, 0x4a, 0x5b, 0x2b, 0x6d, 0x95, 0xaf, 0x19}} , {{0x8b, 0x9d, 0xb6, 0xcc, 0x60, 0xb4, 0x72, 0x4f, 0x17, 0x69, 0x5a, 0x4a, 0x68, 0x34, 0xab, 0xa1, 0x45, 0x32, 0x3c, 0x83, 0x87, 0x72, 0x30, 0x54, 0x77, 0x68, 0xae, 0xfb, 0xb5, 0x8b, 0x22, 0x5e}}}, {{{0xf1, 0xb9, 0x87, 0x35, 0xc5, 0xbb, 0xb9, 0xcf, 0xf5, 0xd6, 0xcd, 0xd5, 0x0c, 0x7c, 0x0e, 0xe6, 0x90, 0x34, 0xfb, 0x51, 0x42, 0x1e, 0x6d, 0xac, 0x9a, 0x46, 0xc4, 0x97, 0x29, 0x32, 0xbf, 0x45}} , {{0x66, 0x9e, 0xc6, 0x24, 0xc0, 0xed, 0xa5, 0x5d, 0x88, 0xd4, 0xf0, 0x73, 0x97, 0x7b, 0xea, 0x7f, 0x42, 0xff, 0x21, 0xa0, 0x9b, 0x2f, 0x9a, 0xfd, 0x53, 0x57, 0x07, 0x84, 0x48, 0x88, 0x9d, 0x52}}}, {{{0xc6, 0x96, 0x48, 0x34, 0x2a, 0x06, 0xaf, 0x94, 0x3d, 0xf4, 0x1a, 0xcf, 0xf2, 0xc0, 0x21, 0xc2, 0x42, 0x5e, 0xc8, 0x2f, 0x35, 0xa2, 0x3e, 0x29, 0xfa, 0x0c, 0x84, 0xe5, 0x89, 0x72, 0x7c, 0x06}} , {{0x32, 0x65, 0x03, 0xe5, 0x89, 0xa6, 0x6e, 0xb3, 0x5b, 0x8e, 0xca, 0xeb, 0xfe, 0x22, 0x56, 0x8b, 0x5d, 0x14, 0x4b, 0x4d, 0xf9, 0xbe, 0xb5, 0xf5, 0xe6, 0x5c, 0x7b, 0x8b, 0xf4, 0x13, 0x11, 0x34}}}, {{{0x07, 0xc6, 0x22, 0x15, 0xe2, 0x9c, 0x60, 0xa2, 0x19, 0xd9, 0x27, 0xae, 0x37, 0x4e, 0xa6, 0xc9, 0x80, 0xa6, 0x91, 0x8f, 0x12, 0x49, 0xe5, 0x00, 0x18, 0x47, 0xd1, 0xd7, 0x28, 0x22, 0x63, 0x39}} , {{0xe8, 0xe2, 0x00, 0x7e, 0xf2, 0x9e, 0x1e, 0x99, 0x39, 0x95, 0x04, 0xbd, 0x1e, 0x67, 0x7b, 0xb2, 0x26, 0xac, 0xe6, 0xaa, 0xe2, 0x46, 0xd5, 0xe4, 0xe8, 0x86, 0xbd, 0xab, 0x7c, 0x55, 0x59, 0x6f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0x64, 0x6e, 0x9b, 0x35, 0x71, 0x78, 0xce, 0x33, 0x03, 0x21, 0x33, 0x36, 0xf1, 0x73, 0x9b, 0xb9, 0x15, 0x8b, 0x2c, 0x69, 0xcf, 0x4d, 0xed, 0x4f, 0x4d, 0x57, 0x14, 0x13, 0x82, 0xa4, 0x4d}} , {{0x65, 0x6e, 0x0a, 0xa4, 0x59, 0x07, 0x17, 0xf2, 0x6b, 0x4a, 0x1f, 0x6e, 0xf6, 0xb5, 0xbc, 0x62, 0xe4, 0xb6, 0xda, 0xa2, 0x93, 0xbc, 0x29, 0x05, 0xd2, 0xd2, 0x73, 0x46, 0x03, 0x16, 0x40, 0x31}}}, {{{0x4c, 0x73, 0x6d, 0x15, 0xbd, 0xa1, 0x4d, 0x5c, 0x13, 0x0b, 0x24, 0x06, 0x98, 0x78, 0x1c, 0x5b, 0xeb, 0x1f, 0x18, 0x54, 0x43, 0xd9, 0x55, 0x66, 0xda, 0x29, 0x21, 0xe8, 0xb8, 0x3c, 0x42, 0x22}} , {{0xb4, 0xcd, 0x08, 0x6f, 0x15, 0x23, 0x1a, 0x0b, 0x22, 0xed, 0xd1, 0xf1, 0xa7, 0xc7, 0x73, 0x45, 0xf3, 0x9e, 0xce, 0x76, 0xb7, 0xf6, 0x39, 0xb6, 0x8e, 0x79, 0xbe, 0xe9, 0x9b, 0xcf, 0x7d, 0x62}}}, {{{0x92, 0x5b, 0xfc, 0x72, 0xfd, 0xba, 0xf1, 0xfd, 0xa6, 0x7c, 0x95, 0xe3, 0x61, 0x3f, 0xe9, 0x03, 0xd4, 0x2b, 0xd4, 0x20, 0xd9, 0xdb, 0x4d, 0x32, 0x3e, 0xf5, 0x11, 0x64, 0xe3, 0xb4, 0xbe, 0x32}} , {{0x86, 0x17, 0x90, 0xe7, 0xc9, 0x1f, 0x10, 0xa5, 0x6a, 0x2d, 0x39, 0xd0, 0x3b, 0xc4, 0xa6, 0xe9, 0x59, 0x13, 0xda, 0x1a, 0xe6, 0xa0, 0xb9, 0x3c, 0x50, 0xb8, 0x40, 0x7c, 0x15, 0x36, 0x5a, 0x42}}}, {{{0xb4, 0x0b, 0x32, 0xab, 0xdc, 0x04, 0x51, 0x55, 0x21, 0x1e, 0x0b, 0x75, 0x99, 0x89, 0x73, 0x35, 0x3a, 0x91, 0x2b, 0xfe, 0xe7, 0x49, 0xea, 0x76, 0xc1, 0xf9, 0x46, 0xb9, 0x53, 0x02, 0x23, 0x04}} , {{0xfc, 0x5a, 0x1e, 0x1d, 0x74, 0x58, 0x95, 0xa6, 0x8f, 0x7b, 0x97, 0x3e, 0x17, 0x3b, 0x79, 0x2d, 0xa6, 0x57, 0xef, 0x45, 0x02, 0x0b, 0x4d, 0x6e, 0x9e, 0x93, 0x8d, 0x2f, 0xd9, 0x9d, 0xdb, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc0, 0xd7, 0x56, 0x97, 0x58, 0x91, 0xde, 0x09, 0x4f, 0x9f, 0xbe, 0x63, 0xb0, 0x83, 0x86, 0x43, 0x5d, 0xbc, 0xe0, 0xf3, 0xc0, 0x75, 0xbf, 0x8b, 0x8e, 0xaa, 0xf7, 0x8b, 0x64, 0x6e, 0xb0, 0x63}} , {{0x16, 0xae, 0x8b, 0xe0, 0x9b, 0x24, 0x68, 0x5c, 0x44, 0xc2, 0xd0, 0x08, 0xb7, 0x7b, 0x62, 0xfd, 0x7f, 0xd8, 0xd4, 0xb7, 0x50, 0xfd, 0x2c, 0x1b, 0xbf, 0x41, 0x95, 0xd9, 0x8e, 0xd8, 0x17, 0x1b}}}, {{{0x86, 0x55, 0x37, 0x8e, 0xc3, 0x38, 0x48, 0x14, 0xb5, 0x97, 0xd2, 0xa7, 0x54, 0x45, 0xf1, 0x35, 0x44, 0x38, 0x9e, 0xf1, 0x1b, 0xb6, 0x34, 0x00, 0x3c, 0x96, 0xee, 0x29, 0x00, 0xea, 0x2c, 0x0b}} , {{0xea, 0xda, 0x99, 0x9e, 0x19, 0x83, 0x66, 0x6d, 0xe9, 0x76, 0x87, 0x50, 0xd1, 0xfd, 0x3c, 0x60, 0x87, 0xc6, 0x41, 0xd9, 0x8e, 0xdb, 0x5e, 0xde, 0xaa, 0x9a, 0xd3, 0x28, 0xda, 0x95, 0xea, 0x47}}}, {{{0xd0, 0x80, 0xba, 0x19, 0xae, 0x1d, 0xa9, 0x79, 0xf6, 0x3f, 0xac, 0x5d, 0x6f, 0x96, 0x1f, 0x2a, 0xce, 0x29, 0xb2, 0xff, 0x37, 0xf1, 0x94, 0x8f, 0x0c, 0xb5, 0x28, 0xba, 0x9a, 0x21, 0xf6, 0x66}} , {{0x02, 0xfb, 0x54, 0xb8, 0x05, 0xf3, 0x81, 0x52, 0x69, 0x34, 0x46, 0x9d, 0x86, 0x76, 0x8f, 0xd7, 0xf8, 0x6a, 0x66, 0xff, 0xe6, 0xa7, 0x90, 0xf7, 0x5e, 0xcd, 0x6a, 0x9b, 0x55, 0xfc, 0x9d, 0x48}}}, {{{0xbd, 0xaa, 0x13, 0xe6, 0xcd, 0x45, 0x4a, 0xa4, 0x59, 0x0a, 0x64, 0xb1, 0x98, 0xd6, 0x34, 0x13, 0x04, 0xe6, 0x97, 0x94, 0x06, 0xcb, 0xd4, 0x4e, 0xbb, 0x96, 0xcd, 0xd1, 0x57, 0xd1, 0xe3, 0x06}} , {{0x7a, 0x6c, 0x45, 0x27, 0xc4, 0x93, 0x7f, 0x7d, 0x7c, 0x62, 0x50, 0x38, 0x3a, 0x6b, 0xb5, 0x88, 0xc6, 0xd9, 0xf1, 0x78, 0x19, 0xb9, 0x39, 0x93, 0x3d, 0xc9, 0xe0, 0x9c, 0x3c, 0xce, 0xf5, 0x72}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x24, 0xea, 0x23, 0x7d, 0x56, 0x2c, 0xe2, 0x59, 0x0e, 0x85, 0x60, 0x04, 0x88, 0x5a, 0x74, 0x1e, 0x4b, 0xef, 0x13, 0xda, 0x4c, 0xff, 0x83, 0x45, 0x85, 0x3f, 0x08, 0x95, 0x2c, 0x20, 0x13, 0x1f}} , {{0x48, 0x5f, 0x27, 0x90, 0x5c, 0x02, 0x42, 0xad, 0x78, 0x47, 0x5c, 0xb5, 0x7e, 0x08, 0x85, 0x00, 0xfa, 0x7f, 0xfd, 0xfd, 0xe7, 0x09, 0x11, 0xf2, 0x7e, 0x1b, 0x38, 0x6c, 0x35, 0x6d, 0x33, 0x66}}}, {{{0x93, 0x03, 0x36, 0x81, 0xac, 0xe4, 0x20, 0x09, 0x35, 0x4c, 0x45, 0xb2, 0x1e, 0x4c, 0x14, 0x21, 0xe6, 0xe9, 0x8a, 0x7b, 0x8d, 0xfe, 0x1e, 0xc6, 0x3e, 0xc1, 0x35, 0xfa, 0xe7, 0x70, 0x4e, 0x1d}} , {{0x61, 0x2e, 0xc2, 0xdd, 0x95, 0x57, 0xd1, 0xab, 0x80, 0xe8, 0x63, 0x17, 0xb5, 0x48, 0xe4, 0x8a, 0x11, 0x9e, 0x72, 0xbe, 0x85, 0x8d, 0x51, 0x0a, 0xf2, 0x9f, 0xe0, 0x1c, 0xa9, 0x07, 0x28, 0x7b}}}, {{{0xbb, 0x71, 0x14, 0x5e, 0x26, 0x8c, 0x3d, 0xc8, 0xe9, 0x7c, 0xd3, 0xd6, 0xd1, 0x2f, 0x07, 0x6d, 0xe6, 0xdf, 0xfb, 0x79, 0xd6, 0x99, 0x59, 0x96, 0x48, 0x40, 0x0f, 0x3a, 0x7b, 0xb2, 0xa0, 0x72}} , {{0x4e, 0x3b, 0x69, 0xc8, 0x43, 0x75, 0x51, 0x6c, 0x79, 0x56, 0xe4, 0xcb, 0xf7, 0xa6, 0x51, 0xc2, 0x2c, 0x42, 0x0b, 0xd4, 0x82, 0x20, 0x1c, 0x01, 0x08, 0x66, 0xd7, 0xbf, 0x04, 0x56, 0xfc, 0x02}}}, {{{0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c}} , {{0x6b, 0xa6, 0xf5, 0x4b, 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, 0xe6, 0x99, 0x2c, 0x5f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x85, 0xe0, 0x24, 0x32, 0xb4, 0xd1, 0xef, 0xfc, 0x69, 0xa2, 0xbf, 0x8f, 0x72, 0x2c, 0x95, 0xf6, 0xe4, 0x6e, 0x7d, 0x90, 0xf7, 0x57, 0x81, 0xa0, 0xf7, 0xda, 0xef, 0x33, 0x07, 0xe3, 0x6b, 0x78}} , {{0x36, 0x27, 0x3e, 0xc6, 0x12, 0x07, 0xab, 0x4e, 0xbe, 0x69, 0x9d, 0xb3, 0xbe, 0x08, 0x7c, 0x2a, 0x47, 0x08, 0xfd, 0xd4, 0xcd, 0x0e, 0x27, 0x34, 0x5b, 0x98, 0x34, 0x2f, 0x77, 0x5f, 0x3a, 0x65}}}, {{{0x13, 0xaa, 0x2e, 0x4c, 0xf0, 0x22, 0xb8, 0x6c, 0xb3, 0x19, 0x4d, 0xeb, 0x6b, 0xd0, 0xa4, 0xc6, 0x9c, 0xdd, 0xc8, 0x5b, 0x81, 0x57, 0x89, 0xdf, 0x33, 0xa9, 0x68, 0x49, 0x80, 0xe4, 0xfe, 0x21}} , {{0x00, 0x17, 0x90, 0x30, 0xe9, 0xd3, 0x60, 0x30, 0x31, 0xc2, 0x72, 0x89, 0x7a, 0x36, 0xa5, 0xbd, 0x39, 0x83, 0x85, 0x50, 0xa1, 0x5d, 0x6c, 0x41, 0x1d, 0xb5, 0x2c, 0x07, 0x40, 0x77, 0x0b, 0x50}}}, {{{0x64, 0x34, 0xec, 0xc0, 0x9e, 0x44, 0x41, 0xaf, 0xa0, 0x36, 0x05, 0x6d, 0xea, 0x30, 0x25, 0x46, 0x35, 0x24, 0x9d, 0x86, 0xbd, 0x95, 0xf1, 0x6a, 0x46, 0xd7, 0x94, 0x54, 0xf9, 0x3b, 0xbd, 0x5d}} , {{0x77, 0x5b, 0xe2, 0x37, 0xc7, 0xe1, 0x7c, 0x13, 0x8c, 0x9f, 0x7b, 0x7b, 0x2a, 0xce, 0x42, 0xa3, 0xb9, 0x2a, 0x99, 0xa8, 0xc0, 0xd8, 0x3c, 0x86, 0xb0, 0xfb, 0xe9, 0x76, 0x77, 0xf7, 0xf5, 0x56}}}, {{{0xdf, 0xb3, 0x46, 0x11, 0x6e, 0x13, 0xb7, 0x28, 0x4e, 0x56, 0xdd, 0xf1, 0xac, 0xad, 0x58, 0xc3, 0xf8, 0x88, 0x94, 0x5e, 0x06, 0x98, 0xa1, 0xe4, 0x6a, 0xfb, 0x0a, 0x49, 0x5d, 0x8a, 0xfe, 0x77}} , {{0x46, 0x02, 0xf5, 0xa5, 0xaf, 0xc5, 0x75, 0x6d, 0xba, 0x45, 0x35, 0x0a, 0xfe, 0xc9, 0xac, 0x22, 0x91, 0x8d, 0x21, 0x95, 0x33, 0x03, 0xc0, 0x8a, 0x16, 0xf3, 0x39, 0xe0, 0x01, 0x0f, 0x53, 0x3c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x34, 0x75, 0x37, 0x1f, 0x34, 0x4e, 0xa9, 0x1d, 0x68, 0x67, 0xf8, 0x49, 0x98, 0x96, 0xfc, 0x4c, 0x65, 0x97, 0xf7, 0x02, 0x4a, 0x52, 0x6c, 0x01, 0xbd, 0x48, 0xbb, 0x1b, 0xed, 0xa4, 0xe2, 0x53}} , {{0x59, 0xd5, 0x9b, 0x5a, 0xa2, 0x90, 0xd3, 0xb8, 0x37, 0x4c, 0x55, 0x82, 0x28, 0x08, 0x0f, 0x7f, 0xaa, 0x81, 0x65, 0xe0, 0x0c, 0x52, 0xc9, 0xa3, 0x32, 0x27, 0x64, 0xda, 0xfd, 0x34, 0x23, 0x5a}}}, {{{0xb5, 0xb0, 0x0c, 0x4d, 0xb3, 0x7b, 0x23, 0xc8, 0x1f, 0x8a, 0x39, 0x66, 0xe6, 0xba, 0x4c, 0x10, 0x37, 0xca, 0x9c, 0x7c, 0x05, 0x9e, 0xff, 0xc0, 0xf8, 0x8e, 0xb1, 0x8f, 0x6f, 0x67, 0x18, 0x26}} , {{0x4b, 0x41, 0x13, 0x54, 0x23, 0x1a, 0xa4, 0x4e, 0xa9, 0x8b, 0x1e, 0x4b, 0xfc, 0x15, 0x24, 0xbb, 0x7e, 0xcb, 0xb6, 0x1e, 0x1b, 0xf5, 0xf2, 0xc8, 0x56, 0xec, 0x32, 0xa2, 0x60, 0x5b, 0xa0, 0x2a}}}, {{{0xa4, 0x29, 0x47, 0x86, 0x2e, 0x92, 0x4f, 0x11, 0x4f, 0xf3, 0xb2, 0x5c, 0xd5, 0x3e, 0xa6, 0xb9, 0xc8, 0xe2, 0x33, 0x11, 0x1f, 0x01, 0x8f, 0xb0, 0x9b, 0xc7, 0xa5, 0xff, 0x83, 0x0f, 0x1e, 0x28}} , {{0x1d, 0x29, 0x7a, 0xa1, 0xec, 0x8e, 0xb5, 0xad, 0xea, 0x02, 0x68, 0x60, 0x74, 0x29, 0x1c, 0xa5, 0xcf, 0xc8, 0x3b, 0x7d, 0x8b, 0x2b, 0x7c, 0xad, 0xa4, 0x40, 0x17, 0x51, 0x59, 0x7c, 0x2e, 0x5d}}}, {{{0x0a, 0x6c, 0x4f, 0xbc, 0x3e, 0x32, 0xe7, 0x4a, 0x1a, 0x13, 0xc1, 0x49, 0x38, 0xbf, 0xf7, 0xc2, 0xd3, 0x8f, 0x6b, 0xad, 0x52, 0xf7, 0xcf, 0xbc, 0x27, 0xcb, 0x40, 0x67, 0x76, 0xcd, 0x6d, 0x56}} , {{0xe5, 0xb0, 0x27, 0xad, 0xbe, 0x9b, 0xf2, 0xb5, 0x63, 0xde, 0x3a, 0x23, 0x95, 0xb7, 0x0a, 0x7e, 0xf3, 0x9e, 0x45, 0x6f, 0x19, 0x39, 0x75, 0x8f, 0x39, 0x3d, 0x0f, 0xc0, 0x9f, 0xf1, 0xe9, 0x51}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x88, 0xaa, 0x14, 0x24, 0x86, 0x94, 0x11, 0x12, 0x3e, 0x1a, 0xb5, 0xcc, 0xbb, 0xe0, 0x9c, 0xd5, 0x9c, 0x6d, 0xba, 0x58, 0x72, 0x8d, 0xfb, 0x22, 0x7b, 0x9f, 0x7c, 0x94, 0x30, 0xb3, 0x51, 0x21}} , {{0xf6, 0x74, 0x3d, 0xf2, 0xaf, 0xd0, 0x1e, 0x03, 0x7c, 0x23, 0x6b, 0xc9, 0xfc, 0x25, 0x70, 0x90, 0xdc, 0x9a, 0xa4, 0xfb, 0x49, 0xfc, 0x3d, 0x0a, 0x35, 0x38, 0x6f, 0xe4, 0x7e, 0x50, 0x01, 0x2a}}}, {{{0xd6, 0xe3, 0x96, 0x61, 0x3a, 0xfd, 0xef, 0x9b, 0x1f, 0x90, 0xa4, 0x24, 0x14, 0x5b, 0xc8, 0xde, 0x50, 0xb1, 0x1d, 0xaf, 0xe8, 0x55, 0x8a, 0x87, 0x0d, 0xfe, 0xaa, 0x3b, 0x82, 0x2c, 0x8d, 0x7b}} , {{0x85, 0x0c, 0xaf, 0xf8, 0x83, 0x44, 0x49, 0xd9, 0x45, 0xcf, 0xf7, 0x48, 0xd9, 0x53, 0xb4, 0xf1, 0x65, 0xa0, 0xe1, 0xc3, 0xb3, 0x15, 0xed, 0x89, 0x9b, 0x4f, 0x62, 0xb3, 0x57, 0xa5, 0x45, 0x1c}}}, {{{0x8f, 0x12, 0xea, 0xaf, 0xd1, 0x1f, 0x79, 0x10, 0x0b, 0xf6, 0xa3, 0x7b, 0xea, 0xac, 0x8b, 0x57, 0x32, 0x62, 0xe7, 0x06, 0x12, 0x51, 0xa0, 0x3b, 0x43, 0x5e, 0xa4, 0x20, 0x78, 0x31, 0xce, 0x0d}} , {{0x84, 0x7c, 0xc2, 0xa6, 0x91, 0x23, 0xce, 0xbd, 0xdc, 0xf9, 0xce, 0xd5, 0x75, 0x30, 0x22, 0xe6, 0xf9, 0x43, 0x62, 0x0d, 0xf7, 0x75, 0x9d, 0x7f, 0x8c, 0xff, 0x7d, 0xe4, 0x72, 0xac, 0x9f, 0x1c}}}, {{{0x88, 0xc1, 0x99, 0xd0, 0x3c, 0x1c, 0x5d, 0xb4, 0xef, 0x13, 0x0f, 0x90, 0xb9, 0x36, 0x2f, 0x95, 0x95, 0xc6, 0xdc, 0xde, 0x0a, 0x51, 0xe2, 0x8d, 0xf3, 0xbc, 0x51, 0xec, 0xdf, 0xb1, 0xa2, 0x5f}} , {{0x2e, 0x68, 0xa1, 0x23, 0x7d, 0x9b, 0x40, 0x69, 0x85, 0x7b, 0x42, 0xbf, 0x90, 0x4b, 0xd6, 0x40, 0x2f, 0xd7, 0x52, 0x52, 0xb2, 0x21, 0xde, 0x64, 0xbd, 0x88, 0xc3, 0x6d, 0xa5, 0xfa, 0x81, 0x3f}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfb, 0xfd, 0x47, 0x7b, 0x8a, 0x66, 0x9e, 0x79, 0x2e, 0x64, 0x82, 0xef, 0xf7, 0x21, 0xec, 0xf6, 0xd8, 0x86, 0x09, 0x31, 0x7c, 0xdd, 0x03, 0x6a, 0x58, 0xa0, 0x77, 0xb7, 0x9b, 0x8c, 0x87, 0x1f}} , {{0x55, 0x47, 0xe4, 0xa8, 0x3d, 0x55, 0x21, 0x34, 0xab, 0x1d, 0xae, 0xe0, 0xf4, 0xea, 0xdb, 0xc5, 0xb9, 0x58, 0xbf, 0xc4, 0x2a, 0x89, 0x31, 0x1a, 0xf4, 0x2d, 0xe1, 0xca, 0x37, 0x99, 0x47, 0x59}}}, {{{0xc7, 0xca, 0x63, 0xc1, 0x49, 0xa9, 0x35, 0x45, 0x55, 0x7e, 0xda, 0x64, 0x32, 0x07, 0x50, 0xf7, 0x32, 0xac, 0xde, 0x75, 0x58, 0x9b, 0x11, 0xb2, 0x3a, 0x1f, 0xf5, 0xf7, 0x79, 0x04, 0xe6, 0x08}} , {{0x46, 0xfa, 0x22, 0x4b, 0xfa, 0xe1, 0xfe, 0x96, 0xfc, 0x67, 0xba, 0x67, 0x97, 0xc4, 0xe7, 0x1b, 0x86, 0x90, 0x5f, 0xee, 0xf4, 0x5b, 0x11, 0xb2, 0xcd, 0xad, 0xee, 0xc2, 0x48, 0x6c, 0x2b, 0x1b}}}, {{{0xe3, 0x39, 0x62, 0xb4, 0x4f, 0x31, 0x04, 0xc9, 0xda, 0xd5, 0x73, 0x51, 0x57, 0xc5, 0xb8, 0xf3, 0xa3, 0x43, 0x70, 0xe4, 0x61, 0x81, 0x84, 0xe2, 0xbb, 0xbf, 0x4f, 0x9e, 0xa4, 0x5e, 0x74, 0x06}} , {{0x29, 0xac, 0xff, 0x27, 0xe0, 0x59, 0xbe, 0x39, 0x9c, 0x0d, 0x83, 0xd7, 0x10, 0x0b, 0x15, 0xb7, 0xe1, 0xc2, 0x2c, 0x30, 0x73, 0x80, 0x3a, 0x7d, 0x5d, 0xab, 0x58, 0x6b, 0xc1, 0xf0, 0xf4, 0x22}}}, {{{0xfe, 0x7f, 0xfb, 0x35, 0x7d, 0xc6, 0x01, 0x23, 0x28, 0xc4, 0x02, 0xac, 0x1f, 0x42, 0xb4, 0x9d, 0xfc, 0x00, 0x94, 0xa5, 0xee, 0xca, 0xda, 0x97, 0x09, 0x41, 0x77, 0x87, 0x5d, 0x7b, 0x87, 0x78}} , {{0xf5, 0xfb, 0x90, 0x2d, 0x81, 0x19, 0x9e, 0x2f, 0x6d, 0x85, 0x88, 0x8c, 0x40, 0x5c, 0x77, 0x41, 0x4d, 0x01, 0x19, 0x76, 0x60, 0xe8, 0x4c, 0x48, 0xe4, 0x33, 0x83, 0x32, 0x6c, 0xb4, 0x41, 0x03}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xff, 0x10, 0xc2, 0x09, 0x4f, 0x6e, 0xf4, 0xd2, 0xdf, 0x7e, 0xca, 0x7b, 0x1c, 0x1d, 0xba, 0xa3, 0xb6, 0xda, 0x67, 0x33, 0xd4, 0x87, 0x36, 0x4b, 0x11, 0x20, 0x05, 0xa6, 0x29, 0xc1, 0x87, 0x17}} , {{0xf6, 0x96, 0xca, 0x2f, 0xda, 0x38, 0xa7, 0x1b, 0xfc, 0xca, 0x7d, 0xfe, 0x08, 0x89, 0xe2, 0x47, 0x2b, 0x6a, 0x5d, 0x4b, 0xfa, 0xa1, 0xb4, 0xde, 0xb6, 0xc2, 0x31, 0x51, 0xf5, 0xe0, 0xa4, 0x0b}}}, {{{0x5c, 0xe5, 0xc6, 0x04, 0x8e, 0x2b, 0x57, 0xbe, 0x38, 0x85, 0x23, 0xcb, 0xb7, 0xbe, 0x4f, 0xa9, 0xd3, 0x6e, 0x12, 0xaa, 0xd5, 0xb2, 0x2e, 0x93, 0x29, 0x9a, 0x4a, 0x88, 0x18, 0x43, 0xf5, 0x01}} , {{0x50, 0xfc, 0xdb, 0xa2, 0x59, 0x21, 0x8d, 0xbd, 0x7e, 0x33, 0xae, 0x2f, 0x87, 0x1a, 0xd0, 0x97, 0xc7, 0x0d, 0x4d, 0x63, 0x01, 0xef, 0x05, 0x84, 0xec, 0x40, 0xdd, 0xa8, 0x0a, 0x4f, 0x70, 0x0b}}}, {{{0x41, 0x69, 0x01, 0x67, 0x5c, 0xd3, 0x8a, 0xc5, 0xcf, 0x3f, 0xd1, 0x57, 0xd1, 0x67, 0x3e, 0x01, 0x39, 0xb5, 0xcb, 0x81, 0x56, 0x96, 0x26, 0xb6, 0xc2, 0xe7, 0x5c, 0xfb, 0x63, 0x97, 0x58, 0x06}} , {{0x0c, 0x0e, 0xf3, 0xba, 0xf0, 0xe5, 0xba, 0xb2, 0x57, 0x77, 0xc6, 0x20, 0x9b, 0x89, 0x24, 0xbe, 0xf2, 0x9c, 0x8a, 0xba, 0x69, 0xc1, 0xf1, 0xb0, 0x4f, 0x2a, 0x05, 0x9a, 0xee, 0x10, 0x7e, 0x36}}}, {{{0x3f, 0x26, 0xe9, 0x40, 0xe9, 0x03, 0xad, 0x06, 0x69, 0x91, 0xe0, 0xd1, 0x89, 0x60, 0x84, 0x79, 0xde, 0x27, 0x6d, 0xe6, 0x76, 0xbd, 0xea, 0xe6, 0xae, 0x48, 0xc3, 0x67, 0xc0, 0x57, 0xcd, 0x2f}} , {{0x7f, 0xc1, 0xdc, 0xb9, 0xc7, 0xbc, 0x86, 0x3d, 0x55, 0x4b, 0x28, 0x7a, 0xfb, 0x4d, 0xc7, 0xf8, 0xbc, 0x67, 0x2a, 0x60, 0x4d, 0x8f, 0x07, 0x0b, 0x1a, 0x17, 0xbf, 0xfa, 0xac, 0xa7, 0x3d, 0x1a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x91, 0x3f, 0xed, 0x5e, 0x18, 0x78, 0x3f, 0x23, 0x2c, 0x0d, 0x8c, 0x44, 0x00, 0xe8, 0xfb, 0xe9, 0x8e, 0xd6, 0xd1, 0x36, 0x58, 0x57, 0x9e, 0xae, 0x4b, 0x5c, 0x0b, 0x07, 0xbc, 0x6b, 0x55, 0x2b}} , {{0x6f, 0x4d, 0x17, 0xd7, 0xe1, 0x84, 0xd9, 0x78, 0xb1, 0x90, 0xfd, 0x2e, 0xb3, 0xb5, 0x19, 0x3f, 0x1b, 0xfa, 0xc0, 0x68, 0xb3, 0xdd, 0x00, 0x2e, 0x89, 0xbd, 0x7e, 0x80, 0x32, 0x13, 0xa0, 0x7b}}}, {{{0x1a, 0x6f, 0x40, 0xaf, 0x44, 0x44, 0xb0, 0x43, 0x8f, 0x0d, 0xd0, 0x1e, 0xc4, 0x0b, 0x19, 0x5d, 0x8e, 0xfe, 0xc1, 0xf3, 0xc5, 0x5c, 0x91, 0xf8, 0x04, 0x4e, 0xbe, 0x90, 0xb4, 0x47, 0x5c, 0x3f}} , {{0xb0, 0x3b, 0x2c, 0xf3, 0xfe, 0x32, 0x71, 0x07, 0x3f, 0xaa, 0xba, 0x45, 0x60, 0xa8, 0x8d, 0xea, 0x54, 0xcb, 0x39, 0x10, 0xb4, 0xf2, 0x8b, 0xd2, 0x14, 0x82, 0x42, 0x07, 0x8e, 0xe9, 0x7c, 0x53}}}, {{{0xb0, 0xae, 0xc1, 0x8d, 0xc9, 0x8f, 0xb9, 0x7a, 0x77, 0xef, 0xba, 0x79, 0xa0, 0x3c, 0xa8, 0xf5, 0x6a, 0xe2, 0x3f, 0x5d, 0x00, 0xe3, 0x4b, 0x45, 0x24, 0x7b, 0x43, 0x78, 0x55, 0x1d, 0x2b, 0x1e}} , {{0x01, 0xb8, 0xd6, 0x16, 0x67, 0xa0, 0x15, 0xb9, 0xe1, 0x58, 0xa4, 0xa7, 0x31, 0x37, 0x77, 0x2f, 0x8b, 0x12, 0x9f, 0xf4, 0x3f, 0xc7, 0x36, 0x66, 0xd2, 0xa8, 0x56, 0xf7, 0x7f, 0x74, 0xc6, 0x41}}}, {{{0x5d, 0xf8, 0xb4, 0xa8, 0x30, 0xdd, 0xcc, 0x38, 0xa5, 0xd3, 0xca, 0xd8, 0xd1, 0xf8, 0xb2, 0x31, 0x91, 0xd4, 0x72, 0x05, 0x57, 0x4a, 0x3b, 0x82, 0x4a, 0xc6, 0x68, 0x20, 0xe2, 0x18, 0x41, 0x61}} , {{0x19, 0xd4, 0x8d, 0x47, 0x29, 0x12, 0x65, 0xb0, 0x11, 0x78, 0x47, 0xb5, 0xcb, 0xa3, 0xa5, 0xfa, 0x05, 0x85, 0x54, 0xa9, 0x33, 0x97, 0x8d, 0x2b, 0xc2, 0xfe, 0x99, 0x35, 0x28, 0xe5, 0xeb, 0x63}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb1, 0x3f, 0x3f, 0xef, 0xd8, 0xf4, 0xfc, 0xb3, 0xa0, 0x60, 0x50, 0x06, 0x2b, 0x29, 0x52, 0x70, 0x15, 0x0b, 0x24, 0x24, 0xf8, 0x5f, 0x79, 0x18, 0xcc, 0xff, 0x89, 0x99, 0x84, 0xa1, 0xae, 0x13}} , {{0x44, 0x1f, 0xb8, 0xc2, 0x01, 0xc1, 0x30, 0x19, 0x55, 0x05, 0x60, 0x10, 0xa4, 0x6c, 0x2d, 0x67, 0x70, 0xe5, 0x25, 0x1b, 0xf2, 0xbf, 0xdd, 0xfb, 0x70, 0x2b, 0xa1, 0x8c, 0x9c, 0x94, 0x84, 0x08}}}, {{{0xe7, 0xc4, 0x43, 0x4d, 0xc9, 0x2b, 0x69, 0x5d, 0x1d, 0x3c, 0xaf, 0xbb, 0x43, 0x38, 0x4e, 0x98, 0x3d, 0xed, 0x0d, 0x21, 0x03, 0xfd, 0xf0, 0x99, 0x47, 0x04, 0xb0, 0x98, 0x69, 0x55, 0x72, 0x0f}} , {{0x5e, 0xdf, 0x15, 0x53, 0x3b, 0x86, 0x80, 0xb0, 0xf1, 0x70, 0x68, 0x8f, 0x66, 0x7c, 0x0e, 0x49, 0x1a, 0xd8, 0x6b, 0xfe, 0x4e, 0xef, 0xca, 0x47, 0xd4, 0x03, 0xc1, 0x37, 0x50, 0x9c, 0xc1, 0x16}}}, {{{0xcd, 0x24, 0xc6, 0x3e, 0x0c, 0x82, 0x9b, 0x91, 0x2b, 0x61, 0x4a, 0xb2, 0x0f, 0x88, 0x55, 0x5f, 0x5a, 0x57, 0xff, 0xe5, 0x74, 0x0b, 0x13, 0x43, 0x00, 0xd8, 0x6b, 0xcf, 0xd2, 0x15, 0x03, 0x2c}} , {{0xdc, 0xff, 0x15, 0x61, 0x2f, 0x4a, 0x2f, 0x62, 0xf2, 0x04, 0x2f, 0xb5, 0x0c, 0xb7, 0x1e, 0x3f, 0x74, 0x1a, 0x0f, 0xd7, 0xea, 0xcd, 0xd9, 0x7d, 0xf6, 0x12, 0x0e, 0x2f, 0xdb, 0x5a, 0x3b, 0x16}}}, {{{0x1b, 0x37, 0x47, 0xe3, 0xf5, 0x9e, 0xea, 0x2c, 0x2a, 0xe7, 0x82, 0x36, 0xf4, 0x1f, 0x81, 0x47, 0x92, 0x4b, 0x69, 0x0e, 0x11, 0x8c, 0x5d, 0x53, 0x5b, 0x81, 0x27, 0x08, 0xbc, 0xa0, 0xae, 0x25}} , {{0x69, 0x32, 0xa1, 0x05, 0x11, 0x42, 0x00, 0xd2, 0x59, 0xac, 0x4d, 0x62, 0x8b, 0x13, 0xe2, 0x50, 0x5d, 0xa0, 0x9d, 0x9b, 0xfd, 0xbb, 0x12, 0x41, 0x75, 0x41, 0x9e, 0xcc, 0xdc, 0xc7, 0xdc, 0x5d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd9, 0xe3, 0x38, 0x06, 0x46, 0x70, 0x82, 0x5e, 0x28, 0x49, 0x79, 0xff, 0x25, 0xd2, 0x4e, 0x29, 0x8d, 0x06, 0xb0, 0x23, 0xae, 0x9b, 0x66, 0xe4, 0x7d, 0xc0, 0x70, 0x91, 0xa3, 0xfc, 0xec, 0x4e}} , {{0x62, 0x12, 0x37, 0x6a, 0x30, 0xf6, 0x1e, 0xfb, 0x14, 0x5c, 0x0d, 0x0e, 0xb7, 0x81, 0x6a, 0xe7, 0x08, 0x05, 0xac, 0xaa, 0x38, 0x46, 0xe2, 0x73, 0xea, 0x4b, 0x07, 0x81, 0x43, 0x7c, 0x9e, 0x5e}}}, {{{0xfc, 0xf9, 0x21, 0x4f, 0x2e, 0x76, 0x9b, 0x1f, 0x28, 0x60, 0x77, 0x43, 0x32, 0x9d, 0xbe, 0x17, 0x30, 0x2a, 0xc6, 0x18, 0x92, 0x66, 0x62, 0x30, 0x98, 0x40, 0x11, 0xa6, 0x7f, 0x18, 0x84, 0x28}} , {{0x3f, 0xab, 0xd3, 0xf4, 0x8a, 0x76, 0xa1, 0x3c, 0xca, 0x2d, 0x49, 0xc3, 0xea, 0x08, 0x0b, 0x85, 0x17, 0x2a, 0xc3, 0x6c, 0x08, 0xfd, 0x57, 0x9f, 0x3d, 0x5f, 0xdf, 0x67, 0x68, 0x42, 0x00, 0x32}}}, {{{0x51, 0x60, 0x1b, 0x06, 0x4f, 0x8a, 0x21, 0xba, 0x38, 0xa8, 0xba, 0xd6, 0x40, 0xf6, 0xe9, 0x9b, 0x76, 0x4d, 0x56, 0x21, 0x5b, 0x0a, 0x9b, 0x2e, 0x4f, 0x3d, 0x81, 0x32, 0x08, 0x9f, 0x97, 0x5b}} , {{0xe5, 0x44, 0xec, 0x06, 0x9d, 0x90, 0x79, 0x9f, 0xd3, 0xe0, 0x79, 0xaf, 0x8f, 0x10, 0xfd, 0xdd, 0x04, 0xae, 0x27, 0x97, 0x46, 0x33, 0x79, 0xea, 0xb8, 0x4e, 0xca, 0x5a, 0x59, 0x57, 0xe1, 0x0e}}}, {{{0x1a, 0xda, 0xf3, 0xa5, 0x41, 0x43, 0x28, 0xfc, 0x7e, 0xe7, 0x71, 0xea, 0xc6, 0x3b, 0x59, 0xcc, 0x2e, 0xd3, 0x40, 0xec, 0xb3, 0x13, 0x6f, 0x44, 0xcd, 0x13, 0xb2, 0x37, 0xf2, 0x6e, 0xd9, 0x1c}} , {{0xe3, 0xdb, 0x60, 0xcd, 0x5c, 0x4a, 0x18, 0x0f, 0xef, 0x73, 0x36, 0x71, 0x8c, 0xf6, 0x11, 0xb4, 0xd8, 0xce, 0x17, 0x5e, 0x4f, 0x26, 0x77, 0x97, 0x5f, 0xcb, 0xef, 0x91, 0xeb, 0x6a, 0x62, 0x7a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x18, 0x4a, 0xa2, 0x97, 0x08, 0x81, 0x2d, 0x83, 0xc4, 0xcc, 0xf0, 0x83, 0x7e, 0xec, 0x0d, 0x95, 0x4c, 0x5b, 0xfb, 0xfa, 0x98, 0x80, 0x4a, 0x66, 0x56, 0x0c, 0x51, 0xb3, 0xf2, 0x04, 0x5d, 0x27}} , {{0x3b, 0xb9, 0xb8, 0x06, 0x5a, 0x2e, 0xfe, 0xc3, 0x82, 0x37, 0x9c, 0xa3, 0x11, 0x1f, 0x9c, 0xa6, 0xda, 0x63, 0x48, 0x9b, 0xad, 0xde, 0x2d, 0xa6, 0xbc, 0x6e, 0x32, 0xda, 0x27, 0x65, 0xdd, 0x57}}}, {{{0x84, 0x4f, 0x37, 0x31, 0x7d, 0x2e, 0xbc, 0xad, 0x87, 0x07, 0x2a, 0x6b, 0x37, 0xfc, 0x5f, 0xeb, 0x4e, 0x75, 0x35, 0xa6, 0xde, 0xab, 0x0a, 0x19, 0x3a, 0xb7, 0xb1, 0xef, 0x92, 0x6a, 0x3b, 0x3c}} , {{0x3b, 0xb2, 0x94, 0x6d, 0x39, 0x60, 0xac, 0xee, 0xe7, 0x81, 0x1a, 0x3b, 0x76, 0x87, 0x5c, 0x05, 0x94, 0x2a, 0x45, 0xb9, 0x80, 0xe9, 0x22, 0xb1, 0x07, 0xcb, 0x40, 0x9e, 0x70, 0x49, 0x6d, 0x12}}}, {{{0xfd, 0x18, 0x78, 0x84, 0xa8, 0x4c, 0x7d, 0x6e, 0x59, 0xa6, 0xe5, 0x74, 0xf1, 0x19, 0xa6, 0x84, 0x2e, 0x51, 0xc1, 0x29, 0x13, 0xf2, 0x14, 0x6b, 0x5d, 0x53, 0x51, 0xf7, 0xef, 0xbf, 0x01, 0x22}} , {{0xa4, 0x4b, 0x62, 0x4c, 0xe6, 0xfd, 0x72, 0x07, 0xf2, 0x81, 0xfc, 0xf2, 0xbd, 0x12, 0x7c, 0x68, 0x76, 0x2a, 0xba, 0xf5, 0x65, 0xb1, 0x1f, 0x17, 0x0a, 0x38, 0xb0, 0xbf, 0xc0, 0xf8, 0xf4, 0x2a}}}, {{{0x55, 0x60, 0x55, 0x5b, 0xe4, 0x1d, 0x71, 0x4c, 0x9d, 0x5b, 0x9f, 0x70, 0xa6, 0x85, 0x9a, 0x2c, 0xa0, 0xe2, 0x32, 0x48, 0xce, 0x9e, 0x2a, 0xa5, 0x07, 0x3b, 0xc7, 0x6c, 0x86, 0x77, 0xde, 0x3c}} , {{0xf7, 0x18, 0x7a, 0x96, 0x7e, 0x43, 0x57, 0xa9, 0x55, 0xfc, 0x4e, 0xb6, 0x72, 0x00, 0xf2, 0xe4, 0xd7, 0x52, 0xd3, 0xd3, 0xb6, 0x85, 0xf6, 0x71, 0xc7, 0x44, 0x3f, 0x7f, 0xd7, 0xb3, 0xf2, 0x79}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x46, 0xca, 0xa7, 0x55, 0x7b, 0x79, 0xf3, 0xca, 0x5a, 0x65, 0xf6, 0xed, 0x50, 0x14, 0x7b, 0xe4, 0xc4, 0x2a, 0x65, 0x9e, 0xe2, 0xf9, 0xca, 0xa7, 0x22, 0x26, 0x53, 0xcb, 0x21, 0x5b, 0xa7, 0x31}} , {{0x90, 0xd7, 0xc5, 0x26, 0x08, 0xbd, 0xb0, 0x53, 0x63, 0x58, 0xc3, 0x31, 0x5e, 0x75, 0x46, 0x15, 0x91, 0xa6, 0xf8, 0x2f, 0x1a, 0x08, 0x65, 0x88, 0x2f, 0x98, 0x04, 0xf1, 0x7c, 0x6e, 0x00, 0x77}}}, {{{0x81, 0x21, 0x61, 0x09, 0xf6, 0x4e, 0xf1, 0x92, 0xee, 0x63, 0x61, 0x73, 0x87, 0xc7, 0x54, 0x0e, 0x42, 0x4b, 0xc9, 0x47, 0xd1, 0xb8, 0x7e, 0x91, 0x75, 0x37, 0x99, 0x28, 0xb8, 0xdd, 0x7f, 0x50}} , {{0x89, 0x8f, 0xc0, 0xbe, 0x5d, 0xd6, 0x9f, 0xa0, 0xf0, 0x9d, 0x81, 0xce, 0x3a, 0x7b, 0x98, 0x58, 0xbb, 0xd7, 0x78, 0xc8, 0x3f, 0x13, 0xf1, 0x74, 0x19, 0xdf, 0xf8, 0x98, 0x89, 0x5d, 0xfa, 0x5f}}}, {{{0x9e, 0x35, 0x85, 0x94, 0x47, 0x1f, 0x90, 0x15, 0x26, 0xd0, 0x84, 0xed, 0x8a, 0x80, 0xf7, 0x63, 0x42, 0x86, 0x27, 0xd7, 0xf4, 0x75, 0x58, 0xdc, 0x9c, 0xc0, 0x22, 0x7e, 0x20, 0x35, 0xfd, 0x1f}} , {{0x68, 0x0e, 0x6f, 0x97, 0xba, 0x70, 0xbb, 0xa3, 0x0e, 0xe5, 0x0b, 0x12, 0xf4, 0xa2, 0xdc, 0x47, 0xf8, 0xe6, 0xd0, 0x23, 0x6c, 0x33, 0xa8, 0x99, 0x46, 0x6e, 0x0f, 0x44, 0xba, 0x76, 0x48, 0x0f}}}, {{{0xa3, 0x2a, 0x61, 0x37, 0xe2, 0x59, 0x12, 0x0e, 0x27, 0xba, 0x64, 0x43, 0xae, 0xc0, 0x42, 0x69, 0x79, 0xa4, 0x1e, 0x29, 0x8b, 0x15, 0xeb, 0xf8, 0xaf, 0xd4, 0xa2, 0x68, 0x33, 0xb5, 0x7a, 0x24}} , {{0x2c, 0x19, 0x33, 0xdd, 0x1b, 0xab, 0xec, 0x01, 0xb0, 0x23, 0xf8, 0x42, 0x2b, 0x06, 0x88, 0xea, 0x3d, 0x2d, 0x00, 0x2a, 0x78, 0x45, 0x4d, 0x38, 0xed, 0x2e, 0x2e, 0x44, 0x49, 0xed, 0xcb, 0x33}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa0, 0x68, 0xe8, 0x41, 0x8f, 0x91, 0xf8, 0x11, 0x13, 0x90, 0x2e, 0xa7, 0xab, 0x30, 0xef, 0xad, 0xa0, 0x61, 0x00, 0x88, 0xef, 0xdb, 0xce, 0x5b, 0x5c, 0xbb, 0x62, 0xc8, 0x56, 0xf9, 0x00, 0x73}} , {{0x3f, 0x60, 0xc1, 0x82, 0x2d, 0xa3, 0x28, 0x58, 0x24, 0x9e, 0x9f, 0xe3, 0x70, 0xcc, 0x09, 0x4e, 0x1a, 0x3f, 0x11, 0x11, 0x15, 0x07, 0x3c, 0xa4, 0x41, 0xe0, 0x65, 0xa3, 0x0a, 0x41, 0x6d, 0x11}}}, {{{0x31, 0x40, 0x01, 0x52, 0x56, 0x94, 0x5b, 0x28, 0x8a, 0xaa, 0x52, 0xee, 0xd8, 0x0a, 0x05, 0x8d, 0xcd, 0xb5, 0xaa, 0x2e, 0x38, 0xaa, 0xb7, 0x87, 0xf7, 0x2b, 0xfb, 0x04, 0xcb, 0x84, 0x3d, 0x54}} , {{0x20, 0xef, 0x59, 0xde, 0xa4, 0x2b, 0x93, 0x6e, 0x2e, 0xec, 0x42, 0x9a, 0xd4, 0x2d, 0xf4, 0x46, 0x58, 0x27, 0x2b, 0x18, 0x8f, 0x83, 0x3d, 0x69, 0x9e, 0xd4, 0x3e, 0xb6, 0xc5, 0xfd, 0x58, 0x03}}}, {{{0x33, 0x89, 0xc9, 0x63, 0x62, 0x1c, 0x17, 0xb4, 0x60, 0xc4, 0x26, 0x68, 0x09, 0xc3, 0x2e, 0x37, 0x0f, 0x7b, 0xb4, 0x9c, 0xb6, 0xf9, 0xfb, 0xd4, 0x51, 0x78, 0xc8, 0x63, 0xea, 0x77, 0x47, 0x07}} , {{0x32, 0xb4, 0x18, 0x47, 0x79, 0xcb, 0xd4, 0x5a, 0x07, 0x14, 0x0f, 0xa0, 0xd5, 0xac, 0xd0, 0x41, 0x40, 0xab, 0x61, 0x23, 0xe5, 0x2a, 0x2a, 0x6f, 0xf7, 0xa8, 0xd4, 0x76, 0xef, 0xe7, 0x45, 0x6c}}}, {{{0xa1, 0x5e, 0x60, 0x4f, 0xfb, 0xe1, 0x70, 0x6a, 0x1f, 0x55, 0x4f, 0x09, 0xb4, 0x95, 0x33, 0x36, 0xc6, 0x81, 0x01, 0x18, 0x06, 0x25, 0x27, 0xa4, 0xb4, 0x24, 0xa4, 0x86, 0x03, 0x4c, 0xac, 0x02}} , {{0x77, 0x38, 0xde, 0xd7, 0x60, 0x48, 0x07, 0xf0, 0x74, 0xa8, 0xff, 0x54, 0xe5, 0x30, 0x43, 0xff, 0x77, 0xfb, 0x21, 0x07, 0xff, 0xb2, 0x07, 0x6b, 0xe4, 0xe5, 0x30, 0xfc, 0x19, 0x6c, 0xa3, 0x01}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x13, 0xc5, 0x2c, 0xac, 0xd3, 0x83, 0x82, 0x7c, 0x29, 0xf7, 0x05, 0xa5, 0x00, 0xb6, 0x1f, 0x86, 0x55, 0xf4, 0xd6, 0x2f, 0x0c, 0x99, 0xd0, 0x65, 0x9b, 0x6b, 0x46, 0x0d, 0x43, 0xf8, 0x16, 0x28}} , {{0x1e, 0x7f, 0xb4, 0x74, 0x7e, 0xb1, 0x89, 0x4f, 0x18, 0x5a, 0xab, 0x64, 0x06, 0xdf, 0x45, 0x87, 0xe0, 0x6a, 0xc6, 0xf0, 0x0e, 0xc9, 0x24, 0x35, 0x38, 0xea, 0x30, 0x54, 0xb4, 0xc4, 0x52, 0x54}}}, {{{0xe9, 0x9f, 0xdc, 0x3f, 0xc1, 0x89, 0x44, 0x74, 0x27, 0xe4, 0xc1, 0x90, 0xff, 0x4a, 0xa7, 0x3c, 0xee, 0xcd, 0xf4, 0x1d, 0x25, 0x94, 0x7f, 0x63, 0x16, 0x48, 0xbc, 0x64, 0xfe, 0x95, 0xc4, 0x0c}} , {{0x8b, 0x19, 0x75, 0x6e, 0x03, 0x06, 0x5e, 0x6a, 0x6f, 0x1a, 0x8c, 0xe3, 0xd3, 0x28, 0xf2, 0xe0, 0xb9, 0x7a, 0x43, 0x69, 0xe6, 0xd3, 0xc0, 0xfe, 0x7e, 0x97, 0xab, 0x6c, 0x7b, 0x8e, 0x13, 0x42}}}, {{{0xd4, 0xca, 0x70, 0x3d, 0xab, 0xfb, 0x5f, 0x5e, 0x00, 0x0c, 0xcc, 0x77, 0x22, 0xf8, 0x78, 0x55, 0xae, 0x62, 0x35, 0xfb, 0x9a, 0xc6, 0x03, 0xe4, 0x0c, 0xee, 0xab, 0xc7, 0xc0, 0x89, 0x87, 0x54}} , {{0x32, 0xad, 0xae, 0x85, 0x58, 0x43, 0xb8, 0xb1, 0xe6, 0x3e, 0x00, 0x9c, 0x78, 0x88, 0x56, 0xdb, 0x9c, 0xfc, 0x79, 0xf6, 0xf9, 0x41, 0x5f, 0xb7, 0xbc, 0x11, 0xf9, 0x20, 0x36, 0x1c, 0x53, 0x2b}}}, {{{0x5a, 0x20, 0x5b, 0xa1, 0xa5, 0x44, 0x91, 0x24, 0x02, 0x63, 0x12, 0x64, 0xb8, 0x55, 0xf6, 0xde, 0x2c, 0xdb, 0x47, 0xb8, 0xc6, 0x0a, 0xc3, 0x00, 0x78, 0x93, 0xd8, 0xf5, 0xf5, 0x18, 0x28, 0x0a}} , {{0xd6, 0x1b, 0x9a, 0x6c, 0xe5, 0x46, 0xea, 0x70, 0x96, 0x8d, 0x4e, 0x2a, 0x52, 0x21, 0x26, 0x4b, 0xb1, 0xbb, 0x0f, 0x7c, 0xa9, 0x9b, 0x04, 0xbb, 0x51, 0x08, 0xf1, 0x9a, 0xa4, 0x76, 0x7c, 0x18}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xfa, 0x94, 0xf7, 0x40, 0xd0, 0xd7, 0xeb, 0xa9, 0x82, 0x36, 0xd5, 0x15, 0xb9, 0x33, 0x7a, 0xbf, 0x8a, 0xf2, 0x63, 0xaa, 0x37, 0xf5, 0x59, 0xac, 0xbd, 0xbb, 0x32, 0x36, 0xbe, 0x73, 0x99, 0x38}} , {{0x2c, 0xb3, 0xda, 0x7a, 0xd8, 0x3d, 0x99, 0xca, 0xd2, 0xf4, 0xda, 0x99, 0x8e, 0x4f, 0x98, 0xb7, 0xf4, 0xae, 0x3e, 0x9f, 0x8e, 0x35, 0x60, 0xa4, 0x33, 0x75, 0xa4, 0x04, 0x93, 0xb1, 0x6b, 0x4d}}}, {{{0x97, 0x9d, 0xa8, 0xcd, 0x97, 0x7b, 0x9d, 0xb9, 0xe7, 0xa5, 0xef, 0xfd, 0xa8, 0x42, 0x6b, 0xc3, 0x62, 0x64, 0x7d, 0xa5, 0x1b, 0xc9, 0x9e, 0xd2, 0x45, 0xb9, 0xee, 0x03, 0xb0, 0xbf, 0xc0, 0x68}} , {{0xed, 0xb7, 0x84, 0x2c, 0xf6, 0xd3, 0xa1, 0x6b, 0x24, 0x6d, 0x87, 0x56, 0x97, 0x59, 0x79, 0x62, 0x9f, 0xac, 0xed, 0xf3, 0xc9, 0x89, 0x21, 0x2e, 0x04, 0xb3, 0xcc, 0x2f, 0xbe, 0xd6, 0x0a, 0x4b}}}, {{{0x39, 0x61, 0x05, 0xed, 0x25, 0x89, 0x8b, 0x5d, 0x1b, 0xcb, 0x0c, 0x55, 0xf4, 0x6a, 0x00, 0x8a, 0x46, 0xe8, 0x1e, 0xc6, 0x83, 0xc8, 0x5a, 0x76, 0xdb, 0xcc, 0x19, 0x7a, 0xcc, 0x67, 0x46, 0x0b}} , {{0x53, 0xcf, 0xc2, 0xa1, 0xad, 0x6a, 0xf3, 0xcd, 0x8f, 0xc9, 0xde, 0x1c, 0xf8, 0x6c, 0x8f, 0xf8, 0x76, 0x42, 0xe7, 0xfe, 0xb2, 0x72, 0x21, 0x0a, 0x66, 0x74, 0x8f, 0xb7, 0xeb, 0xe4, 0x6f, 0x01}}}, {{{0x22, 0x8c, 0x6b, 0xbe, 0xfc, 0x4d, 0x70, 0x62, 0x6e, 0x52, 0x77, 0x99, 0x88, 0x7e, 0x7b, 0x57, 0x7a, 0x0d, 0xfe, 0xdc, 0x72, 0x92, 0xf1, 0x68, 0x1d, 0x97, 0xd7, 0x7c, 0x8d, 0x53, 0x10, 0x37}} , {{0x53, 0x88, 0x77, 0x02, 0xca, 0x27, 0xa8, 0xe5, 0x45, 0xe2, 0xa8, 0x48, 0x2a, 0xab, 0x18, 0xca, 0xea, 0x2d, 0x2a, 0x54, 0x17, 0x37, 0x32, 0x09, 0xdc, 0xe0, 0x4a, 0xb7, 0x7d, 0x82, 0x10, 0x7d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8a, 0x64, 0x1e, 0x14, 0x0a, 0x57, 0xd4, 0xda, 0x5c, 0x96, 0x9b, 0x01, 0x4c, 0x67, 0xbf, 0x8b, 0x30, 0xfe, 0x08, 0xdb, 0x0d, 0xd5, 0xa8, 0xd7, 0x09, 0x11, 0x85, 0xa2, 0xd3, 0x45, 0xfb, 0x7e}} , {{0xda, 0x8c, 0xc2, 0xd0, 0xac, 0x18, 0xe8, 0x52, 0x36, 0xd4, 0x21, 0xa3, 0xdd, 0x57, 0x22, 0x79, 0xb7, 0xf8, 0x71, 0x9d, 0xc6, 0x91, 0x70, 0x86, 0x56, 0xbf, 0xa1, 0x11, 0x8b, 0x19, 0xe1, 0x0f}}}, {{{0x18, 0x32, 0x98, 0x2c, 0x8f, 0x91, 0xae, 0x12, 0xf0, 0x8c, 0xea, 0xf3, 0x3c, 0xb9, 0x5d, 0xe4, 0x69, 0xed, 0xb2, 0x47, 0x18, 0xbd, 0xce, 0x16, 0x52, 0x5c, 0x23, 0xe2, 0xa5, 0x25, 0x52, 0x5d}} , {{0xb9, 0xb1, 0xe7, 0x5d, 0x4e, 0xbc, 0xee, 0xbb, 0x40, 0x81, 0x77, 0x82, 0x19, 0xab, 0xb5, 0xc6, 0xee, 0xab, 0x5b, 0x6b, 0x63, 0x92, 0x8a, 0x34, 0x8d, 0xcd, 0xee, 0x4f, 0x49, 0xe5, 0xc9, 0x7e}}}, {{{0x21, 0xac, 0x8b, 0x22, 0xcd, 0xc3, 0x9a, 0xe9, 0x5e, 0x78, 0xbd, 0xde, 0xba, 0xad, 0xab, 0xbf, 0x75, 0x41, 0x09, 0xc5, 0x58, 0xa4, 0x7d, 0x92, 0xb0, 0x7f, 0xf2, 0xa1, 0xd1, 0xc0, 0xb3, 0x6d}} , {{0x62, 0x4f, 0xd0, 0x75, 0x77, 0xba, 0x76, 0x77, 0xd7, 0xb8, 0xd8, 0x92, 0x6f, 0x98, 0x34, 0x3d, 0xd6, 0x4e, 0x1c, 0x0f, 0xf0, 0x8f, 0x2e, 0xf1, 0xb3, 0xbd, 0xb1, 0xb9, 0xec, 0x99, 0xb4, 0x07}}}, {{{0x60, 0x57, 0x2e, 0x9a, 0x72, 0x1d, 0x6b, 0x6e, 0x58, 0x33, 0x24, 0x8c, 0x48, 0x39, 0x46, 0x8e, 0x89, 0x6a, 0x88, 0x51, 0x23, 0x62, 0xb5, 0x32, 0x09, 0x36, 0xe3, 0x57, 0xf5, 0x98, 0xde, 0x6f}} , {{0x8b, 0x2c, 0x00, 0x48, 0x4a, 0xf9, 0x5b, 0x87, 0x69, 0x52, 0xe5, 0x5b, 0xd1, 0xb1, 0xe5, 0x25, 0x25, 0xe0, 0x9c, 0xc2, 0x13, 0x44, 0xe8, 0xb9, 0x0a, 0x70, 0xad, 0xbd, 0x0f, 0x51, 0x94, 0x69}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xa2, 0xdc, 0xab, 0xa9, 0x25, 0x2d, 0xac, 0x5f, 0x03, 0x33, 0x08, 0xe7, 0x7e, 0xfe, 0x95, 0x36, 0x3c, 0x5b, 0x3a, 0xd3, 0x05, 0x82, 0x1c, 0x95, 0x2d, 0xd8, 0x77, 0x7e, 0x02, 0xd9, 0x5b, 0x70}} , {{0xc2, 0xfe, 0x1b, 0x0c, 0x67, 0xcd, 0xd6, 0xe0, 0x51, 0x8e, 0x2c, 0xe0, 0x79, 0x88, 0xf0, 0xcf, 0x41, 0x4a, 0xad, 0x23, 0xd4, 0x46, 0xca, 0x94, 0xa1, 0xc3, 0xeb, 0x28, 0x06, 0xfa, 0x17, 0x14}}}, {{{0x7b, 0xaa, 0x70, 0x0a, 0x4b, 0xfb, 0xf5, 0xbf, 0x80, 0xc5, 0xcf, 0x08, 0x7a, 0xdd, 0xa1, 0xf4, 0x9d, 0x54, 0x50, 0x53, 0x23, 0x77, 0x23, 0xf5, 0x34, 0xa5, 0x22, 0xd1, 0x0d, 0x96, 0x2e, 0x47}} , {{0xcc, 0xb7, 0x32, 0x89, 0x57, 0xd0, 0x98, 0x75, 0xe4, 0x37, 0x99, 0xa9, 0xe8, 0xba, 0xed, 0xba, 0xeb, 0xc7, 0x4f, 0x15, 0x76, 0x07, 0x0c, 0x4c, 0xef, 0x9f, 0x52, 0xfc, 0x04, 0x5d, 0x58, 0x10}}}, {{{0xce, 0x82, 0xf0, 0x8f, 0x79, 0x02, 0xa8, 0xd1, 0xda, 0x14, 0x09, 0x48, 0xee, 0x8a, 0x40, 0x98, 0x76, 0x60, 0x54, 0x5a, 0xde, 0x03, 0x24, 0xf5, 0xe6, 0x2f, 0xe1, 0x03, 0xbf, 0x68, 0x82, 0x7f}} , {{0x64, 0xe9, 0x28, 0xc7, 0xa4, 0xcf, 0x2a, 0xf9, 0x90, 0x64, 0x72, 0x2c, 0x8b, 0xeb, 0xec, 0xa0, 0xf2, 0x7d, 0x35, 0xb5, 0x90, 0x4d, 0x7f, 0x5b, 0x4a, 0x49, 0xe4, 0xb8, 0x3b, 0xc8, 0xa1, 0x2f}}}, {{{0x8b, 0xc5, 0xcc, 0x3d, 0x69, 0xa6, 0xa1, 0x18, 0x44, 0xbc, 0x4d, 0x77, 0x37, 0xc7, 0x86, 0xec, 0x0c, 0xc9, 0xd6, 0x44, 0xa9, 0x23, 0x27, 0xb9, 0x03, 0x34, 0xa7, 0x0a, 0xd5, 0xc7, 0x34, 0x37}} , {{0xf9, 0x7e, 0x3e, 0x66, 0xee, 0xf9, 0x99, 0x28, 0xff, 0xad, 0x11, 0xd8, 0xe2, 0x66, 0xc5, 0xcd, 0x0f, 0x0d, 0x0b, 0x6a, 0xfc, 0x7c, 0x24, 0xa8, 0x4f, 0xa8, 0x5e, 0x80, 0x45, 0x8b, 0x6c, 0x41}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xef, 0x1e, 0xec, 0xf7, 0x8d, 0x77, 0xf2, 0xea, 0xdb, 0x60, 0x03, 0x21, 0xc0, 0xff, 0x5e, 0x67, 0xc3, 0x71, 0x0b, 0x21, 0xb4, 0x41, 0xa0, 0x68, 0x38, 0xc6, 0x01, 0xa3, 0xd3, 0x51, 0x3c, 0x3c}} , {{0x92, 0xf8, 0xd6, 0x4b, 0xef, 0x42, 0x13, 0xb2, 0x4a, 0xc4, 0x2e, 0x72, 0x3f, 0xc9, 0x11, 0xbd, 0x74, 0x02, 0x0e, 0xf5, 0x13, 0x9d, 0x83, 0x1a, 0x1b, 0xd5, 0x54, 0xde, 0xc4, 0x1e, 0x16, 0x6c}}}, {{{0x27, 0x52, 0xe4, 0x63, 0xaa, 0x94, 0xe6, 0xc3, 0x28, 0x9c, 0xc6, 0x56, 0xac, 0xfa, 0xb6, 0xbd, 0xe2, 0xcc, 0x76, 0xc6, 0x27, 0x27, 0xa2, 0x8e, 0x78, 0x2b, 0x84, 0x72, 0x10, 0xbd, 0x4e, 0x2a}} , {{0xea, 0xa7, 0x23, 0xef, 0x04, 0x61, 0x80, 0x50, 0xc9, 0x6e, 0xa5, 0x96, 0xd1, 0xd1, 0xc8, 0xc3, 0x18, 0xd7, 0x2d, 0xfd, 0x26, 0xbd, 0xcb, 0x7b, 0x92, 0x51, 0x0e, 0x4a, 0x65, 0x57, 0xb8, 0x49}}}, {{{0xab, 0x55, 0x36, 0xc3, 0xec, 0x63, 0x55, 0x11, 0x55, 0xf6, 0xa5, 0xc7, 0x01, 0x5f, 0xfe, 0x79, 0xd8, 0x0a, 0xf7, 0x03, 0xd8, 0x98, 0x99, 0xf5, 0xd0, 0x00, 0x54, 0x6b, 0x66, 0x28, 0xf5, 0x25}} , {{0x7a, 0x8d, 0xa1, 0x5d, 0x70, 0x5d, 0x51, 0x27, 0xee, 0x30, 0x65, 0x56, 0x95, 0x46, 0xde, 0xbd, 0x03, 0x75, 0xb4, 0x57, 0x59, 0x89, 0xeb, 0x02, 0x9e, 0xcc, 0x89, 0x19, 0xa7, 0xcb, 0x17, 0x67}}}, {{{0x6a, 0xeb, 0xfc, 0x9a, 0x9a, 0x10, 0xce, 0xdb, 0x3a, 0x1c, 0x3c, 0x6a, 0x9d, 0xea, 0x46, 0xbc, 0x45, 0x49, 0xac, 0xe3, 0x41, 0x12, 0x7c, 0xf0, 0xf7, 0x4f, 0xf9, 0xf7, 0xff, 0x2c, 0x89, 0x04}} , {{0x30, 0x31, 0x54, 0x1a, 0x46, 0xca, 0xe6, 0xc6, 0xcb, 0xe2, 0xc3, 0xc1, 0x8b, 0x75, 0x81, 0xbe, 0xee, 0xf8, 0xa3, 0x11, 0x1c, 0x25, 0xa3, 0xa7, 0x35, 0x51, 0x55, 0xe2, 0x25, 0xaa, 0xe2, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xb4, 0x48, 0x10, 0x9f, 0x8a, 0x09, 0x76, 0xfa, 0xf0, 0x7a, 0xb0, 0x70, 0xf7, 0x83, 0x80, 0x52, 0x84, 0x2b, 0x26, 0xa2, 0xc4, 0x5d, 0x4f, 0xba, 0xb1, 0xc8, 0x40, 0x0d, 0x78, 0x97, 0xc4, 0x60}} , {{0xd4, 0xb1, 0x6c, 0x08, 0xc7, 0x40, 0x38, 0x73, 0x5f, 0x0b, 0xf3, 0x76, 0x5d, 0xb2, 0xa5, 0x2f, 0x57, 0x57, 0x07, 0xed, 0x08, 0xa2, 0x6c, 0x4f, 0x08, 0x02, 0xb5, 0x0e, 0xee, 0x44, 0xfa, 0x22}}}, {{{0x0f, 0x00, 0x3f, 0xa6, 0x04, 0x19, 0x56, 0x65, 0x31, 0x7f, 0x8b, 0xeb, 0x0d, 0xe1, 0x47, 0x89, 0x97, 0x16, 0x53, 0xfa, 0x81, 0xa7, 0xaa, 0xb2, 0xbf, 0x67, 0xeb, 0x72, 0x60, 0x81, 0x0d, 0x48}} , {{0x7e, 0x13, 0x33, 0xcd, 0xa8, 0x84, 0x56, 0x1e, 0x67, 0xaf, 0x6b, 0x43, 0xac, 0x17, 0xaf, 0x16, 0xc0, 0x52, 0x99, 0x49, 0x5b, 0x87, 0x73, 0x7e, 0xb5, 0x43, 0xda, 0x6b, 0x1d, 0x0f, 0x2d, 0x55}}}, {{{0xe9, 0x58, 0x1f, 0xff, 0x84, 0x3f, 0x93, 0x1c, 0xcb, 0xe1, 0x30, 0x69, 0xa5, 0x75, 0x19, 0x7e, 0x14, 0x5f, 0xf8, 0xfc, 0x09, 0xdd, 0xa8, 0x78, 0x9d, 0xca, 0x59, 0x8b, 0xd1, 0x30, 0x01, 0x13}} , {{0xff, 0x76, 0x03, 0xc5, 0x4b, 0x89, 0x99, 0x70, 0x00, 0x59, 0x70, 0x9c, 0xd5, 0xd9, 0x11, 0x89, 0x5a, 0x46, 0xfe, 0xef, 0xdc, 0xd9, 0x55, 0x2b, 0x45, 0xa7, 0xb0, 0x2d, 0xfb, 0x24, 0xc2, 0x29}}}, {{{0x38, 0x06, 0xf8, 0x0b, 0xac, 0x82, 0xc4, 0x97, 0x2b, 0x90, 0xe0, 0xf7, 0xa8, 0xab, 0x6c, 0x08, 0x80, 0x66, 0x90, 0x46, 0xf7, 0x26, 0x2d, 0xf8, 0xf1, 0xc4, 0x6b, 0x4a, 0x82, 0x98, 0x8e, 0x37}} , {{0x8e, 0xb4, 0xee, 0xb8, 0xd4, 0x3f, 0xb2, 0x1b, 0xe0, 0x0a, 0x3d, 0x75, 0x34, 0x28, 0xa2, 0x8e, 0xc4, 0x92, 0x7b, 0xfe, 0x60, 0x6e, 0x6d, 0xb8, 0x31, 0x1d, 0x62, 0x0d, 0x78, 0x14, 0x42, 0x11}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x5e, 0xa8, 0xd8, 0x04, 0x9b, 0x73, 0xc9, 0xc9, 0xdc, 0x0d, 0x73, 0xbf, 0x0a, 0x0a, 0x73, 0xff, 0x18, 0x1f, 0x9c, 0x51, 0xaa, 0xc6, 0xf1, 0x83, 0x25, 0xfd, 0xab, 0xa3, 0x11, 0xd3, 0x01, 0x24}} , {{0x4d, 0xe3, 0x7e, 0x38, 0x62, 0x5e, 0x64, 0xbb, 0x2b, 0x53, 0xb5, 0x03, 0x68, 0xc4, 0xf2, 0x2b, 0x5a, 0x03, 0x32, 0x99, 0x4a, 0x41, 0x9a, 0xe1, 0x1a, 0xae, 0x8c, 0x48, 0xf3, 0x24, 0x32, 0x65}}}, {{{0xe8, 0xdd, 0xad, 0x3a, 0x8c, 0xea, 0xf4, 0xb3, 0xb2, 0xe5, 0x73, 0xf2, 0xed, 0x8b, 0xbf, 0xed, 0xb1, 0x0c, 0x0c, 0xfb, 0x2b, 0xf1, 0x01, 0x48, 0xe8, 0x26, 0x03, 0x8e, 0x27, 0x4d, 0x96, 0x72}} , {{0xc8, 0x09, 0x3b, 0x60, 0xc9, 0x26, 0x4d, 0x7c, 0xf2, 0x9c, 0xd4, 0xa1, 0x3b, 0x26, 0xc2, 0x04, 0x33, 0x44, 0x76, 0x3c, 0x02, 0xbb, 0x11, 0x42, 0x0c, 0x22, 0xb7, 0xc6, 0xe1, 0xac, 0xb4, 0x0e}}}, {{{0x6f, 0x85, 0xe7, 0xef, 0xde, 0x67, 0x30, 0xfc, 0xbf, 0x5a, 0xe0, 0x7b, 0x7a, 0x2a, 0x54, 0x6b, 0x5d, 0x62, 0x85, 0xa1, 0xf8, 0x16, 0x88, 0xec, 0x61, 0xb9, 0x96, 0xb5, 0xef, 0x2d, 0x43, 0x4d}} , {{0x7c, 0x31, 0x33, 0xcc, 0xe4, 0xcf, 0x6c, 0xff, 0x80, 0x47, 0x77, 0xd1, 0xd8, 0xe9, 0x69, 0x97, 0x98, 0x7f, 0x20, 0x57, 0x1d, 0x1d, 0x4f, 0x08, 0x27, 0xc8, 0x35, 0x57, 0x40, 0xc6, 0x21, 0x0c}}}, {{{0xd2, 0x8e, 0x9b, 0xfa, 0x42, 0x8e, 0xdf, 0x8f, 0xc7, 0x86, 0xf9, 0xa4, 0xca, 0x70, 0x00, 0x9d, 0x21, 0xbf, 0xec, 0x57, 0x62, 0x30, 0x58, 0x8c, 0x0d, 0x35, 0xdb, 0x5d, 0x8b, 0x6a, 0xa0, 0x5a}} , {{0xc1, 0x58, 0x7c, 0x0d, 0x20, 0xdd, 0x11, 0x26, 0x5f, 0x89, 0x3b, 0x97, 0x58, 0xf8, 0x8b, 0xe3, 0xdf, 0x32, 0xe2, 0xfc, 0xd8, 0x67, 0xf2, 0xa5, 0x37, 0x1e, 0x6d, 0xec, 0x7c, 0x27, 0x20, 0x79}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xd0, 0xe9, 0xc0, 0xfa, 0x95, 0x45, 0x23, 0x96, 0xf1, 0x2c, 0x79, 0x25, 0x14, 0xce, 0x40, 0x14, 0x44, 0x2c, 0x36, 0x50, 0xd9, 0x63, 0x56, 0xb7, 0x56, 0x3b, 0x9e, 0xa7, 0xef, 0x89, 0xbb, 0x0e}} , {{0xce, 0x7f, 0xdc, 0x0a, 0xcc, 0x82, 0x1c, 0x0a, 0x78, 0x71, 0xe8, 0x74, 0x8d, 0x01, 0x30, 0x0f, 0xa7, 0x11, 0x4c, 0xdf, 0x38, 0xd7, 0xa7, 0x0d, 0xf8, 0x48, 0x52, 0x00, 0x80, 0x7b, 0x5f, 0x0e}}}, {{{0x25, 0x83, 0xe6, 0x94, 0x7b, 0x81, 0xb2, 0x91, 0xae, 0x0e, 0x05, 0xc9, 0xa3, 0x68, 0x2d, 0xd9, 0x88, 0x25, 0x19, 0x2a, 0x61, 0x61, 0x21, 0x97, 0x15, 0xa1, 0x35, 0xa5, 0x46, 0xc8, 0xa2, 0x0e}} , {{0x1b, 0x03, 0x0d, 0x8b, 0x5a, 0x1b, 0x97, 0x4b, 0xf2, 0x16, 0x31, 0x3d, 0x1f, 0x33, 0xa0, 0x50, 0x3a, 0x18, 0xbe, 0x13, 0xa1, 0x76, 0xc1, 0xba, 0x1b, 0xf1, 0x05, 0x7b, 0x33, 0xa8, 0x82, 0x3b}}}, {{{0xba, 0x36, 0x7b, 0x6d, 0xa9, 0xea, 0x14, 0x12, 0xc5, 0xfa, 0x91, 0x00, 0xba, 0x9b, 0x99, 0xcc, 0x56, 0x02, 0xe9, 0xa0, 0x26, 0x40, 0x66, 0x8c, 0xc4, 0xf8, 0x85, 0x33, 0x68, 0xe7, 0x03, 0x20}} , {{0x50, 0x5b, 0xff, 0xa9, 0xb2, 0xf1, 0xf1, 0x78, 0xcf, 0x14, 0xa4, 0xa9, 0xfc, 0x09, 0x46, 0x94, 0x54, 0x65, 0x0d, 0x9c, 0x5f, 0x72, 0x21, 0xe2, 0x97, 0xa5, 0x2d, 0x81, 0xce, 0x4a, 0x5f, 0x79}}}, {{{0x3d, 0x5f, 0x5c, 0xd2, 0xbc, 0x7d, 0x77, 0x0e, 0x2a, 0x6d, 0x22, 0x45, 0x84, 0x06, 0xc4, 0xdd, 0xc6, 0xa6, 0xc6, 0xd7, 0x49, 0xad, 0x6d, 0x87, 0x91, 0x0e, 0x3a, 0x67, 0x1d, 0x2c, 0x1d, 0x56}} , {{0xfe, 0x7a, 0x74, 0xcf, 0xd4, 0xd2, 0xe5, 0x19, 0xde, 0xd0, 0xdb, 0x70, 0x23, 0x69, 0xe6, 0x6d, 0xec, 0xec, 0xcc, 0x09, 0x33, 0x6a, 0x77, 0xdc, 0x6b, 0x22, 0x76, 0x5d, 0x92, 0x09, 0xac, 0x2d}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x23, 0x15, 0x17, 0xeb, 0xd3, 0xdb, 0x12, 0x5e, 0x01, 0xf0, 0x91, 0xab, 0x2c, 0x41, 0xce, 0xac, 0xed, 0x1b, 0x4b, 0x2d, 0xbc, 0xdb, 0x17, 0x66, 0x89, 0x46, 0xad, 0x4b, 0x1e, 0x6f, 0x0b, 0x14}} , {{0x11, 0xce, 0xbf, 0xb6, 0x77, 0x2d, 0x48, 0x22, 0x18, 0x4f, 0xa3, 0x5d, 0x4a, 0xb0, 0x70, 0x12, 0x3e, 0x54, 0xd7, 0xd8, 0x0e, 0x2b, 0x27, 0xdc, 0x53, 0xff, 0xca, 0x8c, 0x59, 0xb3, 0x4e, 0x44}}}, {{{0x07, 0x76, 0x61, 0x0f, 0x66, 0xb2, 0x21, 0x39, 0x7e, 0xc0, 0xec, 0x45, 0x28, 0x82, 0xa1, 0x29, 0x32, 0x44, 0x35, 0x13, 0x5e, 0x61, 0x5e, 0x54, 0xcb, 0x7c, 0xef, 0xf6, 0x41, 0xcf, 0x9f, 0x0a}} , {{0xdd, 0xf9, 0xda, 0x84, 0xc3, 0xe6, 0x8a, 0x9f, 0x24, 0xd2, 0x96, 0x5d, 0x39, 0x6f, 0x58, 0x8c, 0xc1, 0x56, 0x93, 0xab, 0xb5, 0x79, 0x3b, 0xd2, 0xa8, 0x73, 0x16, 0xed, 0xfa, 0xb4, 0x2f, 0x73}}}, {{{0x8b, 0xb1, 0x95, 0xe5, 0x92, 0x50, 0x35, 0x11, 0x76, 0xac, 0xf4, 0x4d, 0x24, 0xc3, 0x32, 0xe6, 0xeb, 0xfe, 0x2c, 0x87, 0xc4, 0xf1, 0x56, 0xc4, 0x75, 0x24, 0x7a, 0x56, 0x85, 0x5a, 0x3a, 0x13}} , {{0x0d, 0x16, 0xac, 0x3c, 0x4a, 0x58, 0x86, 0x3a, 0x46, 0x7f, 0x6c, 0xa3, 0x52, 0x6e, 0x37, 0xe4, 0x96, 0x9c, 0xe9, 0x5c, 0x66, 0x41, 0x67, 0xe4, 0xfb, 0x79, 0x0c, 0x05, 0xf6, 0x64, 0xd5, 0x7c}}}, {{{0x28, 0xc1, 0xe1, 0x54, 0x73, 0xf2, 0xbf, 0x76, 0x74, 0x19, 0x19, 0x1b, 0xe4, 0xb9, 0xa8, 0x46, 0x65, 0x73, 0xf3, 0x77, 0x9b, 0x29, 0x74, 0x5b, 0xc6, 0x89, 0x6c, 0x2c, 0x7c, 0xf8, 0xb3, 0x0f}} , {{0xf7, 0xd5, 0xe9, 0x74, 0x5d, 0xb8, 0x25, 0x16, 0xb5, 0x30, 0xbc, 0x84, 0xc5, 0xf0, 0xad, 0xca, 0x12, 0x28, 0xbc, 0x9d, 0xd4, 0xfa, 0x82, 0xe6, 0xe3, 0xbf, 0xa2, 0x15, 0x2c, 0xd4, 0x34, 0x10}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x61, 0xb1, 0x46, 0xba, 0x0e, 0x31, 0xa5, 0x67, 0x6c, 0x7f, 0xd6, 0xd9, 0x27, 0x85, 0x0f, 0x79, 0x14, 0xc8, 0x6c, 0x2f, 0x5f, 0x5b, 0x9c, 0x35, 0x3d, 0x38, 0x86, 0x77, 0x65, 0x55, 0x6a, 0x7b}} , {{0xd3, 0xb0, 0x3a, 0x66, 0x60, 0x1b, 0x43, 0xf1, 0x26, 0x58, 0x99, 0x09, 0x8f, 0x2d, 0xa3, 0x14, 0x71, 0x85, 0xdb, 0xed, 0xf6, 0x26, 0xd5, 0x61, 0x9a, 0x73, 0xac, 0x0e, 0xea, 0xac, 0xb7, 0x0c}}}, {{{0x5e, 0xf4, 0xe5, 0x17, 0x0e, 0x10, 0x9f, 0xe7, 0x43, 0x5f, 0x67, 0x5c, 0xac, 0x4b, 0xe5, 0x14, 0x41, 0xd2, 0xbf, 0x48, 0xf5, 0x14, 0xb0, 0x71, 0xc6, 0x61, 0xc1, 0xb2, 0x70, 0x58, 0xd2, 0x5a}} , {{0x2d, 0xba, 0x16, 0x07, 0x92, 0x94, 0xdc, 0xbd, 0x50, 0x2b, 0xc9, 0x7f, 0x42, 0x00, 0xba, 0x61, 0xed, 0xf8, 0x43, 0xed, 0xf5, 0xf9, 0x40, 0x60, 0xb2, 0xb0, 0x82, 0xcb, 0xed, 0x75, 0xc7, 0x65}}}, {{{0x80, 0xba, 0x0d, 0x09, 0x40, 0xa7, 0x39, 0xa6, 0x67, 0x34, 0x7e, 0x66, 0xbe, 0x56, 0xfb, 0x53, 0x78, 0xc4, 0x46, 0xe8, 0xed, 0x68, 0x6c, 0x7f, 0xce, 0xe8, 0x9f, 0xce, 0xa2, 0x64, 0x58, 0x53}} , {{0xe8, 0xc1, 0xa9, 0xc2, 0x7b, 0x59, 0x21, 0x33, 0xe2, 0x43, 0x73, 0x2b, 0xac, 0x2d, 0xc1, 0x89, 0x3b, 0x15, 0xe2, 0xd5, 0xc0, 0x97, 0x8a, 0xfd, 0x6f, 0x36, 0x33, 0xb7, 0xb9, 0xc3, 0x88, 0x09}}}, {{{0xd0, 0xb6, 0x56, 0x30, 0x5c, 0xae, 0xb3, 0x75, 0x44, 0xa4, 0x83, 0x51, 0x6e, 0x01, 0x65, 0xef, 0x45, 0x76, 0xe6, 0xf5, 0xa2, 0x0d, 0xd4, 0x16, 0x3b, 0x58, 0x2f, 0xf2, 0x2f, 0x36, 0x18, 0x3f}} , {{0xfd, 0x2f, 0xe0, 0x9b, 0x1e, 0x8c, 0xc5, 0x18, 0xa9, 0xca, 0xd4, 0x2b, 0x35, 0xb6, 0x95, 0x0a, 0x9f, 0x7e, 0xfb, 0xc4, 0xef, 0x88, 0x7b, 0x23, 0x43, 0xec, 0x2f, 0x0d, 0x0f, 0x7a, 0xfc, 0x5c}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b}} , {{0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61}}}, {{{0x54, 0x83, 0x02, 0x18, 0x82, 0x93, 0x99, 0x07, 0xd0, 0xa7, 0xda, 0xd8, 0x75, 0x89, 0xfa, 0xf2, 0xd9, 0xa3, 0xb8, 0x6b, 0x5a, 0x35, 0x28, 0xd2, 0x6b, 0x59, 0xc2, 0xf8, 0x45, 0xe2, 0xbc, 0x06}} , {{0x65, 0xc0, 0xa3, 0x88, 0x51, 0x95, 0xfc, 0x96, 0x94, 0x78, 0xe8, 0x0d, 0x8b, 0x41, 0xc9, 0xc2, 0x58, 0x48, 0x75, 0x10, 0x2f, 0xcd, 0x2a, 0xc9, 0xa0, 0x6d, 0x0f, 0xdd, 0x9c, 0x98, 0x26, 0x3d}}}, {{{0x2f, 0x66, 0x29, 0x1b, 0x04, 0x89, 0xbd, 0x7e, 0xee, 0x6e, 0xdd, 0xb7, 0x0e, 0xef, 0xb0, 0x0c, 0xb4, 0xfc, 0x7f, 0xc2, 0xc9, 0x3a, 0x3c, 0x64, 0xef, 0x45, 0x44, 0xaf, 0x8a, 0x90, 0x65, 0x76}} , {{0xa1, 0x4c, 0x70, 0x4b, 0x0e, 0xa0, 0x83, 0x70, 0x13, 0xa4, 0xaf, 0xb8, 0x38, 0x19, 0x22, 0x65, 0x09, 0xb4, 0x02, 0x4f, 0x06, 0xf8, 0x17, 0xce, 0x46, 0x45, 0xda, 0x50, 0x7c, 0x8a, 0xd1, 0x4e}}}, {{{0xf7, 0xd4, 0x16, 0x6c, 0x4e, 0x95, 0x9d, 0x5d, 0x0f, 0x91, 0x2b, 0x52, 0xfe, 0x5c, 0x34, 0xe5, 0x30, 0xe6, 0xa4, 0x3b, 0xf3, 0xf3, 0x34, 0x08, 0xa9, 0x4a, 0xa0, 0xb5, 0x6e, 0xb3, 0x09, 0x0a}} , {{0x26, 0xd9, 0x5e, 0xa3, 0x0f, 0xeb, 0xa2, 0xf3, 0x20, 0x3b, 0x37, 0xd4, 0xe4, 0x9e, 0xce, 0x06, 0x3d, 0x53, 0xed, 0xae, 0x2b, 0xeb, 0xb6, 0x24, 0x0a, 0x11, 0xa3, 0x0f, 0xd6, 0x7f, 0xa4, 0x3a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xdb, 0x9f, 0x2c, 0xfc, 0xd6, 0xb2, 0x1e, 0x2e, 0x52, 0x7a, 0x06, 0x87, 0x2d, 0x86, 0x72, 0x2b, 0x6d, 0x90, 0x77, 0x46, 0x43, 0xb5, 0x7a, 0xf8, 0x60, 0x7d, 0x91, 0x60, 0x5b, 0x9d, 0x9e, 0x07}} , {{0x97, 0x87, 0xc7, 0x04, 0x1c, 0x38, 0x01, 0x39, 0x58, 0xc7, 0x85, 0xa3, 0xfc, 0x64, 0x00, 0x64, 0x25, 0xa2, 0xbf, 0x50, 0x94, 0xca, 0x26, 0x31, 0x45, 0x0a, 0x24, 0xd2, 0x51, 0x29, 0x51, 0x16}}}, {{{0x4d, 0x4a, 0xd7, 0x98, 0x71, 0x57, 0xac, 0x7d, 0x8b, 0x37, 0xbd, 0x63, 0xff, 0x87, 0xb1, 0x49, 0x95, 0x20, 0x7c, 0xcf, 0x7c, 0x59, 0xc4, 0x91, 0x9c, 0xef, 0xd0, 0xdb, 0x60, 0x09, 0x9d, 0x46}} , {{0xcb, 0x78, 0x94, 0x90, 0xe4, 0x45, 0xb3, 0xf6, 0xd9, 0xf6, 0x57, 0x74, 0xd5, 0xf8, 0x83, 0x4f, 0x39, 0xc9, 0xbd, 0x88, 0xc2, 0x57, 0x21, 0x1f, 0x24, 0x32, 0x68, 0xf8, 0xc7, 0x21, 0x5f, 0x0b}}}, {{{0x2a, 0x36, 0x68, 0xfc, 0x5f, 0xb6, 0x4f, 0xa5, 0xe3, 0x9d, 0x24, 0x2f, 0xc0, 0x93, 0x61, 0xcf, 0xf8, 0x0a, 0xed, 0xe1, 0xdb, 0x27, 0xec, 0x0e, 0x14, 0x32, 0x5f, 0x8e, 0xa1, 0x62, 0x41, 0x16}} , {{0x95, 0x21, 0x01, 0xce, 0x95, 0x5b, 0x0e, 0x57, 0xc7, 0xb9, 0x62, 0xb5, 0x28, 0xca, 0x11, 0xec, 0xb4, 0x46, 0x06, 0x73, 0x26, 0xff, 0xfb, 0x66, 0x7d, 0xee, 0x5f, 0xb2, 0x56, 0xfd, 0x2a, 0x08}}}, {{{0x92, 0x67, 0x77, 0x56, 0xa1, 0xff, 0xc4, 0xc5, 0x95, 0xf0, 0xe3, 0x3a, 0x0a, 0xca, 0x94, 0x4d, 0x9e, 0x7e, 0x3d, 0xb9, 0x6e, 0xb6, 0xb0, 0xce, 0xa4, 0x30, 0x89, 0x99, 0xe9, 0xad, 0x11, 0x59}} , {{0xf6, 0x48, 0x95, 0xa1, 0x6f, 0x5f, 0xb7, 0xa5, 0xbb, 0x30, 0x00, 0x1c, 0xd2, 0x8a, 0xd6, 0x25, 0x26, 0x1b, 0xb2, 0x0d, 0x37, 0x6a, 0x05, 0xf4, 0x9d, 0x3e, 0x17, 0x2a, 0x43, 0xd2, 0x3a, 0x06}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x32, 0x99, 0x93, 0xd1, 0x9a, 0x72, 0xf3, 0xa9, 0x16, 0xbd, 0xb4, 0x4c, 0xdd, 0xf9, 0xd4, 0xb2, 0x64, 0x9a, 0xd3, 0x05, 0xe4, 0xa3, 0x73, 0x1c, 0xcb, 0x7e, 0x57, 0x67, 0xff, 0x04, 0xb3, 0x10}} , {{0xb9, 0x4b, 0xa4, 0xad, 0xd0, 0x6d, 0x61, 0x23, 0xb4, 0xaf, 0x34, 0xa9, 0xaa, 0x65, 0xec, 0xd9, 0x69, 0xe3, 0x85, 0xcd, 0xcc, 0xe7, 0xb0, 0x9b, 0x41, 0xc1, 0x1c, 0xf9, 0xa0, 0xfa, 0xb7, 0x13}}}, {{{0x04, 0xfd, 0x88, 0x3c, 0x0c, 0xd0, 0x09, 0x52, 0x51, 0x4f, 0x06, 0x19, 0xcc, 0xc3, 0xbb, 0xde, 0x80, 0xc5, 0x33, 0xbc, 0xf9, 0xf3, 0x17, 0x36, 0xdd, 0xc6, 0xde, 0xe8, 0x9b, 0x5d, 0x79, 0x1b}} , {{0x65, 0x0a, 0xbe, 0x51, 0x57, 0xad, 0x50, 0x79, 0x08, 0x71, 0x9b, 0x07, 0x95, 0x8f, 0xfb, 0xae, 0x4b, 0x38, 0xba, 0xcf, 0x53, 0x2a, 0x86, 0x1e, 0xc0, 0x50, 0x5c, 0x67, 0x1b, 0xf6, 0x87, 0x6c}}}, {{{0x4f, 0x00, 0xb2, 0x66, 0x55, 0xed, 0x4a, 0xed, 0x8d, 0xe1, 0x66, 0x18, 0xb2, 0x14, 0x74, 0x8d, 0xfd, 0x1a, 0x36, 0x0f, 0x26, 0x5c, 0x8b, 0x89, 0xf3, 0xab, 0xf2, 0xf3, 0x24, 0x67, 0xfd, 0x70}} , {{0xfd, 0x4e, 0x2a, 0xc1, 0x3a, 0xca, 0x8f, 0x00, 0xd8, 0xec, 0x74, 0x67, 0xef, 0x61, 0xe0, 0x28, 0xd0, 0x96, 0xf4, 0x48, 0xde, 0x81, 0xe3, 0xef, 0xdc, 0xaa, 0x7d, 0xf3, 0xb6, 0x55, 0xa6, 0x65}}}, {{{0xeb, 0xcb, 0xc5, 0x70, 0x91, 0x31, 0x10, 0x93, 0x0d, 0xc8, 0xd0, 0xef, 0x62, 0xe8, 0x6f, 0x82, 0xe3, 0x69, 0x3d, 0x91, 0x7f, 0x31, 0xe1, 0x26, 0x35, 0x3c, 0x4a, 0x2f, 0xab, 0xc4, 0x9a, 0x5e}} , {{0xab, 0x1b, 0xb5, 0xe5, 0x2b, 0xc3, 0x0e, 0x29, 0xb0, 0xd0, 0x73, 0xe6, 0x4f, 0x64, 0xf2, 0xbc, 0xe4, 0xe4, 0xe1, 0x9a, 0x52, 0x33, 0x2f, 0xbd, 0xcc, 0x03, 0xee, 0x8a, 0xfa, 0x00, 0x5f, 0x50}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf6, 0xdb, 0x0d, 0x22, 0x3d, 0xb5, 0x14, 0x75, 0x31, 0xf0, 0x81, 0xe2, 0xb9, 0x37, 0xa2, 0xa9, 0x84, 0x11, 0x9a, 0x07, 0xb5, 0x53, 0x89, 0x78, 0xa9, 0x30, 0x27, 0xa1, 0xf1, 0x4e, 0x5c, 0x2e}} , {{0x8b, 0x00, 0x54, 0xfb, 0x4d, 0xdc, 0xcb, 0x17, 0x35, 0x40, 0xff, 0xb7, 0x8c, 0xfe, 0x4a, 0xe4, 0x4e, 0x99, 0x4e, 0xa8, 0x74, 0x54, 0x5d, 0x5c, 0x96, 0xa3, 0x12, 0x55, 0x36, 0x31, 0x17, 0x5c}}}, {{{0xce, 0x24, 0xef, 0x7b, 0x86, 0xf2, 0x0f, 0x77, 0xe8, 0x5c, 0x7d, 0x87, 0x38, 0x2d, 0xef, 0xaf, 0xf2, 0x8c, 0x72, 0x2e, 0xeb, 0xb6, 0x55, 0x4b, 0x6e, 0xf1, 0x4e, 0x8a, 0x0e, 0x9a, 0x6c, 0x4c}} , {{0x25, 0xea, 0x86, 0xc2, 0xd1, 0x4f, 0xb7, 0x3e, 0xa8, 0x5c, 0x8d, 0x66, 0x81, 0x25, 0xed, 0xc5, 0x4c, 0x05, 0xb9, 0xd8, 0xd6, 0x70, 0xbe, 0x73, 0x82, 0xe8, 0xa1, 0xe5, 0x1e, 0x71, 0xd5, 0x26}}}, {{{0x4e, 0x6d, 0xc3, 0xa7, 0x4f, 0x22, 0x45, 0x26, 0xa2, 0x7e, 0x16, 0xf7, 0xf7, 0x63, 0xdc, 0x86, 0x01, 0x2a, 0x71, 0x38, 0x5c, 0x33, 0xc3, 0xce, 0x30, 0xff, 0xf9, 0x2c, 0x91, 0x71, 0x8a, 0x72}} , {{0x8c, 0x44, 0x09, 0x28, 0xd5, 0x23, 0xc9, 0x8f, 0xf3, 0x84, 0x45, 0xc6, 0x9a, 0x5e, 0xff, 0xd2, 0xc7, 0x57, 0x93, 0xa3, 0xc1, 0x69, 0xdd, 0x62, 0x0f, 0xda, 0x5c, 0x30, 0x59, 0x5d, 0xe9, 0x4c}}}, {{{0x92, 0x7e, 0x50, 0x27, 0x72, 0xd7, 0x0c, 0xd6, 0x69, 0x96, 0x81, 0x35, 0x84, 0x94, 0x35, 0x8b, 0x6c, 0xaa, 0x62, 0x86, 0x6e, 0x1c, 0x15, 0xf3, 0x6c, 0xb3, 0xff, 0x65, 0x1b, 0xa2, 0x9b, 0x59}} , {{0xe2, 0xa9, 0x65, 0x88, 0xc4, 0x50, 0xfa, 0xbb, 0x3b, 0x6e, 0x5f, 0x44, 0x01, 0xca, 0x97, 0xd4, 0xdd, 0xf6, 0xcd, 0x3f, 0x3f, 0xe5, 0x97, 0x67, 0x2b, 0x8c, 0x66, 0x0f, 0x35, 0x9b, 0xf5, 0x07}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xf1, 0x59, 0x27, 0xd8, 0xdb, 0x5a, 0x11, 0x5e, 0x82, 0xf3, 0x38, 0xff, 0x1c, 0xed, 0xfe, 0x3f, 0x64, 0x54, 0x3f, 0x7f, 0xd1, 0x81, 0xed, 0xef, 0x65, 0xc5, 0xcb, 0xfd, 0xe1, 0x80, 0xcd, 0x11}} , {{0xe0, 0xdb, 0x22, 0x28, 0xe6, 0xff, 0x61, 0x9d, 0x41, 0x14, 0x2d, 0x3b, 0x26, 0x22, 0xdf, 0xf1, 0x34, 0x81, 0xe9, 0x45, 0xee, 0x0f, 0x98, 0x8b, 0xa6, 0x3f, 0xef, 0xf7, 0x43, 0x19, 0xf1, 0x43}}}, {{{0xee, 0xf3, 0x00, 0xa1, 0x50, 0xde, 0xc0, 0xb6, 0x01, 0xe3, 0x8c, 0x3c, 0x4d, 0x31, 0xd2, 0xb0, 0x58, 0xcd, 0xed, 0x10, 0x4a, 0x7a, 0xef, 0x80, 0xa9, 0x19, 0x32, 0xf3, 0xd8, 0x33, 0x8c, 0x06}} , {{0xcb, 0x7d, 0x4f, 0xff, 0x30, 0xd8, 0x12, 0x3b, 0x39, 0x1c, 0x06, 0xf9, 0x4c, 0x34, 0x35, 0x71, 0xb5, 0x16, 0x94, 0x67, 0xdf, 0xee, 0x11, 0xde, 0xa4, 0x1d, 0x88, 0x93, 0x35, 0xa9, 0x32, 0x10}}}, {{{0xe9, 0xc3, 0xbc, 0x7b, 0x5c, 0xfc, 0xb2, 0xf9, 0xc9, 0x2f, 0xe5, 0xba, 0x3a, 0x0b, 0xab, 0x64, 0x38, 0x6f, 0x5b, 0x4b, 0x93, 0xda, 0x64, 0xec, 0x4d, 0x3d, 0xa0, 0xf5, 0xbb, 0xba, 0x47, 0x48}} , {{0x60, 0xbc, 0x45, 0x1f, 0x23, 0xa2, 0x3b, 0x70, 0x76, 0xe6, 0x97, 0x99, 0x4f, 0x77, 0x54, 0x67, 0x30, 0x9a, 0xe7, 0x66, 0xd6, 0xcd, 0x2e, 0x51, 0x24, 0x2c, 0x42, 0x4a, 0x11, 0xfe, 0x6f, 0x7e}}}, {{{0x87, 0xc0, 0xb1, 0xf0, 0xa3, 0x6f, 0x0c, 0x93, 0xa9, 0x0a, 0x72, 0xef, 0x5c, 0xbe, 0x65, 0x35, 0xa7, 0x6a, 0x4e, 0x2c, 0xbf, 0x21, 0x23, 0xe8, 0x2f, 0x97, 0xc7, 0x3e, 0xc8, 0x17, 0xac, 0x1e}} , {{0x7b, 0xef, 0x21, 0xe5, 0x40, 0xcc, 0x1e, 0xdc, 0xd6, 0xbd, 0x97, 0x7a, 0x7c, 0x75, 0x86, 0x7a, 0x25, 0x5a, 0x6e, 0x7c, 0xe5, 0x51, 0x3c, 0x1b, 0x5b, 0x82, 0x9a, 0x07, 0x60, 0xa1, 0x19, 0x04}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x96, 0x88, 0xa6, 0xab, 0x8f, 0xe3, 0x3a, 0x49, 0xf8, 0xfe, 0x34, 0xe7, 0x6a, 0xb2, 0xfe, 0x40, 0x26, 0x74, 0x57, 0x4c, 0xf6, 0xd4, 0x99, 0xce, 0x5d, 0x7b, 0x2f, 0x67, 0xd6, 0x5a, 0xe4, 0x4e}} , {{0x5c, 0x82, 0xb3, 0xbd, 0x55, 0x25, 0xf6, 0x6a, 0x93, 0xa4, 0x02, 0xc6, 0x7d, 0x5c, 0xb1, 0x2b, 0x5b, 0xff, 0xfb, 0x56, 0xf8, 0x01, 0x41, 0x90, 0xc6, 0xb6, 0xac, 0x4f, 0xfe, 0xa7, 0x41, 0x70}}}, {{{0xdb, 0xfa, 0x9b, 0x2c, 0xd4, 0x23, 0x67, 0x2c, 0x8a, 0x63, 0x6c, 0x07, 0x26, 0x48, 0x4f, 0xc2, 0x03, 0xd2, 0x53, 0x20, 0x28, 0xed, 0x65, 0x71, 0x47, 0xa9, 0x16, 0x16, 0x12, 0xbc, 0x28, 0x33}} , {{0x39, 0xc0, 0xfa, 0xfa, 0xcd, 0x33, 0x43, 0xc7, 0x97, 0x76, 0x9b, 0x93, 0x91, 0x72, 0xeb, 0xc5, 0x18, 0x67, 0x4c, 0x11, 0xf0, 0xf4, 0xe5, 0x73, 0xb2, 0x5c, 0x1b, 0xc2, 0x26, 0x3f, 0xbf, 0x2b}}}, {{{0x86, 0xe6, 0x8c, 0x1d, 0xdf, 0xca, 0xfc, 0xd5, 0xf8, 0x3a, 0xc3, 0x44, 0x72, 0xe6, 0x78, 0x9d, 0x2b, 0x97, 0xf8, 0x28, 0x45, 0xb4, 0x20, 0xc9, 0x2a, 0x8c, 0x67, 0xaa, 0x11, 0xc5, 0x5b, 0x2f}} , {{0x17, 0x0f, 0x86, 0x52, 0xd7, 0x9d, 0xc3, 0x44, 0x51, 0x76, 0x32, 0x65, 0xb4, 0x37, 0x81, 0x99, 0x46, 0x37, 0x62, 0xed, 0xcf, 0x64, 0x9d, 0x72, 0x40, 0x7a, 0x4c, 0x0b, 0x76, 0x2a, 0xfb, 0x56}}}, {{{0x33, 0xa7, 0x90, 0x7c, 0xc3, 0x6f, 0x17, 0xa5, 0xa0, 0x67, 0x72, 0x17, 0xea, 0x7e, 0x63, 0x14, 0x83, 0xde, 0xc1, 0x71, 0x2d, 0x41, 0x32, 0x7a, 0xf3, 0xd1, 0x2b, 0xd8, 0x2a, 0xa6, 0x46, 0x36}} , {{0xac, 0xcc, 0x6b, 0x7c, 0xf9, 0xb8, 0x8b, 0x08, 0x5c, 0xd0, 0x7d, 0x8f, 0x73, 0xea, 0x20, 0xda, 0x86, 0xca, 0x00, 0xc7, 0xad, 0x73, 0x4d, 0xe9, 0xe8, 0xa9, 0xda, 0x1f, 0x03, 0x06, 0xdd, 0x24}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x9c, 0xb2, 0x61, 0x0a, 0x98, 0x2a, 0xa5, 0xd7, 0xee, 0xa9, 0xac, 0x65, 0xcb, 0x0a, 0x1e, 0xe2, 0xbe, 0xdc, 0x85, 0x59, 0x0f, 0x9c, 0xa6, 0x57, 0x34, 0xa5, 0x87, 0xeb, 0x7b, 0x1e, 0x0c, 0x3c}} , {{0x2f, 0xbd, 0x84, 0x63, 0x0d, 0xb5, 0xa0, 0xf0, 0x4b, 0x9e, 0x93, 0xc6, 0x34, 0x9a, 0x34, 0xff, 0x73, 0x19, 0x2f, 0x6e, 0x54, 0x45, 0x2c, 0x92, 0x31, 0x76, 0x34, 0xf1, 0xb2, 0x26, 0xe8, 0x74}}}, {{{0x0a, 0x67, 0x90, 0x6d, 0x0c, 0x4c, 0xcc, 0xc0, 0xe6, 0xbd, 0xa7, 0x5e, 0x55, 0x8c, 0xcd, 0x58, 0x9b, 0x11, 0xa2, 0xbb, 0x4b, 0xb1, 0x43, 0x04, 0x3c, 0x55, 0xed, 0x23, 0xfe, 0xcd, 0xb1, 0x53}} , {{0x05, 0xfb, 0x75, 0xf5, 0x01, 0xaf, 0x38, 0x72, 0x58, 0xfc, 0x04, 0x29, 0x34, 0x7a, 0x67, 0xa2, 0x08, 0x50, 0x6e, 0xd0, 0x2b, 0x73, 0xd5, 0xb8, 0xe4, 0x30, 0x96, 0xad, 0x45, 0xdf, 0xa6, 0x5c}}}, {{{0x0d, 0x88, 0x1a, 0x90, 0x7e, 0xdc, 0xd8, 0xfe, 0xc1, 0x2f, 0x5d, 0x67, 0xee, 0x67, 0x2f, 0xed, 0x6f, 0x55, 0x43, 0x5f, 0x87, 0x14, 0x35, 0x42, 0xd3, 0x75, 0xae, 0xd5, 0xd3, 0x85, 0x1a, 0x76}} , {{0x87, 0xc8, 0xa0, 0x6e, 0xe1, 0xb0, 0xad, 0x6a, 0x4a, 0x34, 0x71, 0xed, 0x7c, 0xd6, 0x44, 0x03, 0x65, 0x4a, 0x5c, 0x5c, 0x04, 0xf5, 0x24, 0x3f, 0xb0, 0x16, 0x5e, 0x8c, 0xb2, 0xd2, 0xc5, 0x20}}}, {{{0x98, 0x83, 0xc2, 0x37, 0xa0, 0x41, 0xa8, 0x48, 0x5c, 0x5f, 0xbf, 0xc8, 0xfa, 0x24, 0xe0, 0x59, 0x2c, 0xbd, 0xf6, 0x81, 0x7e, 0x88, 0xe6, 0xca, 0x04, 0xd8, 0x5d, 0x60, 0xbb, 0x74, 0xa7, 0x0b}} , {{0x21, 0x13, 0x91, 0xbf, 0x77, 0x7a, 0x33, 0xbc, 0xe9, 0x07, 0x39, 0x0a, 0xdd, 0x7d, 0x06, 0x10, 0x9a, 0xee, 0x47, 0x73, 0x1b, 0x15, 0x5a, 0xfb, 0xcd, 0x4d, 0xd0, 0xd2, 0x3a, 0x01, 0xba, 0x54}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x48, 0xd5, 0x39, 0x4a, 0x0b, 0x20, 0x6a, 0x43, 0xa0, 0x07, 0x82, 0x5e, 0x49, 0x7c, 0xc9, 0x47, 0xf1, 0x7c, 0x37, 0xb9, 0x23, 0xef, 0x6b, 0x46, 0x45, 0x8c, 0x45, 0x76, 0xdf, 0x14, 0x6b, 0x6e}} , {{0x42, 0xc9, 0xca, 0x29, 0x4c, 0x76, 0x37, 0xda, 0x8a, 0x2d, 0x7c, 0x3a, 0x58, 0xf2, 0x03, 0xb4, 0xb5, 0xb9, 0x1a, 0x13, 0x2d, 0xde, 0x5f, 0x6b, 0x9d, 0xba, 0x52, 0xc9, 0x5d, 0xb3, 0xf3, 0x30}}}, {{{0x4c, 0x6f, 0xfe, 0x6b, 0x0c, 0x62, 0xd7, 0x48, 0x71, 0xef, 0xb1, 0x85, 0x79, 0xc0, 0xed, 0x24, 0xb1, 0x08, 0x93, 0x76, 0x8e, 0xf7, 0x38, 0x8e, 0xeb, 0xfe, 0x80, 0x40, 0xaf, 0x90, 0x64, 0x49}} , {{0x4a, 0x88, 0xda, 0xc1, 0x98, 0x44, 0x3c, 0x53, 0x4e, 0xdb, 0x4b, 0xb9, 0x12, 0x5f, 0xcd, 0x08, 0x04, 0xef, 0x75, 0xe7, 0xb1, 0x3a, 0xe5, 0x07, 0xfa, 0xca, 0x65, 0x7b, 0x72, 0x10, 0x64, 0x7f}}}, {{{0x3d, 0x81, 0xf0, 0xeb, 0x16, 0xfd, 0x58, 0x33, 0x8d, 0x7c, 0x1a, 0xfb, 0x20, 0x2c, 0x8a, 0xee, 0x90, 0xbb, 0x33, 0x6d, 0x45, 0xe9, 0x8e, 0x99, 0x85, 0xe1, 0x08, 0x1f, 0xc5, 0xf1, 0xb5, 0x46}} , {{0xe4, 0xe7, 0x43, 0x4b, 0xa0, 0x3f, 0x2b, 0x06, 0xba, 0x17, 0xae, 0x3d, 0xe6, 0xce, 0xbd, 0xb8, 0xed, 0x74, 0x11, 0x35, 0xec, 0x96, 0xfe, 0x31, 0xe3, 0x0e, 0x7a, 0x4e, 0xc9, 0x1d, 0xcb, 0x20}}}, {{{0xe0, 0x67, 0xe9, 0x7b, 0xdb, 0x96, 0x5c, 0xb0, 0x32, 0xd0, 0x59, 0x31, 0x90, 0xdc, 0x92, 0x97, 0xac, 0x09, 0x38, 0x31, 0x0f, 0x7e, 0xd6, 0x5d, 0xd0, 0x06, 0xb6, 0x1f, 0xea, 0xf0, 0x5b, 0x07}} , {{0x81, 0x9f, 0xc7, 0xde, 0x6b, 0x41, 0x22, 0x35, 0x14, 0x67, 0x77, 0x3e, 0x90, 0x81, 0xb0, 0xd9, 0x85, 0x4c, 0xca, 0x9b, 0x3f, 0x04, 0x59, 0xd6, 0xaa, 0x17, 0xc3, 0x88, 0x34, 0x37, 0xba, 0x43}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x4c, 0xb6, 0x69, 0xc8, 0x81, 0x95, 0x94, 0x33, 0x92, 0x34, 0xe9, 0x3c, 0x84, 0x0d, 0x3d, 0x5a, 0x37, 0x9c, 0x22, 0xa0, 0xaa, 0x65, 0xce, 0xb4, 0xc2, 0x2d, 0x66, 0x67, 0x02, 0xff, 0x74, 0x10}} , {{0x22, 0xb0, 0xd5, 0xe6, 0xc7, 0xef, 0xb1, 0xa7, 0x13, 0xda, 0x60, 0xb4, 0x80, 0xc1, 0x42, 0x7d, 0x10, 0x70, 0x97, 0x04, 0x4d, 0xda, 0x23, 0x89, 0xc2, 0x0e, 0x68, 0xcb, 0xde, 0xe0, 0x9b, 0x29}}}, {{{0x33, 0xfe, 0x42, 0x2a, 0x36, 0x2b, 0x2e, 0x36, 0x64, 0x5c, 0x8b, 0xcc, 0x81, 0x6a, 0x15, 0x08, 0xa1, 0x27, 0xe8, 0x57, 0xe5, 0x78, 0x8e, 0xf2, 0x58, 0x19, 0x12, 0x42, 0xae, 0xc4, 0x63, 0x3e}} , {{0x78, 0x96, 0x9c, 0xa7, 0xca, 0x80, 0xae, 0x02, 0x85, 0xb1, 0x7c, 0x04, 0x5c, 0xc1, 0x5b, 0x26, 0xc1, 0xba, 0xed, 0xa5, 0x59, 0x70, 0x85, 0x8c, 0x8c, 0xe8, 0x87, 0xac, 0x6a, 0x28, 0x99, 0x35}}}, {{{0x9f, 0x04, 0x08, 0x28, 0xbe, 0x87, 0xda, 0x80, 0x28, 0x38, 0xde, 0x9f, 0xcd, 0xe4, 0xe3, 0x62, 0xfb, 0x2e, 0x46, 0x8d, 0x01, 0xb3, 0x06, 0x51, 0xd4, 0x19, 0x3b, 0x11, 0xfa, 0xe2, 0xad, 0x1e}} , {{0xa0, 0x20, 0x99, 0x69, 0x0a, 0xae, 0xa3, 0x70, 0x4e, 0x64, 0x80, 0xb7, 0x85, 0x9c, 0x87, 0x54, 0x43, 0x43, 0x55, 0x80, 0x6d, 0x8d, 0x7c, 0xa9, 0x64, 0xca, 0x6c, 0x2e, 0x21, 0xd8, 0xc8, 0x6c}}}, {{{0x91, 0x4a, 0x07, 0xad, 0x08, 0x75, 0xc1, 0x4f, 0xa4, 0xb2, 0xc3, 0x6f, 0x46, 0x3e, 0xb1, 0xce, 0x52, 0xab, 0x67, 0x09, 0x54, 0x48, 0x6b, 0x6c, 0xd7, 0x1d, 0x71, 0x76, 0xcb, 0xff, 0xdd, 0x31}} , {{0x36, 0x88, 0xfa, 0xfd, 0xf0, 0x36, 0x6f, 0x07, 0x74, 0x88, 0x50, 0xd0, 0x95, 0x38, 0x4a, 0x48, 0x2e, 0x07, 0x64, 0x97, 0x11, 0x76, 0x01, 0x1a, 0x27, 0x4d, 0x8e, 0x25, 0x9a, 0x9b, 0x1c, 0x22}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xbe, 0x57, 0xbd, 0x0e, 0x0f, 0xac, 0x5e, 0x76, 0xa3, 0x71, 0xad, 0x2b, 0x10, 0x45, 0x02, 0xec, 0x59, 0xd5, 0x5d, 0xa9, 0x44, 0xcc, 0x25, 0x4c, 0xb3, 0x3c, 0x5b, 0x69, 0x07, 0x55, 0x26, 0x6b}} , {{0x30, 0x6b, 0xd4, 0xa7, 0x51, 0x29, 0xe3, 0xf9, 0x7a, 0x75, 0x2a, 0x82, 0x2f, 0xd6, 0x1d, 0x99, 0x2b, 0x80, 0xd5, 0x67, 0x1e, 0x15, 0x9d, 0xca, 0xfd, 0xeb, 0xac, 0x97, 0x35, 0x09, 0x7f, 0x3f}}}, {{{0x35, 0x0d, 0x34, 0x0a, 0xb8, 0x67, 0x56, 0x29, 0x20, 0xf3, 0x19, 0x5f, 0xe2, 0x83, 0x42, 0x73, 0x53, 0xa8, 0xc5, 0x02, 0x19, 0x33, 0xb4, 0x64, 0xbd, 0xc3, 0x87, 0x8c, 0xd7, 0x76, 0xed, 0x25}} , {{0x47, 0x39, 0x37, 0x76, 0x0d, 0x1d, 0x0c, 0xf5, 0x5a, 0x6d, 0x43, 0x88, 0x99, 0x15, 0xb4, 0x52, 0x0f, 0x2a, 0xb3, 0xb0, 0x3f, 0xa6, 0xb3, 0x26, 0xb3, 0xc7, 0x45, 0xf5, 0x92, 0x5f, 0x9b, 0x17}}}, {{{0x9d, 0x23, 0xbd, 0x15, 0xfe, 0x52, 0x52, 0x15, 0x26, 0x79, 0x86, 0xba, 0x06, 0x56, 0x66, 0xbb, 0x8c, 0x2e, 0x10, 0x11, 0xd5, 0x4a, 0x18, 0x52, 0xda, 0x84, 0x44, 0xf0, 0x3e, 0xe9, 0x8c, 0x35}} , {{0xad, 0xa0, 0x41, 0xec, 0xc8, 0x4d, 0xb9, 0xd2, 0x6e, 0x96, 0x4e, 0x5b, 0xc5, 0xc2, 0xa0, 0x1b, 0xcf, 0x0c, 0xbf, 0x17, 0x66, 0x57, 0xc1, 0x17, 0x90, 0x45, 0x71, 0xc2, 0xe1, 0x24, 0xeb, 0x27}}}, {{{0x2c, 0xb9, 0x42, 0xa4, 0xaf, 0x3b, 0x42, 0x0e, 0xc2, 0x0f, 0xf2, 0xea, 0x83, 0xaf, 0x9a, 0x13, 0x17, 0xb0, 0xbd, 0x89, 0x17, 0xe3, 0x72, 0xcb, 0x0e, 0x76, 0x7e, 0x41, 0x63, 0x04, 0x88, 0x71}} , {{0x75, 0x78, 0x38, 0x86, 0x57, 0xdd, 0x9f, 0xee, 0x54, 0x70, 0x65, 0xbf, 0xf1, 0x2c, 0xe0, 0x39, 0x0d, 0xe3, 0x89, 0xfd, 0x8e, 0x93, 0x4f, 0x43, 0xdc, 0xd5, 0x5b, 0xde, 0xf9, 0x98, 0xe5, 0x7b}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe7, 0x3b, 0x65, 0x11, 0xdf, 0xb2, 0xf2, 0x63, 0x94, 0x12, 0x6f, 0x5c, 0x9e, 0x77, 0xc1, 0xb6, 0xd8, 0xab, 0x58, 0x7a, 0x1d, 0x95, 0x73, 0xdd, 0xe7, 0xe3, 0x6f, 0xf2, 0x03, 0x1d, 0xdb, 0x76}} , {{0xae, 0x06, 0x4e, 0x2c, 0x52, 0x1b, 0xbc, 0x5a, 0x5a, 0xa5, 0xbe, 0x27, 0xbd, 0xeb, 0xe1, 0x14, 0x17, 0x68, 0x26, 0x07, 0x03, 0xd1, 0x18, 0x0b, 0xdf, 0xf1, 0x06, 0x5c, 0xa6, 0x1b, 0xb9, 0x24}}}, {{{0xc5, 0x66, 0x80, 0x13, 0x0e, 0x48, 0x8c, 0x87, 0x31, 0x84, 0xb4, 0x60, 0xed, 0xc5, 0xec, 0xb6, 0xc5, 0x05, 0x33, 0x5f, 0x2f, 0x7d, 0x40, 0xb6, 0x32, 0x1d, 0x38, 0x74, 0x1b, 0xf1, 0x09, 0x3d}} , {{0xd4, 0x69, 0x82, 0xbc, 0x8d, 0xf8, 0x34, 0x36, 0x75, 0x55, 0x18, 0x55, 0x58, 0x3c, 0x79, 0xaf, 0x26, 0x80, 0xab, 0x9b, 0x95, 0x00, 0xf1, 0xcb, 0xda, 0xc1, 0x9f, 0xf6, 0x2f, 0xa2, 0xf4, 0x45}}}, {{{0x17, 0xbe, 0xeb, 0x85, 0xed, 0x9e, 0xcd, 0x56, 0xf5, 0x17, 0x45, 0x42, 0xb4, 0x1f, 0x44, 0x4c, 0x05, 0x74, 0x15, 0x47, 0x00, 0xc6, 0x6a, 0x3d, 0x24, 0x09, 0x0d, 0x58, 0xb1, 0x42, 0xd7, 0x04}} , {{0x8d, 0xbd, 0xa3, 0xc4, 0x06, 0x9b, 0x1f, 0x90, 0x58, 0x60, 0x74, 0xb2, 0x00, 0x3b, 0x3c, 0xd2, 0xda, 0x82, 0xbb, 0x10, 0x90, 0x69, 0x92, 0xa9, 0xb4, 0x30, 0x81, 0xe3, 0x7c, 0xa8, 0x89, 0x45}}}, {{{0x3f, 0xdc, 0x05, 0xcb, 0x41, 0x3c, 0xc8, 0x23, 0x04, 0x2c, 0x38, 0x99, 0xe3, 0x68, 0x55, 0xf9, 0xd3, 0x32, 0xc7, 0xbf, 0xfa, 0xd4, 0x1b, 0x5d, 0xde, 0xdc, 0x10, 0x42, 0xc0, 0x42, 0xd9, 0x75}} , {{0x2d, 0xab, 0x35, 0x4e, 0x87, 0xc4, 0x65, 0x97, 0x67, 0x24, 0xa4, 0x47, 0xad, 0x3f, 0x8e, 0xf3, 0xcb, 0x31, 0x17, 0x77, 0xc5, 0xe2, 0xd7, 0x8f, 0x3c, 0xc1, 0xcd, 0x56, 0x48, 0xc1, 0x6c, 0x69}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x14, 0xae, 0x5f, 0x88, 0x7b, 0xa5, 0x90, 0xdf, 0x10, 0xb2, 0x8b, 0x5e, 0x24, 0x17, 0xc3, 0xa3, 0xd4, 0x0f, 0x92, 0x61, 0x1a, 0x19, 0x5a, 0xad, 0x76, 0xbd, 0xd8, 0x1c, 0xdd, 0xe0, 0x12, 0x6d}} , {{0x8e, 0xbd, 0x70, 0x8f, 0x02, 0xa3, 0x24, 0x4d, 0x5a, 0x67, 0xc4, 0xda, 0xf7, 0x20, 0x0f, 0x81, 0x5b, 0x7a, 0x05, 0x24, 0x67, 0x83, 0x0b, 0x2a, 0x80, 0xe7, 0xfd, 0x74, 0x4b, 0x9e, 0x5c, 0x0d}}}, {{{0x94, 0xd5, 0x5f, 0x1f, 0xa2, 0xfb, 0xeb, 0xe1, 0x07, 0x34, 0xf8, 0x20, 0xad, 0x81, 0x30, 0x06, 0x2d, 0xa1, 0x81, 0x95, 0x36, 0xcf, 0x11, 0x0b, 0xaf, 0xc1, 0x2b, 0x9a, 0x6c, 0x55, 0xc1, 0x16}} , {{0x36, 0x4f, 0xf1, 0x5e, 0x74, 0x35, 0x13, 0x28, 0xd7, 0x11, 0xcf, 0xb8, 0xde, 0x93, 0xb3, 0x05, 0xb8, 0xb5, 0x73, 0xe9, 0xeb, 0xad, 0x19, 0x1e, 0x89, 0x0f, 0x8b, 0x15, 0xd5, 0x8c, 0xe3, 0x23}}}, {{{0x33, 0x79, 0xe7, 0x18, 0xe6, 0x0f, 0x57, 0x93, 0x15, 0xa0, 0xa7, 0xaa, 0xc4, 0xbf, 0x4f, 0x30, 0x74, 0x95, 0x5e, 0x69, 0x4a, 0x5b, 0x45, 0xe4, 0x00, 0xeb, 0x23, 0x74, 0x4c, 0xdf, 0x6b, 0x45}} , {{0x97, 0x29, 0x6c, 0xc4, 0x42, 0x0b, 0xdd, 0xc0, 0x29, 0x5c, 0x9b, 0x34, 0x97, 0xd0, 0xc7, 0x79, 0x80, 0x63, 0x74, 0xe4, 0x8e, 0x37, 0xb0, 0x2b, 0x7c, 0xe8, 0x68, 0x6c, 0xc3, 0x82, 0x97, 0x57}}}, {{{0x22, 0xbe, 0x83, 0xb6, 0x4b, 0x80, 0x6b, 0x43, 0x24, 0x5e, 0xef, 0x99, 0x9b, 0xa8, 0xfc, 0x25, 0x8d, 0x3b, 0x03, 0x94, 0x2b, 0x3e, 0xe7, 0x95, 0x76, 0x9b, 0xcc, 0x15, 0xdb, 0x32, 0xe6, 0x66}} , {{0x84, 0xf0, 0x4a, 0x13, 0xa6, 0xd6, 0xfa, 0x93, 0x46, 0x07, 0xf6, 0x7e, 0x5c, 0x6d, 0x5e, 0xf6, 0xa6, 0xe7, 0x48, 0xf0, 0x06, 0xea, 0xff, 0x90, 0xc1, 0xcc, 0x4c, 0x19, 0x9c, 0x3c, 0x4e, 0x53}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2a, 0x50, 0xe3, 0x07, 0x15, 0x59, 0xf2, 0x8b, 0x81, 0xf2, 0xf3, 0xd3, 0x6c, 0x99, 0x8c, 0x70, 0x67, 0xec, 0xcc, 0xee, 0x9e, 0x59, 0x45, 0x59, 0x7d, 0x47, 0x75, 0x69, 0xf5, 0x24, 0x93, 0x5d}} , {{0x6a, 0x4f, 0x1b, 0xbe, 0x6b, 0x30, 0xcf, 0x75, 0x46, 0xe3, 0x7b, 0x9d, 0xfc, 0xcd, 0xd8, 0x5c, 0x1f, 0xb4, 0xc8, 0xe2, 0x24, 0xec, 0x1a, 0x28, 0x05, 0x32, 0x57, 0xfd, 0x3c, 0x5a, 0x98, 0x10}}}, {{{0xa3, 0xdb, 0xf7, 0x30, 0xd8, 0xc2, 0x9a, 0xe1, 0xd3, 0xce, 0x22, 0xe5, 0x80, 0x1e, 0xd9, 0xe4, 0x1f, 0xab, 0xc0, 0x71, 0x1a, 0x86, 0x0e, 0x27, 0x99, 0x5b, 0xfa, 0x76, 0x99, 0xb0, 0x08, 0x3c}} , {{0x2a, 0x93, 0xd2, 0x85, 0x1b, 0x6a, 0x5d, 0xa6, 0xee, 0xd1, 0xd1, 0x33, 0xbd, 0x6a, 0x36, 0x73, 0x37, 0x3a, 0x44, 0xb4, 0xec, 0xa9, 0x7a, 0xde, 0x83, 0x40, 0xd7, 0xdf, 0x28, 0xba, 0xa2, 0x30}}}, {{{0xd3, 0xb5, 0x6d, 0x05, 0x3f, 0x9f, 0xf3, 0x15, 0x8d, 0x7c, 0xca, 0xc9, 0xfc, 0x8a, 0x7c, 0x94, 0xb0, 0x63, 0x36, 0x9b, 0x78, 0xd1, 0x91, 0x1f, 0x93, 0xd8, 0x57, 0x43, 0xde, 0x76, 0xa3, 0x43}} , {{0x9b, 0x35, 0xe2, 0xa9, 0x3d, 0x32, 0x1e, 0xbb, 0x16, 0x28, 0x70, 0xe9, 0x45, 0x2f, 0x8f, 0x70, 0x7f, 0x08, 0x7e, 0x53, 0xc4, 0x7a, 0xbf, 0xf7, 0xe1, 0xa4, 0x6a, 0xd8, 0xac, 0x64, 0x1b, 0x11}}}, {{{0xb2, 0xeb, 0x47, 0x46, 0x18, 0x3e, 0x1f, 0x99, 0x0c, 0xcc, 0xf1, 0x2c, 0xe0, 0xe7, 0x8f, 0xe0, 0x01, 0x7e, 0x65, 0xb8, 0x0c, 0xd0, 0xfb, 0xc8, 0xb9, 0x90, 0x98, 0x33, 0x61, 0x3b, 0xd8, 0x27}} , {{0xa0, 0xbe, 0x72, 0x3a, 0x50, 0x4b, 0x74, 0xab, 0x01, 0xc8, 0x93, 0xc5, 0xe4, 0xc7, 0x08, 0x6c, 0xb4, 0xca, 0xee, 0xeb, 0x8e, 0xd7, 0x4e, 0x26, 0xc6, 0x1d, 0xe2, 0x71, 0xaf, 0x89, 0xa0, 0x2a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x98, 0x0b, 0xe4, 0xde, 0xdb, 0xa8, 0xfa, 0x82, 0x74, 0x06, 0x52, 0x6d, 0x08, 0x52, 0x8a, 0xff, 0x62, 0xc5, 0x6a, 0x44, 0x0f, 0x51, 0x8c, 0x1f, 0x6e, 0xb6, 0xc6, 0x2c, 0x81, 0xd3, 0x76, 0x46}} , {{0xf4, 0x29, 0x74, 0x2e, 0x80, 0xa7, 0x1a, 0x8f, 0xf6, 0xbd, 0xd6, 0x8e, 0xbf, 0xc1, 0x95, 0x2a, 0xeb, 0xa0, 0x7f, 0x45, 0xa0, 0x50, 0x14, 0x05, 0xb1, 0x57, 0x4c, 0x74, 0xb7, 0xe2, 0x89, 0x7d}}}, {{{0x07, 0xee, 0xa7, 0xad, 0xb7, 0x09, 0x0b, 0x49, 0x4e, 0xbf, 0xca, 0xe5, 0x21, 0xe6, 0xe6, 0xaf, 0xd5, 0x67, 0xf3, 0xce, 0x7e, 0x7c, 0x93, 0x7b, 0x5a, 0x10, 0x12, 0x0e, 0x6c, 0x06, 0x11, 0x75}} , {{0xd5, 0xfc, 0x86, 0xa3, 0x3b, 0xa3, 0x3e, 0x0a, 0xfb, 0x0b, 0xf7, 0x36, 0xb1, 0x5b, 0xda, 0x70, 0xb7, 0x00, 0xa7, 0xda, 0x88, 0x8f, 0x84, 0xa8, 0xbc, 0x1c, 0x39, 0xb8, 0x65, 0xf3, 0x4d, 0x60}}}, {{{0x96, 0x9d, 0x31, 0xf4, 0xa2, 0xbe, 0x81, 0xb9, 0xa5, 0x59, 0x9e, 0xba, 0x07, 0xbe, 0x74, 0x58, 0xd8, 0xeb, 0xc5, 0x9f, 0x3d, 0xd1, 0xf4, 0xae, 0xce, 0x53, 0xdf, 0x4f, 0xc7, 0x2a, 0x89, 0x4d}} , {{0x29, 0xd8, 0xf2, 0xaa, 0xe9, 0x0e, 0xf7, 0x2e, 0x5f, 0x9d, 0x8a, 0x5b, 0x09, 0xed, 0xc9, 0x24, 0x22, 0xf4, 0x0f, 0x25, 0x8f, 0x1c, 0x84, 0x6e, 0x34, 0x14, 0x6c, 0xea, 0xb3, 0x86, 0x5d, 0x04}}}, {{{0x07, 0x98, 0x61, 0xe8, 0x6a, 0xd2, 0x81, 0x49, 0x25, 0xd5, 0x5b, 0x18, 0xc7, 0x35, 0x52, 0x51, 0xa4, 0x46, 0xad, 0x18, 0x0d, 0xc9, 0x5f, 0x18, 0x91, 0x3b, 0xb4, 0xc0, 0x60, 0x59, 0x8d, 0x66}} , {{0x03, 0x1b, 0x79, 0x53, 0x6e, 0x24, 0xae, 0x57, 0xd9, 0x58, 0x09, 0x85, 0x48, 0xa2, 0xd3, 0xb5, 0xe2, 0x4d, 0x11, 0x82, 0xe6, 0x86, 0x3c, 0xe9, 0xb1, 0x00, 0x19, 0xc2, 0x57, 0xf7, 0x66, 0x7a}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x0f, 0xe3, 0x89, 0x03, 0xd7, 0x22, 0x95, 0x9f, 0xca, 0xb4, 0x8d, 0x9e, 0x6d, 0x97, 0xff, 0x8d, 0x21, 0x59, 0x07, 0xef, 0x03, 0x2d, 0x5e, 0xf8, 0x44, 0x46, 0xe7, 0x85, 0x80, 0xc5, 0x89, 0x50}} , {{0x8b, 0xd8, 0x53, 0x86, 0x24, 0x86, 0x29, 0x52, 0x01, 0xfa, 0x20, 0xc3, 0x4e, 0x95, 0xcb, 0xad, 0x7b, 0x34, 0x94, 0x30, 0xb7, 0x7a, 0xfa, 0x96, 0x41, 0x60, 0x2b, 0xcb, 0x59, 0xb9, 0xca, 0x50}}}, {{{0xc2, 0x5b, 0x9b, 0x78, 0x23, 0x1b, 0x3a, 0x88, 0x94, 0x5f, 0x0a, 0x9b, 0x98, 0x2b, 0x6e, 0x53, 0x11, 0xf6, 0xff, 0xc6, 0x7d, 0x42, 0xcc, 0x02, 0x80, 0x40, 0x0d, 0x1e, 0xfb, 0xaf, 0x61, 0x07}} , {{0xb0, 0xe6, 0x2f, 0x81, 0x70, 0xa1, 0x2e, 0x39, 0x04, 0x7c, 0xc4, 0x2c, 0x87, 0x45, 0x4a, 0x5b, 0x69, 0x97, 0xac, 0x6d, 0x2c, 0x10, 0x42, 0x7c, 0x3b, 0x15, 0x70, 0x60, 0x0e, 0x11, 0x6d, 0x3a}}}, {{{0x9b, 0x18, 0x80, 0x5e, 0xdb, 0x05, 0xbd, 0xc6, 0xb7, 0x3c, 0xc2, 0x40, 0x4d, 0x5d, 0xce, 0x97, 0x8a, 0x34, 0x15, 0xab, 0x28, 0x5d, 0x10, 0xf0, 0x37, 0x0c, 0xcc, 0x16, 0xfa, 0x1f, 0x33, 0x0d}} , {{0x19, 0xf9, 0x35, 0xaa, 0x59, 0x1a, 0x0c, 0x5c, 0x06, 0xfc, 0x6a, 0x0b, 0x97, 0x53, 0x36, 0xfc, 0x2a, 0xa5, 0x5a, 0x9b, 0x30, 0xef, 0x23, 0xaf, 0x39, 0x5d, 0x9a, 0x6b, 0x75, 0x57, 0x48, 0x0b}}}, {{{0x26, 0xdc, 0x76, 0x3b, 0xfc, 0xf9, 0x9c, 0x3f, 0x89, 0x0b, 0x62, 0x53, 0xaf, 0x83, 0x01, 0x2e, 0xbc, 0x6a, 0xc6, 0x03, 0x0d, 0x75, 0x2a, 0x0d, 0xe6, 0x94, 0x54, 0xcf, 0xb3, 0xe5, 0x96, 0x25}} , {{0xfe, 0x82, 0xb1, 0x74, 0x31, 0x8a, 0xa7, 0x6f, 0x56, 0xbd, 0x8d, 0xf4, 0xe0, 0x94, 0x51, 0x59, 0xde, 0x2c, 0x5a, 0xf4, 0x84, 0x6b, 0x4a, 0x88, 0x93, 0xc0, 0x0c, 0x9a, 0xac, 0xa7, 0xa0, 0x68}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x25, 0x0d, 0xd6, 0xc7, 0x23, 0x47, 0x10, 0xad, 0xc7, 0x08, 0x5c, 0x87, 0x87, 0x93, 0x98, 0x18, 0xb8, 0xd3, 0x9c, 0xac, 0x5a, 0x3d, 0xc5, 0x75, 0xf8, 0x49, 0x32, 0x14, 0xcc, 0x51, 0x96, 0x24}} , {{0x65, 0x9c, 0x5d, 0xf0, 0x37, 0x04, 0xf0, 0x34, 0x69, 0x2a, 0xf0, 0xa5, 0x64, 0xca, 0xde, 0x2b, 0x5b, 0x15, 0x10, 0xd2, 0xab, 0x06, 0xdd, 0xc4, 0xb0, 0xb6, 0x5b, 0xc1, 0x17, 0xdf, 0x8f, 0x02}}}, {{{0xbd, 0x59, 0x3d, 0xbf, 0x5c, 0x31, 0x44, 0x2c, 0x32, 0x94, 0x04, 0x60, 0x84, 0x0f, 0xad, 0x00, 0xb6, 0x8f, 0xc9, 0x1d, 0xcc, 0x5c, 0xa2, 0x49, 0x0e, 0x50, 0x91, 0x08, 0x9a, 0x43, 0x55, 0x05}} , {{0x5d, 0x93, 0x55, 0xdf, 0x9b, 0x12, 0x19, 0xec, 0x93, 0x85, 0x42, 0x9e, 0x66, 0x0f, 0x9d, 0xaf, 0x99, 0xaf, 0x26, 0x89, 0xbc, 0x61, 0xfd, 0xff, 0xce, 0x4b, 0xf4, 0x33, 0x95, 0xc9, 0x35, 0x58}}}, {{{0x12, 0x55, 0xf9, 0xda, 0xcb, 0x44, 0xa7, 0xdc, 0x57, 0xe2, 0xf9, 0x9a, 0xe6, 0x07, 0x23, 0x60, 0x54, 0xa7, 0x39, 0xa5, 0x9b, 0x84, 0x56, 0x6e, 0xaa, 0x8b, 0x8f, 0xb0, 0x2c, 0x87, 0xaf, 0x67}} , {{0x00, 0xa9, 0x4c, 0xb2, 0x12, 0xf8, 0x32, 0xa8, 0x7a, 0x00, 0x4b, 0x49, 0x32, 0xba, 0x1f, 0x5d, 0x44, 0x8e, 0x44, 0x7a, 0xdc, 0x11, 0xfb, 0x39, 0x08, 0x57, 0x87, 0xa5, 0x12, 0x42, 0x93, 0x0e}}}, {{{0x17, 0xb4, 0xae, 0x72, 0x59, 0xd0, 0xaa, 0xa8, 0x16, 0x8b, 0x63, 0x11, 0xb3, 0x43, 0x04, 0xda, 0x0c, 0xa8, 0xb7, 0x68, 0xdd, 0x4e, 0x54, 0xe7, 0xaf, 0x5d, 0x5d, 0x05, 0x76, 0x36, 0xec, 0x0d}} , {{0x6d, 0x7c, 0x82, 0x32, 0x38, 0x55, 0x57, 0x74, 0x5b, 0x7d, 0xc3, 0xc4, 0xfb, 0x06, 0x29, 0xf0, 0x13, 0x55, 0x54, 0xc6, 0xa7, 0xdc, 0x4c, 0x9f, 0x98, 0x49, 0x20, 0xa8, 0xc3, 0x8d, 0xfa, 0x48}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x87, 0x47, 0x9d, 0xe9, 0x25, 0xd5, 0xe3, 0x47, 0x78, 0xdf, 0x85, 0xa7, 0x85, 0x5e, 0x7a, 0x4c, 0x5f, 0x79, 0x1a, 0xf3, 0xa2, 0xb2, 0x28, 0xa0, 0x9c, 0xdd, 0x30, 0x40, 0xd4, 0x38, 0xbd, 0x28}} , {{0xfc, 0xbb, 0xd5, 0x78, 0x6d, 0x1d, 0xd4, 0x99, 0xb4, 0xaa, 0x44, 0x44, 0x7a, 0x1b, 0xd8, 0xfe, 0xb4, 0x99, 0xb9, 0xcc, 0xe7, 0xc4, 0xd3, 0x3a, 0x73, 0x83, 0x41, 0x5c, 0x40, 0xd7, 0x2d, 0x55}}}, {{{0x26, 0xe1, 0x7b, 0x5f, 0xe5, 0xdc, 0x3f, 0x7d, 0xa1, 0xa7, 0x26, 0x44, 0x22, 0x23, 0xc0, 0x8f, 0x7d, 0xf1, 0xb5, 0x11, 0x47, 0x7b, 0x19, 0xd4, 0x75, 0x6f, 0x1e, 0xa5, 0x27, 0xfe, 0xc8, 0x0e}} , {{0xd3, 0x11, 0x3d, 0xab, 0xef, 0x2c, 0xed, 0xb1, 0x3d, 0x7c, 0x32, 0x81, 0x6b, 0xfe, 0xf8, 0x1c, 0x3c, 0x7b, 0xc0, 0x61, 0xdf, 0xb8, 0x75, 0x76, 0x7f, 0xaa, 0xd8, 0x93, 0xaf, 0x3d, 0xe8, 0x3d}}}, {{{0xfd, 0x5b, 0x4e, 0x8d, 0xb6, 0x7e, 0x82, 0x9b, 0xef, 0xce, 0x04, 0x69, 0x51, 0x52, 0xff, 0xef, 0xa0, 0x52, 0xb5, 0x79, 0x17, 0x5e, 0x2f, 0xde, 0xd6, 0x3c, 0x2d, 0xa0, 0x43, 0xb4, 0x0b, 0x19}} , {{0xc0, 0x61, 0x48, 0x48, 0x17, 0xf4, 0x9e, 0x18, 0x51, 0x2d, 0xea, 0x2f, 0xf2, 0xf2, 0xe0, 0xa3, 0x14, 0xb7, 0x8b, 0x3a, 0x30, 0xf5, 0x81, 0xc1, 0x5d, 0x71, 0x39, 0x62, 0x55, 0x1f, 0x60, 0x5a}}}, {{{0xe5, 0x89, 0x8a, 0x76, 0x6c, 0xdb, 0x4d, 0x0a, 0x5b, 0x72, 0x9d, 0x59, 0x6e, 0x63, 0x63, 0x18, 0x7c, 0xe3, 0xfa, 0xe2, 0xdb, 0xa1, 0x8d, 0xf4, 0xa5, 0xd7, 0x16, 0xb2, 0xd0, 0xb3, 0x3f, 0x39}} , {{0xce, 0x60, 0x09, 0x6c, 0xf5, 0x76, 0x17, 0x24, 0x80, 0x3a, 0x96, 0xc7, 0x94, 0x2e, 0xf7, 0x6b, 0xef, 0xb5, 0x05, 0x96, 0xef, 0xd3, 0x7b, 0x51, 0xda, 0x05, 0x44, 0x67, 0xbc, 0x07, 0x21, 0x4e}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xe9, 0x73, 0x6f, 0x21, 0xb9, 0xde, 0x22, 0x7d, 0xeb, 0x97, 0x31, 0x10, 0xa3, 0xea, 0xe1, 0xc6, 0x37, 0xeb, 0x8f, 0x43, 0x58, 0xde, 0x41, 0x64, 0x0e, 0x3e, 0x07, 0x99, 0x3d, 0xf1, 0xdf, 0x1e}} , {{0xf8, 0xad, 0x43, 0xc2, 0x17, 0x06, 0xe2, 0xe4, 0xa9, 0x86, 0xcd, 0x18, 0xd7, 0x78, 0xc8, 0x74, 0x66, 0xd2, 0x09, 0x18, 0xa5, 0xf1, 0xca, 0xa6, 0x62, 0x92, 0xc1, 0xcb, 0x00, 0xeb, 0x42, 0x2e}}}, {{{0x7b, 0x34, 0x24, 0x4c, 0xcf, 0x38, 0xe5, 0x6c, 0x0a, 0x01, 0x2c, 0x22, 0x0b, 0x24, 0x38, 0xad, 0x24, 0x7e, 0x19, 0xf0, 0x6c, 0xf9, 0x31, 0xf4, 0x35, 0x11, 0xf6, 0x46, 0x33, 0x3a, 0x23, 0x59}} , {{0x20, 0x0b, 0xa1, 0x08, 0x19, 0xad, 0x39, 0x54, 0xea, 0x3e, 0x23, 0x09, 0xb6, 0xe2, 0xd2, 0xbc, 0x4d, 0xfc, 0x9c, 0xf0, 0x13, 0x16, 0x22, 0x3f, 0xb9, 0xd2, 0x11, 0x86, 0x90, 0x55, 0xce, 0x3c}}}, {{{0xc4, 0x0b, 0x4b, 0x62, 0x99, 0x37, 0x84, 0x3f, 0x74, 0xa2, 0xf9, 0xce, 0xe2, 0x0b, 0x0f, 0x2a, 0x3d, 0xa3, 0xe3, 0xdb, 0x5a, 0x9d, 0x93, 0xcc, 0xa5, 0xef, 0x82, 0x91, 0x1d, 0xe6, 0x6c, 0x68}} , {{0xa3, 0x64, 0x17, 0x9b, 0x8b, 0xc8, 0x3a, 0x61, 0xe6, 0x9d, 0xc6, 0xed, 0x7b, 0x03, 0x52, 0x26, 0x9d, 0x3a, 0xb3, 0x13, 0xcc, 0x8a, 0xfd, 0x2c, 0x1a, 0x1d, 0xed, 0x13, 0xd0, 0x55, 0x57, 0x0e}}}, {{{0x1a, 0xea, 0xbf, 0xfd, 0x4a, 0x3c, 0x8e, 0xec, 0x29, 0x7e, 0x77, 0x77, 0x12, 0x99, 0xd7, 0x84, 0xf9, 0x55, 0x7f, 0xf1, 0x8b, 0xb4, 0xd2, 0x95, 0xa3, 0x8d, 0xf0, 0x8a, 0xa7, 0xeb, 0x82, 0x4b}} , {{0x2c, 0x28, 0xf4, 0x3a, 0xf6, 0xde, 0x0a, 0xe0, 0x41, 0x44, 0x23, 0xf8, 0x3f, 0x03, 0x64, 0x9f, 0xc3, 0x55, 0x4c, 0xc6, 0xc1, 0x94, 0x1c, 0x24, 0x5d, 0x5f, 0x92, 0x45, 0x96, 0x57, 0x37, 0x14}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xc1, 0xcd, 0x90, 0x66, 0xb9, 0x76, 0xa0, 0x5b, 0xa5, 0x85, 0x75, 0x23, 0xf9, 0x89, 0xa5, 0x82, 0xb2, 0x6f, 0xb1, 0xeb, 0xc4, 0x69, 0x6f, 0x18, 0x5a, 0xed, 0x94, 0x3d, 0x9d, 0xd9, 0x2c, 0x1a}} , {{0x35, 0xb0, 0xe6, 0x73, 0x06, 0xb7, 0x37, 0xe0, 0xf8, 0xb0, 0x22, 0xe8, 0xd2, 0xed, 0x0b, 0xef, 0xe6, 0xc6, 0x5a, 0x99, 0x9e, 0x1a, 0x9f, 0x04, 0x97, 0xe4, 0x4d, 0x0b, 0xbe, 0xba, 0x44, 0x40}}}, {{{0xc1, 0x56, 0x96, 0x91, 0x5f, 0x1f, 0xbb, 0x54, 0x6f, 0x88, 0x89, 0x0a, 0xb2, 0xd6, 0x41, 0x42, 0x6a, 0x82, 0xee, 0x14, 0xaa, 0x76, 0x30, 0x65, 0x0f, 0x67, 0x39, 0xa6, 0x51, 0x7c, 0x49, 0x24}} , {{0x35, 0xa3, 0x78, 0xd1, 0x11, 0x0f, 0x75, 0xd3, 0x70, 0x46, 0xdb, 0x20, 0x51, 0xcb, 0x92, 0x80, 0x54, 0x10, 0x74, 0x36, 0x86, 0xa9, 0xd7, 0xa3, 0x08, 0x78, 0xf1, 0x01, 0x29, 0xf8, 0x80, 0x3b}}}, {{{0xdb, 0xa7, 0x9d, 0x9d, 0xbf, 0xa0, 0xcc, 0xed, 0x53, 0xa2, 0xa2, 0x19, 0x39, 0x48, 0x83, 0x19, 0x37, 0x58, 0xd1, 0x04, 0x28, 0x40, 0xf7, 0x8a, 0xc2, 0x08, 0xb7, 0xa5, 0x42, 0xcf, 0x53, 0x4c}} , {{0xa7, 0xbb, 0xf6, 0x8e, 0xad, 0xdd, 0xf7, 0x90, 0xdd, 0x5f, 0x93, 0x89, 0xae, 0x04, 0x37, 0xe6, 0x9a, 0xb7, 0xe8, 0xc0, 0xdf, 0x16, 0x2a, 0xbf, 0xc4, 0x3a, 0x3c, 0x41, 0xd5, 0x89, 0x72, 0x5a}}}, {{{0x1f, 0x96, 0xff, 0x34, 0x2c, 0x13, 0x21, 0xcb, 0x0a, 0x89, 0x85, 0xbe, 0xb3, 0x70, 0x9e, 0x1e, 0xde, 0x97, 0xaf, 0x96, 0x30, 0xf7, 0x48, 0x89, 0x40, 0x8d, 0x07, 0xf1, 0x25, 0xf0, 0x30, 0x58}} , {{0x1e, 0xd4, 0x93, 0x57, 0xe2, 0x17, 0xe7, 0x9d, 0xab, 0x3c, 0x55, 0x03, 0x82, 0x2f, 0x2b, 0xdb, 0x56, 0x1e, 0x30, 0x2e, 0x24, 0x47, 0x6e, 0xe6, 0xff, 0x33, 0x24, 0x2c, 0x75, 0x51, 0xd4, 0x67}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0x2b, 0x06, 0xd9, 0xa1, 0x5d, 0xe1, 0xf4, 0xd1, 0x1e, 0x3c, 0x9a, 0xc6, 0x29, 0x2b, 0x13, 0x13, 0x78, 0xc0, 0xd8, 0x16, 0x17, 0x2d, 0x9e, 0xa9, 0xc9, 0x79, 0x57, 0xab, 0x24, 0x91, 0x92, 0x19}} , {{0x69, 0xfb, 0xa1, 0x9c, 0xa6, 0x75, 0x49, 0x7d, 0x60, 0x73, 0x40, 0x42, 0xc4, 0x13, 0x0a, 0x95, 0x79, 0x1e, 0x04, 0x83, 0x94, 0x99, 0x9b, 0x1e, 0x0c, 0xe8, 0x1f, 0x54, 0xef, 0xcb, 0xc0, 0x52}}}, {{{0x14, 0x89, 0x73, 0xa1, 0x37, 0x87, 0x6a, 0x7a, 0xcf, 0x1d, 0xd9, 0x2e, 0x1a, 0x67, 0xed, 0x74, 0xc0, 0xf0, 0x9c, 0x33, 0xdd, 0xdf, 0x08, 0xbf, 0x7b, 0xd1, 0x66, 0xda, 0xe6, 0xc9, 0x49, 0x08}} , {{0xe9, 0xdd, 0x5e, 0x55, 0xb0, 0x0a, 0xde, 0x21, 0x4c, 0x5a, 0x2e, 0xd4, 0x80, 0x3a, 0x57, 0x92, 0x7a, 0xf1, 0xc4, 0x2c, 0x40, 0xaf, 0x2f, 0xc9, 0x92, 0x03, 0xe5, 0x5a, 0xbc, 0xdc, 0xf4, 0x09}}}, {{{0xf3, 0xe1, 0x2b, 0x7c, 0x05, 0x86, 0x80, 0x93, 0x4a, 0xad, 0xb4, 0x8f, 0x7e, 0x99, 0x0c, 0xfd, 0xcd, 0xef, 0xd1, 0xff, 0x2c, 0x69, 0x34, 0x13, 0x41, 0x64, 0xcf, 0x3b, 0xd0, 0x90, 0x09, 0x1e}} , {{0x9d, 0x45, 0xd6, 0x80, 0xe6, 0x45, 0xaa, 0xf4, 0x15, 0xaa, 0x5c, 0x34, 0x87, 0x99, 0xa2, 0x8c, 0x26, 0x84, 0x62, 0x7d, 0xb6, 0x29, 0xc0, 0x52, 0xea, 0xf5, 0x81, 0x18, 0x0f, 0x35, 0xa9, 0x0e}}}, {{{0xe7, 0x20, 0x72, 0x7c, 0x6d, 0x94, 0x5f, 0x52, 0x44, 0x54, 0xe3, 0xf1, 0xb2, 0xb0, 0x36, 0x46, 0x0f, 0xae, 0x92, 0xe8, 0x70, 0x9d, 0x6e, 0x79, 0xb1, 0xad, 0x37, 0xa9, 0x5f, 0xc0, 0xde, 0x03}} , {{0x15, 0x55, 0x37, 0xc6, 0x1c, 0x27, 0x1c, 0x6d, 0x14, 0x4f, 0xca, 0xa4, 0xc4, 0x88, 0x25, 0x46, 0x39, 0xfc, 0x5a, 0xe5, 0xfe, 0x29, 0x11, 0x69, 0xf5, 0x72, 0x84, 0x4d, 0x78, 0x9f, 0x94, 0x15}}}, {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, {{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, {{{0xec, 0xd3, 0xff, 0x57, 0x0b, 0xb0, 0xb2, 0xdc, 0xf8, 0x4f, 0xe2, 0x12, 0xd5, 0x36, 0xbe, 0x6b, 0x09, 0x43, 0x6d, 0xa3, 0x4d, 0x90, 0x2d, 0xb8, 0x74, 0xe8, 0x71, 0x45, 0x19, 0x8b, 0x0c, 0x6a}} , {{0xb8, 0x42, 0x1c, 0x03, 0xad, 0x2c, 0x03, 0x8e, 0xac, 0xd7, 0x98, 0x29, 0x13, 0xc6, 0x02, 0x29, 0xb5, 0xd4, 0xe7, 0xcf, 0xcc, 0x8b, 0x83, 0xec, 0x35, 0xc7, 0x9c, 0x74, 0xb7, 0xad, 0x85, 0x5f}}}, {{{0x78, 0x84, 0xe1, 0x56, 0x45, 0x69, 0x68, 0x5a, 0x4f, 0xb8, 0xb1, 0x29, 0xff, 0x33, 0x03, 0x31, 0xb7, 0xcb, 0x96, 0x25, 0xe6, 0xe6, 0x41, 0x98, 0x1a, 0xbb, 0x03, 0x56, 0xf2, 0xb2, 0x91, 0x34}} , {{0x2c, 0x6c, 0xf7, 0x66, 0xa4, 0x62, 0x6b, 0x39, 0xb3, 0xba, 0x65, 0xd3, 0x1c, 0xf8, 0x11, 0xaa, 0xbe, 0xdc, 0x80, 0x59, 0x87, 0xf5, 0x7b, 0xe5, 0xe3, 0xb3, 0x3e, 0x39, 0xda, 0xbe, 0x88, 0x09}}}, {{{0x8b, 0xf1, 0xa0, 0xf5, 0xdc, 0x29, 0xb4, 0xe2, 0x07, 0xc6, 0x7a, 0x00, 0xd0, 0x89, 0x17, 0x51, 0xd4, 0xbb, 0xd4, 0x22, 0xea, 0x7e, 0x7d, 0x7c, 0x24, 0xea, 0xf2, 0xe8, 0x22, 0x12, 0x95, 0x06}} , {{0xda, 0x7c, 0xa4, 0x0c, 0xf4, 0xba, 0x6e, 0xe1, 0x89, 0xb5, 0x59, 0xca, 0xf1, 0xc0, 0x29, 0x36, 0x09, 0x44, 0xe2, 0x7f, 0xd1, 0x63, 0x15, 0x99, 0xea, 0x25, 0xcf, 0x0c, 0x9d, 0xc0, 0x44, 0x6f}}}, {{{0x1d, 0x86, 0x4e, 0xcf, 0xf7, 0x37, 0x10, 0x25, 0x8f, 0x12, 0xfb, 0x19, 0xfb, 0xe0, 0xed, 0x10, 0xc8, 0xe2, 0xf5, 0x75, 0xb1, 0x33, 0xc0, 0x96, 0x0d, 0xfb, 0x15, 0x6c, 0x0d, 0x07, 0x5f, 0x05}} , {{0x69, 0x3e, 0x47, 0x97, 0x2c, 0xaf, 0x52, 0x7c, 0x78, 0x83, 0xad, 0x1b, 0x39, 0x82, 0x2f, 0x02, 0x6f, 0x47, 0xdb, 0x2a, 0xb0, 0xe1, 0x91, 0x99, 0x55, 0xb8, 0x99, 0x3a, 0xa0, 0x44, 0x11, 0x51}}} ================================================ FILE: src/libssh/src/external/poly1305.c ================================================ /* * Public Domain poly1305 from Andrew Moon * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna */ #include "config.h" #include #include #include "libssh/poly1305.h" #define mul32x32_64(a,b) ((uint64_t)(a) * (b)) #define U8TO32_LE(p) \ (((uint32_t)((p)[0])) | \ ((uint32_t)((p)[1]) << 8) | \ ((uint32_t)((p)[2]) << 16) | \ ((uint32_t)((p)[3]) << 24)) #define U32TO8_LE(p, v) \ do { \ (p)[0] = (uint8_t)((v)); \ (p)[1] = (uint8_t)((v) >> 8); \ (p)[2] = (uint8_t)((v) >> 16); \ (p)[3] = (uint8_t)((v) >> 24); \ } while (0) void poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { uint32_t t0,t1,t2,t3; uint32_t h0,h1,h2,h3,h4; uint32_t r0,r1,r2,r3,r4; uint32_t s1,s2,s3,s4; uint32_t b, nb; size_t j; uint64_t t[5]; uint64_t f0,f1,f2,f3; uint32_t g0,g1,g2,g3,g4; uint64_t c; unsigned char mp[16]; /* clamp key */ t0 = U8TO32_LE(key+0); t1 = U8TO32_LE(key+4); t2 = U8TO32_LE(key+8); t3 = U8TO32_LE(key+12); /* precompute multipliers */ r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; r3 = t2 & 0x3f03fff; t3 >>= 8; r4 = t3 & 0x00fffff; s1 = r1 * 5; s2 = r2 * 5; s3 = r3 * 5; s4 = r4 * 5; /* init state */ h0 = 0; h1 = 0; h2 = 0; h3 = 0; h4 = 0; /* full blocks */ if (inlen < 16) goto poly1305_donna_atmost15bytes; poly1305_donna_16bytes: m += 16; inlen -= 16; t0 = U8TO32_LE(m-16); t1 = U8TO32_LE(m-12); t2 = U8TO32_LE(m-8); t3 = U8TO32_LE(m-4); h0 += t0 & 0x3ffffff; h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; h4 += (t3 >> 8) | (1 << 24); poly1305_donna_mul: t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1); t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2); t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3); t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4); t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0); h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26); t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26); t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26); t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26); t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26); h0 += b * 5; if (inlen >= 16) goto poly1305_donna_16bytes; /* final bytes */ poly1305_donna_atmost15bytes: if (!inlen) goto poly1305_donna_finish; for (j = 0; j < inlen; j++) mp[j] = m[j]; mp[j++] = 1; for (; j < 16; j++) mp[j] = 0; inlen = 0; t0 = U8TO32_LE(mp+0); t1 = U8TO32_LE(mp+4); t2 = U8TO32_LE(mp+8); t3 = U8TO32_LE(mp+12); h0 += t0 & 0x3ffffff; h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; h4 += (t3 >> 8); goto poly1305_donna_mul; poly1305_donna_finish: b = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += b; g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff; g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff; g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff; g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff; g4 = h4 + b - (1 << 26); b = (g4 >> 31) - 1; nb = ~b; h0 = (h0 & nb) | (g0 & b); h1 = (h1 & nb) | (g1 & b); h2 = (h2 & nb) | (g2 & b); h3 = (h3 & nb) | (g3 & b); h4 = (h4 & nb) | (g4 & b); f0 = ((h0 ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]); f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]); f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]); f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)U8TO32_LE(&key[28]); U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32); U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32); U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32); U32TO8_LE(&out[12], f3); } ================================================ FILE: src/libssh/src/external/sc25519.c ================================================ /* * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, * Peter Schwabe, Bo-Yin Yang. * Copied from supercop-20130419/crypto_sign/ed25519/ref/sc25519.c */ #include "config.h" #include "libssh/priv.h" #include "libssh/sc25519.h" /*Arithmetic modulo the group order m = 2^252 + 27742317777372353535851937790883648493 = 7237005577332262213973186563042994240857116359379907606001950938285454250989 */ static const uint32_t m[32] = { 0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; static const uint32_t mu[33] = { 0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED, 0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; static uint32_t lt(uint32_t a,uint32_t b) /* 16-bit inputs */ { unsigned int x = a; x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ x >>= 31; /* 0: no; 1: yes */ return x; } /* Reduce coefficients of r before calling reduce_add_sub */ static void reduce_add_sub(sc25519 *r) { uint32_t pb = 0; uint32_t b; uint32_t mask; int i; unsigned char t[32]; for (i = 0; i < 32; i++) { pb += m[i]; b = lt(r->v[i],pb); t[i] = r->v[i]-pb+(b<<8); pb = b; } mask = b - 1; for (i = 0; i < 32; i++) { r->v[i] ^= mask & (r->v[i] ^ t[i]); } } /* Reduce coefficients of x before calling barrett_reduce */ static void barrett_reduce(sc25519 *r, const uint32_t x[64]) { /* See HAC, Alg. 14.42 */ int i,j; uint32_t q2[66]; uint32_t *q3 = q2 + 33; uint32_t r1[33]; uint32_t r2[33]; uint32_t carry; uint32_t pb = 0; uint32_t b; for (i = 0; i < 66; i++) { q2[i] = 0; } for (i = 0; i < 33; i++) { r2[i] = 0; } for (i = 0; i < 33; i++) { for (j = 0; j < 33; j++) { if (i + j >= 31) { q2[i+j] += mu[i]*x[j+31]; } } } carry = q2[31] >> 8; q2[32] += carry; carry = q2[32] >> 8; q2[33] += carry; for (i = 0; i < 33; i++) { r1[i] = x[i]; } for (i = 0; i < 32; i++) { for (j = 0; j < 33; j++) { if (i + j < 33) { r2[i+j] += m[i]*q3[j]; } } } for (i = 0; i < 32; i++) { carry = r2[i] >> 8; r2[i+1] += carry; r2[i] &= 0xff; } for (i = 0; i < 32; i++) { pb += r2[i]; b = lt(r1[i],pb); r->v[i] = r1[i]-pb+(b<<8); pb = b; } /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 * If so: Handle it here! */ reduce_add_sub(r); reduce_add_sub(r); } void sc25519_from32bytes(sc25519 *r, const unsigned char x[32]) { int i; uint32_t t[64]; for (i = 0; i < 32; i++) { t[i] = x[i]; } for (i = 32; i < 64; i++) { t[i] = 0; } barrett_reduce(r, t); } void shortsc25519_from16bytes(shortsc25519 *r, const unsigned char x[16]) { int i; for (i = 0; i < 16; i++) { r->v[i] = x[i]; } } void sc25519_from64bytes(sc25519 *r, const unsigned char x[64]) { int i; uint32_t t[64]; for (i = 0; i < 64; i++) { t[i] = x[i]; } barrett_reduce(r, t); } void sc25519_from_shortsc(sc25519 *r, const shortsc25519 *x) { int i; for (i = 0; i < 16; i++) { r->v[i] = x->v[i]; } for (i = 0; i < 16; i++) { r->v[16+i] = 0; } } void sc25519_to32bytes(unsigned char r[32], const sc25519 *x) { int i; for (i = 0; i < 32; i++) { r[i] = x->v[i]; } } int sc25519_iszero_vartime(const sc25519 *x) { int i; for (i = 0; i < 32; i++) { if(x->v[i] != 0) { return 0; } } return 1; } int sc25519_isshort_vartime(const sc25519 *x) { int i; for (i = 31; i > 15; i--) { if (x->v[i] != 0) { return 0; } } return 1; } int sc25519_lt_vartime(const sc25519 *x, const sc25519 *y) { int i; for (i = 31; i >= 0; i--) { if (x->v[i] < y->v[i]) { return 1; } if (x->v[i] > y->v[i]) { return 0; } } return 0; } void sc25519_add(sc25519 *r, const sc25519 *x, const sc25519 *y) { uint32_t i, carry; for (i = 0; i < 32; i++) { r->v[i] = x->v[i] + y->v[i]; } for (i = 0;i < 31; i++) { carry = r->v[i] >> 8; r->v[i+1] += carry; r->v[i] &= 0xff; } reduce_add_sub(r); } void sc25519_sub_nored(sc25519 *r, const sc25519 *x, const sc25519 *y) { uint32_t b = 0; uint32_t t; int i; for (i = 0; i < 32; i++) { t = x->v[i] - y->v[i] - b; r->v[i] = t & 255; b = (t >> 8) & 1; } } void sc25519_mul(sc25519 *r, const sc25519 *x, const sc25519 *y) { uint32_t i,j,carry; uint32_t t[64]; for (i = 0; i < 64; i++) { t[i] = 0; } for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) { t[i+j] += x->v[i] * y->v[j]; } } /* Reduce coefficients */ for (i = 0; i < 63; i++) { carry = t[i] >> 8; t[i+1] += carry; t[i] &= 0xff; } barrett_reduce(r, t); } void sc25519_mul_shortsc(sc25519 *r, const sc25519 *x, const shortsc25519 *y) { sc25519 t; sc25519_from_shortsc(&t, y); sc25519_mul(r, x, &t); } void sc25519_window3(signed char r[85], const sc25519 *s) { char carry; int i; for (i = 0; i < 10; i++) { r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; r[8*i+5] = (s->v[3*i+1] >> 7) & 7; r[8*i+5] ^= (s->v[3*i+2] << 1) & 7; r[8*i+6] = (s->v[3*i+2] >> 2) & 7; r[8*i+7] = (s->v[3*i+2] >> 5) & 7; } r[8*i+0] = s->v[3*i+0] & 7; r[8*i+1] = (s->v[3*i+0] >> 3) & 7; r[8*i+2] = (s->v[3*i+0] >> 6) & 7; r[8*i+2] ^= (s->v[3*i+1] << 2) & 7; r[8*i+3] = (s->v[3*i+1] >> 1) & 7; r[8*i+4] = (s->v[3*i+1] >> 4) & 7; /* Making it signed */ carry = 0; for (i = 0; i < 84; i++) { r[i] += carry; r[i+1] += r[i] >> 3; r[i] &= 7; carry = r[i] >> 2; r[i] -= carry<<3; } r[84] += carry; } void sc25519_window5(signed char r[51], const sc25519 *s) { char carry; int i; for (i = 0; i < 6; i++) { r[8*i+0] = s->v[5*i+0] & 31; r[8*i+1] = (s->v[5*i+0] >> 5) & 31; r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; r[8*i+2] = (s->v[5*i+1] >> 2) & 31; r[8*i+3] = (s->v[5*i+1] >> 7) & 31; r[8*i+3] ^= (s->v[5*i+2] << 1) & 31; r[8*i+4] = (s->v[5*i+2] >> 4) & 31; r[8*i+4] ^= (s->v[5*i+3] << 4) & 31; r[8*i+5] = (s->v[5*i+3] >> 1) & 31; r[8*i+6] = (s->v[5*i+3] >> 6) & 31; r[8*i+6] ^= (s->v[5*i+4] << 2) & 31; r[8*i+7] = (s->v[5*i+4] >> 3) & 31; } r[8*i+0] = s->v[5*i+0] & 31; r[8*i+1] = (s->v[5*i+0] >> 5) & 31; r[8*i+1] ^= (s->v[5*i+1] << 3) & 31; r[8*i+2] = (s->v[5*i+1] >> 2) & 31; /* Making it signed */ carry = 0; for (i = 0; i < 50; i++) { r[i] += carry; r[i+1] += r[i] >> 5; r[i] &= 31; carry = r[i] >> 4; r[i] -= carry<<5; } r[50] += carry; } void sc25519_2interleave2(unsigned char r[127], const sc25519 *s1, const sc25519 *s2) { int i; for (i = 0; i < 31; i++) { r[4*i] = ( s1->v[i] & 3) ^ (( s2->v[i] & 3) << 2); r[4*i+1] = ((s1->v[i] >> 2) & 3) ^ (((s2->v[i] >> 2) & 3) << 2); r[4*i+2] = ((s1->v[i] >> 4) & 3) ^ (((s2->v[i] >> 4) & 3) << 2); r[4*i+3] = ((s1->v[i] >> 6) & 3) ^ (((s2->v[i] >> 6) & 3) << 2); } r[124] = ( s1->v[31] & 3) ^ (( s2->v[31] & 3) << 2); r[125] = ((s1->v[31] >> 2) & 3) ^ (((s2->v[31] >> 2) & 3) << 2); r[126] = ((s1->v[31] >> 4) & 3) ^ (((s2->v[31] >> 4) & 3) << 2); } ================================================ FILE: src/libssh/src/gcrypt_missing.c ================================================ /* * gcrypt_missing.c - routines that are in OpenSSL but not in libgcrypt. * * This file is part of the SSH Library * * Copyright (c) 2003-2006 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include "libssh/priv.h" #include "libssh/libgcrypt.h" #ifdef HAVE_LIBGCRYPT int ssh_gcry_dec2bn(bignum *bn, const char *data) { int count; *bn = bignum_new(); if (*bn == NULL) { return 0; } gcry_mpi_set_ui(*bn, 0); for (count = 0; data[count]; count++) { gcry_mpi_mul_ui(*bn, *bn, 10); gcry_mpi_add_ui(*bn, *bn, data[count] - '0'); } return count; } char *ssh_gcry_bn2dec(bignum bn) { bignum bndup, num, ten; char *ret; int count, count2; int size, rsize; char decnum; size = gcry_mpi_get_nbits(bn) * 3; rsize = size / 10 + size / 1000 + 2; ret = malloc(rsize + 1); if (ret == NULL) { return NULL; } if (!gcry_mpi_cmp_ui(bn, 0)) { strcpy(ret, "0"); } else { ten = bignum_new(); if (ten == NULL) { SAFE_FREE(ret); return NULL; } num = bignum_new(); if (num == NULL) { SAFE_FREE(ret); bignum_safe_free(ten); return NULL; } for (bndup = gcry_mpi_copy(bn), bignum_set_word(ten, 10), count = rsize; count; count--) { gcry_mpi_div(bndup, num, bndup, ten, 0); for (decnum = 0, count2 = gcry_mpi_get_nbits(num); count2; decnum *= 2, decnum += (gcry_mpi_test_bit(num, count2 - 1) ? 1 : 0), count2--) ; ret[count - 1] = decnum + '0'; } for (count = 0; count < rsize && ret[count] == '0'; count++) ; for (count2 = 0; count2 < rsize - count; ++count2) { ret[count2] = ret[count2 + count]; } ret[count2] = 0; bignum_safe_free(num); bignum_safe_free(bndup); bignum_safe_free(ten); } return ret; } /** @brief generates a random integer between 0 and max * @returns 1 in case of success, 0 otherwise */ int ssh_gcry_rand_range(bignum dest, bignum max) { size_t bits; bignum rnd; int rc; bits = bignum_num_bits(max) + 64; rnd = bignum_new(); if (rnd == NULL) { return 0; } rc = bignum_rand(rnd, bits); if (rc != 1) { return rc; } gcry_mpi_mod(dest, rnd, max); bignum_safe_free(rnd); return 1; } #endif ================================================ FILE: src/libssh/src/getpass.c ================================================ /* * getpass.c - platform independent getpass function. * * This file is part of the SSH Library * * Copyright (c) 2011-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include /** * @internal * * @brief Get the password from the console. * * @param[in] prompt The prompt to display. * * @param[in] buf The buffer to fill. * * @param[in] len The length of the buffer. * * @param[in] verify Should the password be verified? * * @return 1 on success, 0 on error. */ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) { char *tmp; char *ptr = NULL; int ok = 0; tmp = calloc(1, len); if (tmp == NULL) { return 0; } /* read the password */ while (!ok) { if (buf[0] != '\0') { fprintf(stdout, "%s[%s] ", prompt, buf); } else { fprintf(stdout, "%s", prompt); } fflush(stdout); if (fgets(tmp, len, stdin) == NULL) { free(tmp); return 0; } if ((ptr = strchr(tmp, '\n'))) { *ptr = '\0'; } fprintf(stdout, "\n"); if (*tmp) { strncpy(buf, tmp, len); } if (verify) { char *key_string; key_string = calloc(1, len); if (key_string == NULL) { break; } fprintf(stdout, "\nVerifying, please re-enter. %s", prompt); fflush(stdout); if (! fgets(key_string, len, stdin)) { explicit_bzero(key_string, len); SAFE_FREE(key_string); clearerr(stdin); continue; } if ((ptr = strchr(key_string, '\n'))) { *ptr = '\0'; } fprintf(stdout, "\n"); if (strcmp(buf, key_string)) { printf("\n\07\07Mismatch - try again\n"); explicit_bzero(key_string, len); SAFE_FREE(key_string); fflush(stdout); continue; } explicit_bzero(key_string, len); SAFE_FREE(key_string); } ok = 1; } explicit_bzero(tmp, len); free(tmp); return ok; } #ifdef _WIN32 #include int ssh_getpass(const char *prompt, char *buf, size_t len, int echo, int verify) { HANDLE h; DWORD mode = 0; int ok; /* fgets needs at least len - 1 */ if (prompt == NULL || buf == NULL || len < 2) { return -1; } /* get stdin and mode */ h = GetStdHandle(STD_INPUT_HANDLE); if (!GetConsoleMode(h, &mode)) { return -1; } /* disable echo */ if (!echo) { if (!SetConsoleMode(h, mode & ~ENABLE_ECHO_INPUT)) { return -1; } } ok = ssh_gets(prompt, buf, len, verify); /* reset echo */ SetConsoleMode(h, mode); if (!ok) { explicit_bzero(buf, len); return -1; } /* force termination */ buf[len - 1] = '\0'; return 0; } #else #include #ifdef HAVE_TERMIOS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif /** * @ingroup libssh_misc * * @brief Get a password from the console. * * You should make sure that the buffer is an empty string! * * You can also use this function to ask for a username. Then you can fill the * buffer with the username and it is shows to the users. If the users just * presses enter the buffer will be untouched. * * @code * char username[128]; * * snprintf(username, sizeof(username), "john"); * * ssh_getpass("Username:", username, sizeof(username), 1, 0); * @endcode * * The prompt will look like this: * * Username: [john] * * If you press enter then john is used as the username, or you can type it in * to change it. * * @param[in] prompt The prompt to show to ask for the password. * * @param[out] buf The buffer the password should be stored. It NEEDS to be * empty or filled out. * * @param[in] len The length of the buffer. * * @param[in] echo Should we echo what you type. * * @param[in] verify Should we ask for the password twice. * * @return 0 on success, -1 on error. */ int ssh_getpass(const char *prompt, char *buf, size_t len, int echo, int verify) { struct termios attr; struct termios old_attr; int ok = 0; int fd = -1; /* fgets needs at least len - 1 */ if (prompt == NULL || buf == NULL || len < 2) { return -1; } if (isatty(STDIN_FILENO)) { ZERO_STRUCT(attr); ZERO_STRUCT(old_attr); /* get local terminal attributes */ if (tcgetattr(STDIN_FILENO, &attr) < 0) { perror("tcgetattr"); return -1; } /* save terminal attributes */ memcpy(&old_attr, &attr, sizeof(attr)); if((fd = fcntl(0, F_GETFL, 0)) < 0) { perror("fcntl"); return -1; } /* disable echo */ if (!echo) { attr.c_lflag &= ~(ECHO); } /* write attributes to terminal */ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) < 0) { perror("tcsetattr"); return -1; } } /* disable nonblocking I/O */ if (fd & O_NDELAY) { fcntl(0, F_SETFL, fd & ~O_NDELAY); } ok = ssh_gets(prompt, buf, len, verify); if (isatty(STDIN_FILENO)) { /* reset terminal */ tcsetattr(STDIN_FILENO, TCSANOW, &old_attr); } /* close fd */ if (fd & O_NDELAY) { fcntl(0, F_SETFL, fd); } if (!ok) { explicit_bzero(buf, len); return -1; } /* force termination */ buf[len - 1] = '\0'; return 0; } #endif ================================================ FILE: src/libssh/src/gssapi.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include /** current state of an GSSAPI authentication */ enum ssh_gssapi_state_e { SSH_GSSAPI_STATE_NONE, /* no status */ SSH_GSSAPI_STATE_RCV_TOKEN, /* Expecting a token */ SSH_GSSAPI_STATE_RCV_MIC, /* Expecting a MIC */ }; struct ssh_gssapi_struct{ enum ssh_gssapi_state_e state; /* current state */ struct gss_OID_desc_struct mech; /* mechanism being elected for auth */ gss_cred_id_t server_creds; /* credentials of server */ gss_cred_id_t client_creds; /* creds delegated by the client */ gss_ctx_id_t ctx; /* the authentication context */ gss_name_t client_name; /* Identity of the client */ char *user; /* username of client */ char *canonic_user; /* canonic form of the client's username */ char *service; /* name of the service */ struct { gss_name_t server_name; /* identity of server */ OM_uint32 flags; /* flags used for init context */ gss_OID oid; /* mech being used for authentication */ gss_cred_id_t creds; /* creds used to initialize context */ gss_cred_id_t client_deleg_creds; /* delegated creds (const, not freeable) */ } client; }; /** @internal * @initializes a gssapi context for authentication */ static int ssh_gssapi_init(ssh_session session){ if (session->gssapi != NULL) return SSH_OK; session->gssapi = malloc(sizeof(struct ssh_gssapi_struct)); if(!session->gssapi){ ssh_set_error_oom(session); return SSH_ERROR; } ZERO_STRUCTP(session->gssapi); session->gssapi->server_creds = GSS_C_NO_CREDENTIAL; session->gssapi->client_creds = GSS_C_NO_CREDENTIAL; session->gssapi->ctx = GSS_C_NO_CONTEXT; session->gssapi->state = SSH_GSSAPI_STATE_NONE; return SSH_OK; } /** @internal * @frees a gssapi context */ static void ssh_gssapi_free(ssh_session session){ OM_uint32 min; if (session->gssapi == NULL) return; SAFE_FREE(session->gssapi->user); SAFE_FREE(session->gssapi->mech.elements); gss_release_cred(&min,&session->gssapi->server_creds); if (session->gssapi->client.creds != session->gssapi->client.client_deleg_creds) { gss_release_cred(&min, &session->gssapi->client.creds); } SAFE_FREE(session->gssapi); } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token){ #ifdef WITH_SERVER if(session->server) return ssh_packet_userauth_gssapi_token_server(session, type, packet, user); #endif return ssh_packet_userauth_gssapi_token_client(session, type, packet, user); } #ifdef WITH_SERVER /** @internal * @brief sends a SSH_MSG_USERAUTH_GSSAPI_RESPONSE packet * @param[in] oid the OID that was selected for authentication */ static int ssh_gssapi_send_response(ssh_session session, ssh_string oid){ if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE) < 0 || ssh_buffer_add_ssh_string(session->out_buffer,oid) < 0) { ssh_set_error_oom(session); return SSH_ERROR; } session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN; ssh_packet_send(session); SSH_LOG(SSH_LOG_PACKET, "Sent SSH_MSG_USERAUTH_GSSAPI_RESPONSE"); return SSH_OK; } #endif /* WITH_SERVER */ static void ssh_gssapi_log_error(int verb, const char *msg, int maj_stat, int min_stat) { gss_buffer_desc msg_maj = { .length = 0, }; gss_buffer_desc msg_min = { .length = 0, }; OM_uint32 dummy_maj, dummy_min; OM_uint32 message_context = 0; dummy_maj = gss_display_status(&dummy_min, maj_stat, GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &msg_maj); if (dummy_maj != 0) { goto out; } dummy_maj = gss_display_status(&dummy_min, min_stat, GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context, &msg_min); if (dummy_maj != 0) { goto out; } SSH_LOG(verb, "GSSAPI(%s): %s - %s", msg, (const char *)msg_maj.value, (const char *)msg_min.value); out: if (msg_maj.value) { gss_release_buffer(&dummy_min, &msg_maj); } if (msg_min.value) { gss_release_buffer(&dummy_min, &msg_min); } } #ifdef WITH_SERVER /** @internal * @brief handles an user authentication using GSSAPI */ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids){ char service_name[]="host"; gss_buffer_desc name_buf; gss_name_t server_name; /* local server fqdn */ OM_uint32 maj_stat, min_stat; size_t i; char *ptr; gss_OID_set supported; /* oids supported by server */ gss_OID_set both_supported; /* oids supported by both client and server */ gss_OID_set selected; /* oid selected for authentication */ int present=0; size_t oid_count=0; struct gss_OID_desc_struct oid; int rc; if (ssh_callbacks_exists(session->server_callbacks, gssapi_select_oid_function)){ ssh_string oid_s = session->server_callbacks->gssapi_select_oid_function(session, user, n_oid, oids, session->server_callbacks->userdata); if (oid_s != NULL){ if (ssh_gssapi_init(session) == SSH_ERROR) return SSH_ERROR; session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN; rc = ssh_gssapi_send_response(session, oid_s); SSH_STRING_FREE(oid_s); return rc; } else { return ssh_auth_reply_default(session,0); } } gss_create_empty_oid_set(&min_stat, &both_supported); maj_stat = gss_indicate_mechs(&min_stat, &supported); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "indicate mecks %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "indicate mechs", maj_stat, min_stat); return SSH_ERROR; } for (i=0; i < supported->count; ++i){ ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length); SSH_LOG(SSH_LOG_DEBUG, "Supported mech %zu: %s", i, ptr); free(ptr); } for (i=0 ; i< n_oid ; ++i){ unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]); size_t len = ssh_string_len(oids[i]); if (oid_s == NULL) { continue; } if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); continue; } oid.elements = &oid_s[2]; oid.length = len - 2; gss_test_oid_set_member(&min_stat,&oid,supported,&present); if(present){ gss_add_oid_set_member(&min_stat,&oid,&both_supported); oid_count++; } } gss_release_oid_set(&min_stat, &supported); if (oid_count == 0){ SSH_LOG(SSH_LOG_PROTOCOL,"GSSAPI: no OID match"); ssh_auth_reply_default(session, 0); gss_release_oid_set(&min_stat, &both_supported); return SSH_OK; } /* from now we have room for context */ if (ssh_gssapi_init(session) == SSH_ERROR) return SSH_ERROR; name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; maj_stat = gss_import_name(&min_stat, &name_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat, min_stat); return -1; } maj_stat = gss_acquire_cred(&min_stat, server_name, 0, both_supported, GSS_C_ACCEPT, &session->gssapi->server_creds, &selected, NULL); gss_release_name(&min_stat, &server_name); gss_release_oid_set(&min_stat, &both_supported); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "error acquiring credentials %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "acquiring creds", maj_stat, min_stat); ssh_auth_reply_default(session,0); return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "acquiring credentials %d, %d", maj_stat, min_stat); /* finding which OID from client we selected */ for (i=0 ; i< n_oid ; ++i){ unsigned char *oid_s = (unsigned char *) ssh_string_data(oids[i]); size_t len = ssh_string_len(oids[i]); if (oid_s == NULL) { continue; } if(len < 2 || oid_s[0] != SSH_OID_TAG || ((size_t)oid_s[1]) != len - 2){ SSH_LOG(SSH_LOG_WARNING,"GSSAPI: received invalid OID"); continue; } oid.elements = &oid_s[2]; oid.length = len - 2; gss_test_oid_set_member(&min_stat,&oid,selected,&present); if(present){ SSH_LOG(SSH_LOG_PACKET, "Selected oid %zu", i); break; } } session->gssapi->mech.length = oid.length; session->gssapi->mech.elements = malloc(oid.length); if (session->gssapi->mech.elements == NULL){ ssh_set_error_oom(session); return SSH_ERROR; } memcpy(session->gssapi->mech.elements, oid.elements, oid.length); gss_release_oid_set(&min_stat, &selected); session->gssapi->user = strdup(user); session->gssapi->service = service_name; session->gssapi->state = SSH_GSSAPI_STATE_RCV_TOKEN; return ssh_gssapi_send_response(session, oids[i]); } static char *ssh_gssapi_name_to_char(gss_name_t name){ gss_buffer_desc buffer; OM_uint32 maj_stat, min_stat; char *ptr; maj_stat = gss_display_name(&min_stat, name, &buffer, NULL); ssh_gssapi_log_error(SSH_LOG_WARNING, "converting name", maj_stat, min_stat); ptr = malloc(buffer.length + 1); if (ptr == NULL) { return NULL; } memcpy(ptr, buffer.value, buffer.length); ptr[buffer.length] = '\0'; gss_release_buffer(&min_stat, &buffer); return ptr; } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server){ ssh_string token; char *hexa; OM_uint32 maj_stat, min_stat; gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; gss_name_t client_name = GSS_C_NO_NAME; OM_uint32 ret_flags=0; gss_channel_bindings_t input_bindings=GSS_C_NO_CHANNEL_BINDINGS; int rc; (void)user; (void)type; SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_USERAUTH_GSSAPI_TOKEN"); if (!session->gssapi || session->gssapi->state != SSH_GSSAPI_STATE_RCV_TOKEN){ ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_USERAUTH_GSSAPI_TOKEN in invalid state"); return SSH_PACKET_USED; } token = ssh_buffer_get_ssh_string(packet); if (token == NULL){ ssh_set_error(session, SSH_REQUEST_DENIED, "ssh_packet_userauth_gssapi_token: invalid packet"); return SSH_PACKET_USED; } if (ssh_callbacks_exists(session->server_callbacks, gssapi_accept_sec_ctx_function)){ ssh_string out_token=NULL; rc = session->server_callbacks->gssapi_accept_sec_ctx_function(session, token, &out_token, session->server_callbacks->userdata); if (rc == SSH_ERROR){ ssh_auth_reply_default(session, 0); ssh_gssapi_free(session); session->gssapi=NULL; return SSH_PACKET_USED; } if (ssh_string_len(out_token) != 0){ rc = ssh_buffer_pack(session->out_buffer, "bS", SSH2_MSG_USERAUTH_GSSAPI_TOKEN, out_token); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_PACKET_USED; } ssh_packet_send(session); SSH_STRING_FREE(out_token); } else { session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC; } return SSH_PACKET_USED; } hexa = ssh_get_hexa(ssh_string_data(token),ssh_string_len(token)); SSH_LOG(SSH_LOG_PACKET, "GSSAPI Token : %s",hexa); SAFE_FREE(hexa); input_token.length = ssh_string_len(token); input_token.value = ssh_string_data(token); maj_stat = gss_accept_sec_context(&min_stat, &session->gssapi->ctx, session->gssapi->server_creds, &input_token, input_bindings, &client_name, NULL /*mech_oid*/, &output_token, &ret_flags, NULL /*time*/, &session->gssapi->client_creds); ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "accepting token", maj_stat, min_stat); SSH_STRING_FREE(token); if (client_name != GSS_C_NO_NAME){ session->gssapi->client_name = client_name; session->gssapi->canonic_user = ssh_gssapi_name_to_char(client_name); } if (GSS_ERROR(maj_stat)){ ssh_gssapi_log_error(SSH_LOG_WARNING, "Gssapi error", maj_stat, min_stat); ssh_auth_reply_default(session,0); ssh_gssapi_free(session); session->gssapi=NULL; return SSH_PACKET_USED; } if (output_token.length != 0){ hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); SAFE_FREE(hexa); ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_USERAUTH_GSSAPI_TOKEN, output_token.length, (size_t)output_token.length, output_token.value); ssh_packet_send(session); } if(maj_stat == GSS_S_COMPLETE){ session->gssapi->state = SSH_GSSAPI_STATE_RCV_MIC; } return SSH_PACKET_USED; } #endif /* WITH_SERVER */ static ssh_buffer ssh_gssapi_build_mic(ssh_session session) { struct ssh_crypto_struct *crypto = NULL; ssh_buffer mic_buffer = NULL; int rc; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH); if (crypto == NULL) { return NULL; } mic_buffer = ssh_buffer_new(); if (mic_buffer == NULL) { ssh_set_error_oom(session); return NULL; } rc = ssh_buffer_pack(mic_buffer, "dPbsss", crypto->digest_len, (size_t)crypto->digest_len, crypto->session_id, SSH2_MSG_USERAUTH_REQUEST, session->gssapi->user, "ssh-connection", "gssapi-with-mic"); if (rc != SSH_OK) { ssh_set_error_oom(session); SSH_BUFFER_FREE(mic_buffer); return NULL; } return mic_buffer; } #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic) { ssh_string mic_token; OM_uint32 maj_stat, min_stat; gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER; ssh_buffer mic_buffer = NULL; (void)user; (void)type; SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_USERAUTH_GSSAPI_MIC"); mic_token = ssh_buffer_get_ssh_string(packet); if (mic_token == NULL) { ssh_set_error(session, SSH_FATAL, "Missing MIC in packet"); goto error; } if (session->gssapi == NULL || session->gssapi->state != SSH_GSSAPI_STATE_RCV_MIC) { ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_USERAUTH_GSSAPI_MIC in invalid state"); goto error; } mic_buffer = ssh_gssapi_build_mic(session); if (mic_buffer == NULL) { ssh_set_error_oom(session); goto error; } if (ssh_callbacks_exists(session->server_callbacks, gssapi_verify_mic_function)){ int rc = session->server_callbacks->gssapi_verify_mic_function(session, mic_token, ssh_buffer_get(mic_buffer), ssh_buffer_get_len(mic_buffer), session->server_callbacks->userdata); if (rc != SSH_OK) { goto error; } } else { mic_buf.length = ssh_buffer_get_len(mic_buffer); mic_buf.value = ssh_buffer_get(mic_buffer); mic_token_buf.length = ssh_string_len(mic_token); mic_token_buf.value = ssh_string_data(mic_token); maj_stat = gss_verify_mic(&min_stat, session->gssapi->ctx, &mic_buf, &mic_token_buf, NULL); ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "verifying MIC", maj_stat, min_stat); if (maj_stat == GSS_S_DEFECTIVE_TOKEN || GSS_ERROR(maj_stat)) { goto error; } } if (ssh_callbacks_exists(session->server_callbacks, auth_gssapi_mic_function)){ switch(session->server_callbacks->auth_gssapi_mic_function(session, session->gssapi->user, session->gssapi->canonic_user, session->server_callbacks->userdata)){ case SSH_AUTH_SUCCESS: ssh_auth_reply_success(session, 0); break; case SSH_AUTH_PARTIAL: ssh_auth_reply_success(session, 1); break; default: ssh_auth_reply_default(session, 0); break; } } goto end; error: ssh_auth_reply_default(session,0); end: ssh_gssapi_free(session); if (mic_buffer != NULL) { SSH_BUFFER_FREE(mic_buffer); } if (mic_token != NULL) { SSH_STRING_FREE(mic_token); } return SSH_PACKET_USED; } /** @brief returns the client credentials of the connected client. * If the client has given a forwardable token, the SSH server will * retrieve it. * @returns gssapi credentials handle. * @returns NULL if no forwardable token is available. */ ssh_gssapi_creds ssh_gssapi_get_creds(ssh_session session){ if (!session || !session->gssapi || session->gssapi->client_creds == GSS_C_NO_CREDENTIAL) return NULL; return (ssh_gssapi_creds)session->gssapi->client_creds; } #endif /* SERVER */ /** * @brief Set the forwadable ticket to be given to the server for authentication. * Unlike ssh_gssapi_get_creds() this is called on the client side of an ssh * connection. * * @param[in] creds gssapi credentials handle. */ void ssh_gssapi_set_creds(ssh_session session, const ssh_gssapi_creds creds) { if (session == NULL) { return; } if (session->gssapi == NULL) { ssh_gssapi_init(session); if (session->gssapi == NULL) { return; } } session->gssapi->client.client_deleg_creds = (gss_cred_id_t)creds; } static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, int n_oid){ int rc; int i; rc = ssh_buffer_pack(session->out_buffer, "bsssd", SSH2_MSG_USERAUTH_REQUEST, session->opts.username, "ssh-connection", "gssapi-with-mic", n_oid); if (rc != SSH_OK) { ssh_set_error_oom(session); goto fail; } for (i=0; iout_buffer, oid_set[i]); if (rc < 0) { goto fail; } } session->auth.state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT; return ssh_packet_send(session); fail: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; } /** @brief returns the OIDs of the mechs that have usable credentials */ static int ssh_gssapi_match(ssh_session session, gss_OID_set *valid_oids) { OM_uint32 maj_stat, min_stat, lifetime; gss_OID_set actual_mechs; gss_buffer_desc namebuf; gss_name_t client_id = GSS_C_NO_NAME; gss_OID oid; unsigned int i; char *ptr; int ret; if (session->gssapi->client.client_deleg_creds == NULL) { if (session->opts.gss_client_identity != NULL) { namebuf.value = (void *)session->opts.gss_client_identity; namebuf.length = strlen(session->opts.gss_client_identity); maj_stat = gss_import_name(&min_stat, &namebuf, GSS_C_NT_USER_NAME, &client_id); if (GSS_ERROR(maj_stat)) { ret = SSH_ERROR; goto end; } } maj_stat = gss_acquire_cred(&min_stat, client_id, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &session->gssapi->client.creds, &actual_mechs, NULL); if (GSS_ERROR(maj_stat)) { ret = SSH_ERROR; goto end; } } else { session->gssapi->client.creds = session->gssapi->client.client_deleg_creds; maj_stat = gss_inquire_cred(&min_stat, session->gssapi->client.creds, &client_id, NULL, NULL, &actual_mechs); if (GSS_ERROR(maj_stat)) { ret = SSH_ERROR; goto end; } } gss_create_empty_oid_set(&min_stat, valid_oids); /* double check each single cred */ for (i = 0; i < actual_mechs->count; i++) { /* check lifetime is not 0 or skip */ lifetime = 0; oid = &actual_mechs->elements[i]; maj_stat = gss_inquire_cred_by_mech(&min_stat, session->gssapi->client.creds, oid, NULL, &lifetime, NULL, NULL); if (maj_stat == GSS_S_COMPLETE && lifetime > 0) { gss_add_oid_set_member(&min_stat, oid, valid_oids); ptr = ssh_get_hexa(oid->elements, oid->length); SSH_LOG(SSH_LOG_DEBUG, "GSSAPI valid oid %d : %s", i, ptr); SAFE_FREE(ptr); } } ret = SSH_OK; end: gss_release_name(&min_stat, &client_id); return ret; } /** * @brief launches a gssapi-with-mic auth request * @returns SSH_AUTH_ERROR: A serious error happened\n * SSH_AUTH_DENIED: Authentication failed : use another method\n * SSH_AUTH_AGAIN: In nonblocking mode, you've got to call this again * later. */ int ssh_gssapi_auth_mic(ssh_session session){ size_t i; gss_OID_set selected; /* oid selected for authentication */ ssh_string *oids = NULL; int rc; size_t n_oids = 0; OM_uint32 maj_stat, min_stat; char name_buf[256] = {0}; gss_buffer_desc hostname; const char *gss_host = session->opts.host; rc = ssh_gssapi_init(session); if (rc == SSH_ERROR) { return SSH_AUTH_ERROR; } if (session->opts.gss_server_identity != NULL) { gss_host = session->opts.gss_server_identity; } /* import target host name */ snprintf(name_buf, sizeof(name_buf), "host@%s", gss_host); hostname.value = name_buf; hostname.length = strlen(name_buf) + 1; maj_stat = gss_import_name(&min_stat, &hostname, (gss_OID)GSS_C_NT_HOSTBASED_SERVICE, &session->gssapi->client.server_name); if (maj_stat != GSS_S_COMPLETE) { SSH_LOG(SSH_LOG_WARNING, "importing name %d, %d", maj_stat, min_stat); ssh_gssapi_log_error(SSH_LOG_WARNING, "importing name", maj_stat, min_stat); return SSH_AUTH_DENIED; } /* copy username */ session->gssapi->user = strdup(session->opts.username); if (session->gssapi->user == NULL) { ssh_set_error_oom(session); return SSH_AUTH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi to host %s with user %s", session->opts.host, session->gssapi->user); rc = ssh_gssapi_match(session, &selected); if (rc == SSH_ERROR) { return SSH_AUTH_DENIED; } n_oids = selected->count; SSH_LOG(SSH_LOG_PROTOCOL, "Sending %zu oids", n_oids); oids = calloc(n_oids, sizeof(ssh_string)); if (oids == NULL) { ssh_set_error_oom(session); return SSH_AUTH_ERROR; } for (i=0; ielements[i].length + 2); if (oids[i] == NULL) { ssh_set_error_oom(session); rc = SSH_ERROR; goto out; } ((unsigned char *)oids[i]->data)[0] = SSH_OID_TAG; ((unsigned char *)oids[i]->data)[1] = selected->elements[i].length; memcpy((unsigned char *)oids[i]->data + 2, selected->elements[i].elements, selected->elements[i].length); } rc = ssh_gssapi_send_auth_mic(session, oids, n_oids); out: for (i = 0; i < n_oids; i++) { SSH_STRING_FREE(oids[i]); } free(oids); if (rc != SSH_ERROR) { return SSH_AUTH_AGAIN; } return SSH_AUTH_ERROR; } static gss_OID ssh_gssapi_oid_from_string(ssh_string oid_s) { gss_OID ret = NULL; unsigned char *data = ssh_string_data(oid_s); size_t len = ssh_string_len(oid_s); if (data == NULL) { return NULL; } if (len > 256 || len <= 2) { SAFE_FREE(ret); return NULL; } if (data[0] != SSH_OID_TAG || data[1] != len - 2) { SAFE_FREE(ret); return NULL; } ret = malloc(sizeof(gss_OID_desc)); if (ret == NULL) { return NULL; } ret->elements = malloc(len - 2); if (ret->elements == NULL) { SAFE_FREE(ret); return NULL; } memcpy(ret->elements, &data[2], len-2); ret->length = len-2; return ret; } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){ ssh_string oid_s; gss_uint32 maj_stat, min_stat; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; char *hexa; (void)type; (void)user; SSH_LOG(SSH_LOG_PACKET, "Received SSH_USERAUTH_GSSAPI_RESPONSE"); if (session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT){ ssh_set_error(session, SSH_FATAL, "Invalid state in ssh_packet_userauth_gssapi_response"); goto error; } oid_s = ssh_buffer_get_ssh_string(packet); if (!oid_s){ ssh_set_error(session, SSH_FATAL, "Missing OID"); goto error; } session->gssapi->client.oid = ssh_gssapi_oid_from_string(oid_s); SSH_STRING_FREE(oid_s); if (!session->gssapi->client.oid) { ssh_set_error(session, SSH_FATAL, "Invalid OID"); goto error; } session->gssapi->client.flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG; if (session->opts.gss_delegate_creds) { session->gssapi->client.flags |= GSS_C_DELEG_FLAG; } /* prepare the first TOKEN response */ maj_stat = gss_init_sec_context(&min_stat, session->gssapi->client.creds, &session->gssapi->ctx, session->gssapi->client.server_name, session->gssapi->client.oid, session->gssapi->client.flags, 0, NULL, &input_token, NULL, &output_token, NULL, NULL); if(GSS_ERROR(maj_stat)){ ssh_gssapi_log_error(SSH_LOG_WARNING, "Initializing gssapi context", maj_stat, min_stat); goto error; } if (output_token.length != 0){ hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s", hexa); SAFE_FREE(hexa); ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_USERAUTH_GSSAPI_TOKEN, output_token.length, (size_t)output_token.length, output_token.value); ssh_packet_send(session); session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN; } return SSH_PACKET_USED; error: session->auth.state = SSH_AUTH_STATE_ERROR; ssh_gssapi_free(session); session->gssapi = NULL; return SSH_PACKET_USED; } static int ssh_gssapi_send_mic(ssh_session session){ OM_uint32 maj_stat, min_stat; gss_buffer_desc mic_buf = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic_token_buf = GSS_C_EMPTY_BUFFER; ssh_buffer mic_buffer; int rc; SSH_LOG(SSH_LOG_PACKET,"Sending SSH_MSG_USERAUTH_GSSAPI_MIC"); mic_buffer = ssh_gssapi_build_mic(session); if (mic_buffer == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } mic_buf.length = ssh_buffer_get_len(mic_buffer); mic_buf.value = ssh_buffer_get(mic_buffer); maj_stat = gss_get_mic(&min_stat,session->gssapi->ctx, GSS_C_QOP_DEFAULT, &mic_buf, &mic_token_buf); if (GSS_ERROR(maj_stat)){ SSH_BUFFER_FREE(mic_buffer); ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "generating MIC", maj_stat, min_stat); return SSH_ERROR; } rc = ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_USERAUTH_GSSAPI_MIC, mic_token_buf.length, (size_t)mic_token_buf.length, mic_token_buf.value); if (rc != SSH_OK) { SSH_BUFFER_FREE(mic_buffer); ssh_set_error_oom(session); return SSH_ERROR; } return ssh_packet_send(session); } SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){ ssh_string token; char *hexa; OM_uint32 maj_stat, min_stat; gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER; (void)user; (void)type; SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_USERAUTH_GSSAPI_TOKEN"); if (!session->gssapi || session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN) { ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_USERAUTH_GSSAPI_TOKEN in invalid state"); goto error; } token = ssh_buffer_get_ssh_string(packet); if (token == NULL){ ssh_set_error(session, SSH_REQUEST_DENIED, "ssh_packet_userauth_gssapi_token: invalid packet"); goto error; } hexa = ssh_get_hexa(ssh_string_data(token),ssh_string_len(token)); SSH_LOG(SSH_LOG_PACKET, "GSSAPI Token : %s",hexa); SAFE_FREE(hexa); input_token.length = ssh_string_len(token); input_token.value = ssh_string_data(token); maj_stat = gss_init_sec_context(&min_stat, session->gssapi->client.creds, &session->gssapi->ctx, session->gssapi->client.server_name, session->gssapi->client.oid, session->gssapi->client.flags, 0, NULL, &input_token, NULL, &output_token, NULL, NULL); ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "accepting token", maj_stat, min_stat); SSH_STRING_FREE(token); if (GSS_ERROR(maj_stat)){ ssh_gssapi_log_error(SSH_LOG_PROTOCOL, "Gssapi error", maj_stat, min_stat); goto error; } if (output_token.length != 0) { hexa = ssh_get_hexa(output_token.value, output_token.length); SSH_LOG(SSH_LOG_PACKET, "GSSAPI: sending token %s",hexa); SAFE_FREE(hexa); ssh_buffer_pack(session->out_buffer, "bdP", SSH2_MSG_USERAUTH_GSSAPI_TOKEN, output_token.length, (size_t)output_token.length, output_token.value); ssh_packet_send(session); } if (maj_stat == GSS_S_COMPLETE) { ssh_gssapi_send_mic(session); session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT; } return SSH_PACKET_USED; error: session->auth.state = SSH_AUTH_STATE_ERROR; ssh_gssapi_free(session); session->gssapi = NULL; return SSH_PACKET_USED; } ================================================ FILE: src/libssh/src/gzip.c ================================================ /* * gzip.c - hooks for compression of packets * * This file is part of the SSH Library * * Copyright (c) 2003 by Aris Adamantiadis * Copyright (c) 2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/crypto.h" #include "libssh/session.h" #define BLOCKSIZE 4092 static z_stream *initcompress(ssh_session session, int level) { z_stream *stream = NULL; int status; stream = calloc(1, sizeof(z_stream)); if (stream == NULL) { return NULL; } status = deflateInit(stream, level); if (status != Z_OK) { SAFE_FREE(stream); ssh_set_error(session, SSH_FATAL, "status %d inititalising zlib deflate", status); return NULL; } return stream; } static ssh_buffer gzip_compress(ssh_session session, ssh_buffer source, int level) { struct ssh_crypto_struct *crypto = NULL; z_stream *zout = NULL; void *in_ptr = ssh_buffer_get(source); unsigned long in_size = ssh_buffer_get_len(source); ssh_buffer dest = NULL; unsigned char out_buf[BLOCKSIZE] = {0}; unsigned long len; int status; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); if (crypto == NULL) { return NULL; } zout = crypto->compress_out_ctx; if (zout == NULL) { zout = crypto->compress_out_ctx = initcompress(session, level); if (zout == NULL) { return NULL; } } dest = ssh_buffer_new(); if (dest == NULL) { return NULL; } zout->next_out = out_buf; zout->next_in = in_ptr; zout->avail_in = in_size; do { zout->avail_out = BLOCKSIZE; status = deflate(zout, Z_PARTIAL_FLUSH); if (status != Z_OK) { SSH_BUFFER_FREE(dest); ssh_set_error(session, SSH_FATAL, "status %d deflating zlib packet", status); return NULL; } len = BLOCKSIZE - zout->avail_out; if (ssh_buffer_add_data(dest, out_buf, len) < 0) { SSH_BUFFER_FREE(dest); return NULL; } zout->next_out = out_buf; } while (zout->avail_out == 0); return dest; } int compress_buffer(ssh_session session, ssh_buffer buf) { ssh_buffer dest = NULL; dest = gzip_compress(session, buf, session->opts.compressionlevel); if (dest == NULL) { return -1; } if (ssh_buffer_reinit(buf) < 0) { SSH_BUFFER_FREE(dest); return -1; } if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) { SSH_BUFFER_FREE(dest); return -1; } SSH_BUFFER_FREE(dest); return 0; } /* decompression */ static z_stream *initdecompress(ssh_session session) { z_stream *stream = NULL; int status; stream = calloc(1, sizeof(z_stream)); if (stream == NULL) { return NULL; } status = inflateInit(stream); if (status != Z_OK) { SAFE_FREE(stream); ssh_set_error(session, SSH_FATAL, "Status = %d initiating inflate context!", status); return NULL; } return stream; } static ssh_buffer gzip_decompress(ssh_session session, ssh_buffer source, size_t maxlen) { struct ssh_crypto_struct *crypto = NULL; z_stream *zin = NULL; void *in_ptr = ssh_buffer_get(source); unsigned long in_size = ssh_buffer_get_len(source); unsigned char out_buf[BLOCKSIZE] = {0}; ssh_buffer dest = NULL; unsigned long len; int status; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto == NULL) { return NULL; } zin = crypto->compress_in_ctx; if (zin == NULL) { zin = crypto->compress_in_ctx = initdecompress(session); if (zin == NULL) { return NULL; } } dest = ssh_buffer_new(); if (dest == NULL) { return NULL; } zin->next_out = out_buf; zin->next_in = in_ptr; zin->avail_in = in_size; do { zin->avail_out = BLOCKSIZE; status = inflate(zin, Z_PARTIAL_FLUSH); if (status != Z_OK && status != Z_BUF_ERROR) { ssh_set_error(session, SSH_FATAL, "status %d inflating zlib packet", status); SSH_BUFFER_FREE(dest); return NULL; } len = BLOCKSIZE - zin->avail_out; if (ssh_buffer_add_data(dest,out_buf,len) < 0) { SSH_BUFFER_FREE(dest); return NULL; } if (ssh_buffer_get_len(dest) > maxlen){ /* Size of packet exceeded, avoid a denial of service attack */ SSH_BUFFER_FREE(dest); return NULL; } zin->next_out = out_buf; } while (zin->avail_out == 0); return dest; } int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen){ ssh_buffer dest = NULL; dest = gzip_decompress(session,buf, maxlen); if (dest == NULL) { return -1; } if (ssh_buffer_reinit(buf) < 0) { SSH_BUFFER_FREE(dest); return -1; } if (ssh_buffer_add_data(buf, ssh_buffer_get(dest), ssh_buffer_get_len(dest)) < 0) { SSH_BUFFER_FREE(dest); return -1; } SSH_BUFFER_FREE(dest); return 0; } ================================================ FILE: src/libssh/src/init.c ================================================ /* * init.c - initialization and finalization of the library * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/priv.h" #include "libssh/socket.h" #include "libssh/dh.h" #include "libssh/poll.h" #include "libssh/threads.h" #ifdef _WIN32 #include #endif #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE #define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor)) #else #define CONSTRUCTOR_ATTRIBUTE #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */ #ifdef HAVE_DESTRUCTOR_ATTRIBUTE #define DESTRUCTOR_ATTRIBUTE __attribute__((destructor)) #else #define DESTRUCTOR_ATTRIBUTE #endif /* HAVE_DESTRUCTOR_ATTRIBUTE */ /* Declare static mutex */ static SSH_MUTEX ssh_init_mutex = SSH_MUTEX_STATIC_INIT; /* Counter for initializations */ static int _ssh_initialized = 0; /* Cache the returned value */ static int _ssh_init_ret = 0; void libssh_constructor(void) CONSTRUCTOR_ATTRIBUTE; void libssh_destructor(void) DESTRUCTOR_ATTRIBUTE; static int _ssh_init(unsigned constructor) { int rc = 0; if (!constructor) { ssh_mutex_lock(&ssh_init_mutex); } _ssh_initialized++; if (_ssh_initialized > 1) { rc = _ssh_init_ret; goto _ret; } rc = ssh_threads_init(); if (rc) { goto _ret; } rc = ssh_crypto_init(); if (rc) { goto _ret; } rc = ssh_dh_init(); if (rc) { goto _ret; } rc = ssh_socket_init(); if (rc) { goto _ret; } _ret: _ssh_init_ret = rc; if (!constructor) { ssh_mutex_unlock(&ssh_init_mutex); } return rc; } /** * @brief Initialize global cryptographic data structures. * * This functions is automatically called when the library is loaded. * */ void libssh_constructor(void) { int rc; rc = _ssh_init(1); if (rc < 0) { fprintf(stderr, "Error in auto_init()\n"); } return; } /** * @defgroup libssh The libssh API * * The libssh library is implementing the SSH protocols and some of its * extensions. This group of functions is mostly used to implement an SSH * client. * Some function are needed to implement an SSH server too. * * @{ */ /** * @brief Initialize global cryptographic data structures. * * Since version 0.8.0, when libssh is dynamically linked, it is not necessary * to call this function on systems which are fully supported with regards to * threading (that is, system with pthreads available). * * If libssh is statically linked, it is necessary to explicitly call ssh_init() * before calling any other provided API, and it is necessary to explicitly call * ssh_finalize() to free the allocated resources before exiting. * * If the library is already initialized, increments the _ssh_initialized * counter and return the error code cached in _ssh_init_ret. * * @returns SSH_OK on success, SSH_ERROR if an error occurred. * * @see ssh_finalize() */ int ssh_init(void) { return _ssh_init(0); } static int _ssh_finalize(unsigned destructor) { if (!destructor) { ssh_mutex_lock(&ssh_init_mutex); if (_ssh_initialized > 1) { _ssh_initialized--; goto _ret; } if (_ssh_initialized == 1) { if (_ssh_init_ret < 0) { goto _ret; } } } /* If the counter reaches zero or it is the destructor calling, finalize */ ssh_dh_finalize(); ssh_crypto_finalize(); ssh_socket_cleanup(); /* It is important to finalize threading after CRYPTO because * it still depends on it */ ssh_threads_finalize(); _ssh_initialized = 0; _ret: if (!destructor) { ssh_mutex_unlock(&ssh_init_mutex); } return 0; } /** * @brief Finalize and cleanup all libssh and cryptographic data structures. * * This function is automatically called when the library is unloaded. * */ void libssh_destructor(void) { int rc; rc = _ssh_finalize(1); if (rc < 0) { fprintf(stderr, "Error in libssh_destructor()\n"); } } /** * @brief Finalize and cleanup all libssh and cryptographic data structures. * * Since version 0.8.0, when libssh is dynamically linked, it is not necessary * to call this function, since it is automatically called when the library is * unloaded. * * If libssh is statically linked, it is necessary to explicitly call ssh_init() * before calling any other provided API, and it is necessary to explicitly call * ssh_finalize() to free the allocated resources before exiting. * * If ssh_init() is called explicitly, then ssh_finalize() must be called * explicitly. * * When called, decrements the counter _ssh_initialized. If the counter reaches * zero, then the libssh and cryptographic data structures are cleaned up. * * @returns 0 on success, -1 if an error occurred. * * @see ssh_init() */ int ssh_finalize(void) { return _ssh_finalize(0); } #ifdef _WIN32 #if defined(_MSC_VER) && !defined(LIBSSH_STATIC) /* Library constructor and destructor */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { int rc = 0; switch(fdwReason) { case DLL_PROCESS_ATTACH: rc = _ssh_init(1); if (rc != 0) { fprintf(stderr, "DllMain: ssh_init failed!"); return FALSE; } break; case DLL_PROCESS_DETACH: _ssh_finalize(1); break; default: break; } return TRUE; } #endif /* _MSC_VER && !LIBSSH_STATIC */ #endif /* _WIN32 */ /** * @internal * @brief Return whether the library is initialized * * @returns true if the library is initialized; false otherwise. * * @see ssh_init() */ bool is_ssh_initialized() { bool is_initialized = false; ssh_mutex_lock(&ssh_init_mutex); is_initialized = _ssh_initialized > 0; ssh_mutex_unlock(&ssh_init_mutex); return is_initialized; } /** @} */ ================================================ FILE: src/libssh/src/kdf.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * Copyrihgt (c) 2018 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/dh.h" #include "libssh/ssh2.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "libssh/string.h" /* The following implements the SSHKDF for crypto backend that * do not have a native implementations */ struct ssh_mac_ctx_struct { enum ssh_kdf_digest digest_type; union { SHACTX sha1_ctx; SHA256CTX sha256_ctx; SHA384CTX sha384_ctx; SHA512CTX sha512_ctx; } ctx; }; static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type) { ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct)); if (ctx == NULL) { return NULL; } ctx->digest_type = type; switch(type){ case SSH_KDF_SHA1: ctx->ctx.sha1_ctx = sha1_init(); return ctx; case SSH_KDF_SHA256: ctx->ctx.sha256_ctx = sha256_init(); return ctx; case SSH_KDF_SHA384: ctx->ctx.sha384_ctx = sha384_init(); return ctx; case SSH_KDF_SHA512: ctx->ctx.sha512_ctx = sha512_init(); return ctx; default: SAFE_FREE(ctx); return NULL; } } static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len) { switch(ctx->digest_type){ case SSH_KDF_SHA1: sha1_update(ctx->ctx.sha1_ctx, data, len); break; case SSH_KDF_SHA256: sha256_update(ctx->ctx.sha256_ctx, data, len); break; case SSH_KDF_SHA384: sha384_update(ctx->ctx.sha384_ctx, data, len); break; case SSH_KDF_SHA512: sha512_update(ctx->ctx.sha512_ctx, data, len); break; } } static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) { switch(ctx->digest_type){ case SSH_KDF_SHA1: sha1_final(md,ctx->ctx.sha1_ctx); break; case SSH_KDF_SHA256: sha256_final(md,ctx->ctx.sha256_ctx); break; case SSH_KDF_SHA384: sha384_final(md,ctx->ctx.sha384_ctx); break; case SSH_KDF_SHA512: sha512_final(md,ctx->ctx.sha512_ctx); break; } SAFE_FREE(ctx); } int sshkdf_derive_key(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { /* Can't use VLAs with Visual Studio, so allocate the biggest * digest buffer we can possibly need */ unsigned char digest[DIGEST_MAX_LEN]; size_t output_len = crypto->digest_len; char letter = key_type; ssh_mac_ctx ctx; if (DIGEST_MAX_LEN < crypto->digest_len) { return -1; } ctx = ssh_mac_ctx_init(crypto->digest_type); if (ctx == NULL) { return -1; } ssh_mac_update(ctx, key, key_len); ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ssh_mac_update(ctx, &letter, 1); ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); ssh_mac_final(digest, ctx); if (requested_len < output_len) { output_len = requested_len; } memcpy(output, digest, output_len); while (requested_len > output_len) { ctx = ssh_mac_ctx_init(crypto->digest_type); if (ctx == NULL) { return -1; } ssh_mac_update(ctx, key, key_len); ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); ssh_mac_update(ctx, output, output_len); ssh_mac_final(digest, ctx); if (requested_len < output_len + crypto->digest_len) { memcpy(output + output_len, digest, requested_len - output_len); } else { memcpy(output + output_len, digest, crypto->digest_len); } output_len += crypto->digest_len; } return 0; } ================================================ FILE: src/libssh/src/kex.c ================================================ /* * kex.c - key exchange * * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/dh.h" #ifdef WITH_GEX #include "libssh/dh-gex.h" #endif /* WITH_GEX */ #include "libssh/kex.h" #include "libssh/session.h" #include "libssh/ssh2.h" #include "libssh/string.h" #include "libssh/curve25519.h" #include "libssh/knownhosts.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/bignum.h" #include "libssh/token.h" #ifdef WITH_BLOWFISH_CIPHER # if defined(HAVE_OPENSSL_BLOWFISH_H) || defined(HAVE_LIBGCRYPT) || defined(HAVE_LIBMBEDCRYPTO) # define BLOWFISH "blowfish-cbc," # else # define BLOWFISH "" # endif #else # define BLOWFISH "" #endif #ifdef HAVE_LIBGCRYPT # define AES "aes256-gcm@openssh.com,aes128-gcm@openssh.com," \ "aes256-ctr,aes192-ctr,aes128-ctr," \ "aes256-cbc,aes192-cbc,aes128-cbc," # define DES "3des-cbc" # define DES_SUPPORTED "3des-cbc" #elif defined(HAVE_LIBMBEDCRYPTO) # ifdef MBEDTLS_GCM_C # define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com," # else # define GCM "" # endif /* MBEDTLS_GCM_C */ # define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr," \ "aes256-cbc,aes192-cbc,aes128-cbc," # define DES "3des-cbc" # define DES_SUPPORTED "3des-cbc" #elif defined(HAVE_LIBCRYPTO) # ifdef HAVE_OPENSSL_AES_H # ifdef HAVE_OPENSSL_EVP_AES_GCM # define GCM "aes256-gcm@openssh.com,aes128-gcm@openssh.com," # else # define GCM "" # endif /* HAVE_OPENSSL_EVP_AES_GCM */ # ifdef BROKEN_AES_CTR # define AES GCM "aes256-cbc,aes192-cbc,aes128-cbc," # else /* BROKEN_AES_CTR */ # define AES GCM "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc," # endif /* BROKEN_AES_CTR */ # else /* HAVE_OPENSSL_AES_H */ # define AES "" # endif /* HAVE_OPENSSL_AES_H */ # define DES "3des-cbc" # define DES_SUPPORTED "3des-cbc" #endif /* HAVE_LIBCRYPTO */ #ifdef WITH_ZLIB #define ZLIB "none,zlib,zlib@openssh.com" #else #define ZLIB "none" #endif #ifdef HAVE_CURVE25519 #define CURVE25519 "curve25519-sha256,curve25519-sha256@libssh.org," #else #define CURVE25519 "" #endif #ifdef HAVE_ECDH #define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521," #define EC_HOSTKEYS "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256," #define EC_PUBLIC_KEY_ALGORITHMS "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ "ecdsa-sha2-nistp256-cert-v01@openssh.com," #else #define EC_HOSTKEYS "" #define EC_PUBLIC_KEY_ALGORITHMS "" #define ECDH "" #endif #ifdef HAVE_DSA #define DSA_HOSTKEYS ",ssh-dss" #define DSA_PUBLIC_KEY_ALGORITHMS ",ssh-dss-cert-v01@openssh.com" #else #define DSA_HOSTKEYS "" #define DSA_PUBLIC_KEY_ALGORITHMS "" #endif #define HOSTKEYS "ssh-ed25519," \ EC_HOSTKEYS \ "rsa-sha2-512," \ "rsa-sha2-256," \ "ssh-rsa" \ DSA_HOSTKEYS #define PUBLIC_KEY_ALGORITHMS "ssh-ed25519-cert-v01@openssh.com," \ EC_PUBLIC_KEY_ALGORITHMS \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ "ssh-rsa-cert-v01@openssh.com" \ DSA_PUBLIC_KEY_ALGORITHMS "," \ HOSTKEYS #ifdef WITH_GEX #define GEX_SHA256 "diffie-hellman-group-exchange-sha256," #define GEX_SHA1 "diffie-hellman-group-exchange-sha1," #else #define GEX_SHA256 #define GEX_SHA1 #endif /* WITH_GEX */ #define CHACHA20 "chacha20-poly1305@openssh.com," #define KEY_EXCHANGE \ CURVE25519 \ ECDH \ "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \ GEX_SHA256 \ "diffie-hellman-group14-sha256," \ "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" #define KEY_EXCHANGE_SUPPORTED \ GEX_SHA1 \ KEY_EXCHANGE /* RFC 8308 */ #define KEX_EXTENSION_CLIENT "ext-info-c" /* Allowed algorithms in FIPS mode */ #define FIPS_ALLOWED_CIPHERS "aes256-gcm@openssh.com,"\ "aes256-ctr,"\ "aes256-cbc,"\ "aes128-gcm@openssh.com,"\ "aes128-ctr,"\ "aes128-cbc" #define FIPS_ALLOWED_HOSTKEYS EC_HOSTKEYS \ "rsa-sha2-512," \ "rsa-sha2-256" #define FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS EC_PUBLIC_KEY_ALGORITHMS \ "rsa-sha2-512-cert-v01@openssh.com," \ "rsa-sha2-256-cert-v01@openssh.com," \ FIPS_ALLOWED_HOSTKEYS #define FIPS_ALLOWED_KEX "ecdh-sha2-nistp256,"\ "ecdh-sha2-nistp384,"\ "ecdh-sha2-nistp521,"\ "diffie-hellman-group-exchange-sha256,"\ "diffie-hellman-group14-sha256,"\ "diffie-hellman-group16-sha512,"\ "diffie-hellman-group18-sha512" #define FIPS_ALLOWED_MACS "hmac-sha2-256-etm@openssh.com,"\ "hmac-sha1-etm@openssh.com,"\ "hmac-sha2-512-etm@openssh.com,"\ "hmac-sha2-256,"\ "hmac-sha1,"\ "hmac-sha2-512" /* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */ static const char *fips_methods[] = { FIPS_ALLOWED_KEX, FIPS_ALLOWED_PUBLIC_KEY_ALGORITHMS, FIPS_ALLOWED_CIPHERS, FIPS_ALLOWED_CIPHERS, FIPS_ALLOWED_MACS, FIPS_ALLOWED_MACS, ZLIB, ZLIB, "", "", NULL }; /* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */ static const char *default_methods[] = { KEY_EXCHANGE, PUBLIC_KEY_ALGORITHMS, AES BLOWFISH DES, AES BLOWFISH DES, "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", "none", "none", "", "", NULL }; /* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */ static const char *supported_methods[] = { KEY_EXCHANGE_SUPPORTED, PUBLIC_KEY_ALGORITHMS, CHACHA20 AES BLOWFISH DES_SUPPORTED, CHACHA20 AES BLOWFISH DES_SUPPORTED, "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", "hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,hmac-sha1-96-etm@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1,hmac-sha1-96", ZLIB, ZLIB, "", "", NULL }; /* descriptions of the key exchange packet */ static const char *ssh_kex_descriptions[] = { "kex algos", "server host key algo", "encryption client->server", "encryption server->client", "mac algo client->server", "mac algo server->client", "compression algo client->server", "compression algo server->client", "languages client->server", "languages server->client", NULL }; const char *ssh_kex_get_default_methods(uint32_t algo) { if (algo >= SSH_KEX_METHODS) { return NULL; } return default_methods[algo]; } const char *ssh_kex_get_supported_method(uint32_t algo) { if (algo >= SSH_KEX_METHODS) { return NULL; } return supported_methods[algo]; } const char *ssh_kex_get_description(uint32_t algo) { if (algo >= SSH_KEX_METHODS) { return NULL; } return ssh_kex_descriptions[algo]; } const char *ssh_kex_get_fips_methods(uint32_t algo) { if (algo >= SSH_KEX_METHODS) { return NULL; } return fips_methods[algo]; } /** * @internal * @brief returns whether the first client key exchange algorithm or * hostkey type matches its server counterpart * @returns whether the first client key exchange algorithm or hostkey type * matches its server counterpart */ static int cmp_first_kex_algo(const char *client_str, const char *server_str) { size_t client_kex_len; size_t server_kex_len; char *colon; int is_wrong = 1; colon = strchr(client_str, ','); if (colon == NULL) { client_kex_len = strlen(client_str); } else { client_kex_len = colon - client_str; } colon = strchr(server_str, ','); if (colon == NULL) { server_kex_len = strlen(server_str); } else { server_kex_len = colon - server_str; } if (client_kex_len != server_kex_len) { return is_wrong; } is_wrong = (strncmp(client_str, server_str, client_kex_len) != 0); return is_wrong; } SSH_PACKET_CALLBACK(ssh_packet_kexinit) { int i, ok; int server_kex = session->server; ssh_string str = NULL; char *strings[SSH_KEX_METHODS] = {0}; char *rsa_sig_ext = NULL; int rc = SSH_ERROR; size_t len; uint8_t first_kex_packet_follows = 0; uint32_t kexinit_reserved = 0; (void)type; (void)user; if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED) { SSH_LOG(SSH_LOG_INFO, "Initiating key re-exchange"); } else if (session->session_state != SSH_SESSION_STATE_INITIAL_KEX) { ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); goto error; } if (server_kex) { len = ssh_buffer_get_data(packet,session->next_crypto->client_kex.cookie, 16); if (len != 16) { ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); goto error; } ok = ssh_hashbufin_add_cookie(session, session->next_crypto->client_kex.cookie); if (ok < 0) { ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); goto error; } } else { len = ssh_buffer_get_data(packet,session->next_crypto->server_kex.cookie, 16); if (len != 16) { ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: no cookie in packet"); goto error; } ok = ssh_hashbufin_add_cookie(session, session->next_crypto->server_kex.cookie); if (ok < 0) { ssh_set_error(session, SSH_FATAL, "ssh_packet_kexinit: adding cookie failed"); goto error; } } for (i = 0; i < SSH_KEX_METHODS; i++) { str = ssh_buffer_get_ssh_string(packet); if (str == NULL) { goto error; } rc = ssh_buffer_add_ssh_string(session->in_hashbuf, str); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Error adding string in hash buffer"); goto error; } strings[i] = ssh_string_to_char(str); if (strings[i] == NULL) { ssh_set_error_oom(session); goto error; } SSH_STRING_FREE(str); str = NULL; } /* copy the server kex info into an array of strings */ if (server_kex) { for (i = 0; i < SSH_KEX_METHODS; i++) { session->next_crypto->client_kex.methods[i] = strings[i]; } } else { /* client */ for (i = 0; i < SSH_KEX_METHODS; i++) { session->next_crypto->server_kex.methods[i] = strings[i]; } } /* * Handle the two final fields for the KEXINIT message (RFC 4253 7.1): * * boolean first_kex_packet_follows * uint32 0 (reserved for future extension) * * Notably if clients set 'first_kex_packet_follows', it is expected * that its value is included when computing the session ID (see * 'make_sessionid'). */ if (server_kex) { rc = ssh_buffer_get_u8(packet, &first_kex_packet_follows); if (rc != 1) { goto error; } rc = ssh_buffer_add_u8(session->in_hashbuf, first_kex_packet_follows); if (rc < 0) { goto error; } rc = ssh_buffer_add_u32(session->in_hashbuf, kexinit_reserved); if (rc < 0) { goto error; } /* * If client sent a ext-info-c message in the kex list, it supports * RFC 8308 extension negotiation. */ ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX], KEX_EXTENSION_CLIENT); if (ok) { const char *hostkeys = NULL; /* The client supports extension negotiation */ session->extensions |= SSH_EXT_NEGOTIATION; /* * RFC 8332 Section 3.1: Use for Server Authentication * Check what algorithms were provided in the SSH_HOSTKEYS list * by the client and enable the respective extensions to provide * correct signature in the next packet if RSA is negotiated */ hostkeys = session->next_crypto->client_kex.methods[SSH_HOSTKEYS]; ok = ssh_match_group(hostkeys, "rsa-sha2-512"); if (ok) { /* Check if rsa-sha2-512 is allowed by config */ if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { char *is_allowed = ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], "rsa-sha2-512"); if (is_allowed != NULL) { session->extensions |= SSH_EXT_SIG_RSA_SHA512; } SAFE_FREE(is_allowed); } } ok = ssh_match_group(hostkeys, "rsa-sha2-256"); if (ok) { /* Check if rsa-sha2-256 is allowed by config */ if (session->opts.wanted_methods[SSH_HOSTKEYS] != NULL) { char *is_allowed = ssh_find_matching(session->opts.wanted_methods[SSH_HOSTKEYS], "rsa-sha2-256"); if (is_allowed != NULL) { session->extensions |= SSH_EXT_SIG_RSA_SHA256; } SAFE_FREE(is_allowed); } } /* * Ensure that the client preference is honored for the case * both signature types are enabled. */ if ((session->extensions & SSH_EXT_SIG_RSA_SHA256) && (session->extensions & SSH_EXT_SIG_RSA_SHA512)) { session->extensions &= ~(SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512); rsa_sig_ext = ssh_find_matching("rsa-sha2-512,rsa-sha2-256", session->next_crypto->client_kex.methods[SSH_HOSTKEYS]); if (rsa_sig_ext == NULL) { goto error; /* should never happen */ } else if (strcmp(rsa_sig_ext, "rsa-sha2-512") == 0) { session->extensions |= SSH_EXT_SIG_RSA_SHA512; } else if (strcmp(rsa_sig_ext, "rsa-sha2-256") == 0) { session->extensions |= SSH_EXT_SIG_RSA_SHA256; } else { SAFE_FREE(rsa_sig_ext); goto error; /* should never happen */ } SAFE_FREE(rsa_sig_ext); } SSH_LOG(SSH_LOG_DEBUG, "The client supports extension " "negotiation. Enabled signature algorithms: %s%s", session->extensions & SSH_EXT_SIG_RSA_SHA256 ? "SHA256" : "", session->extensions & SSH_EXT_SIG_RSA_SHA512 ? " SHA512" : ""); } /* * Remember whether 'first_kex_packet_follows' was set and the client * guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message * must be ignored. */ if (first_kex_packet_follows) { session->first_kex_follows_guess_wrong = cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_KEX], session->next_crypto->server_kex.methods[SSH_KEX]) || cmp_first_kex_algo(session->next_crypto->client_kex.methods[SSH_HOSTKEYS], session->next_crypto->server_kex.methods[SSH_HOSTKEYS]); } } /* Note, that his overwrites authenticated state in case of rekeying */ session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED; session->dh_handshake_state = DH_STATE_INIT; session->ssh_connection_callback(session); return SSH_PACKET_USED; error: SSH_STRING_FREE(str); for (i = 0; i < SSH_KEX_METHODS; i++) { if (server_kex) { session->next_crypto->client_kex.methods[i] = NULL; } else { /* client */ session->next_crypto->server_kex.methods[i] = NULL; } SAFE_FREE(strings[i]); } session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } void ssh_list_kex(struct ssh_kex_struct *kex) { int i = 0; #ifdef DEBUG_CRYPTO ssh_log_hexdump("session cookie", kex->cookie, 16); #endif for(i = 0; i < SSH_KEX_METHODS; i++) { if (kex->methods[i] == NULL) { continue; } SSH_LOG(SSH_LOG_FUNCTIONS, "%s: %s", ssh_kex_descriptions[i], kex->methods[i]); } } /** * @internal * * @brief selects the hostkey mechanisms to be chosen for the key exchange, * as some hostkey mechanisms may be present in known_hosts files. * * @returns a cstring containing a comma-separated list of hostkey methods. * NULL if no method matches */ char *ssh_client_select_hostkeys(ssh_session session) { const char *wanted = NULL; char *wanted_without_certs = NULL; char *known_hosts_algorithms = NULL; char *known_hosts_ordered = NULL; char *new_hostkeys = NULL; char *fips_hostkeys = NULL; wanted = session->opts.wanted_methods[SSH_HOSTKEYS]; if (wanted == NULL) { if (ssh_fips_mode()) { wanted = ssh_kex_get_fips_methods(SSH_HOSTKEYS); } else { wanted = ssh_kex_get_default_methods(SSH_HOSTKEYS); } } /* This removes the certificate types, unsupported for now */ wanted_without_certs = ssh_find_all_matching(HOSTKEYS, wanted); if (wanted_without_certs == NULL) { SSH_LOG(SSH_LOG_WARNING, "List of allowed host key algorithms is empty or contains only " "unsupported algorithms"); return NULL; } SSH_LOG(SSH_LOG_DEBUG, "Order of wanted host keys: \"%s\"", wanted_without_certs); known_hosts_algorithms = ssh_known_hosts_get_algorithms_names(session); if (known_hosts_algorithms == NULL) { SSH_LOG(SSH_LOG_DEBUG, "No key found in known_hosts; " "changing host key method to \"%s\"", wanted_without_certs); return wanted_without_certs; } SSH_LOG(SSH_LOG_DEBUG, "Algorithms found in known_hosts files: \"%s\"", known_hosts_algorithms); /* Filter and order the keys from known_hosts according to wanted list */ known_hosts_ordered = ssh_find_all_matching(known_hosts_algorithms, wanted_without_certs); SAFE_FREE(known_hosts_algorithms); if (known_hosts_ordered == NULL) { SSH_LOG(SSH_LOG_DEBUG, "No key found in known_hosts is allowed; " "changing host key method to \"%s\"", wanted_without_certs); return wanted_without_certs; } /* Append the other supported keys after the preferred ones * This function tolerates NULL pointers in parameters */ new_hostkeys = ssh_append_without_duplicates(known_hosts_ordered, wanted_without_certs); SAFE_FREE(known_hosts_ordered); SAFE_FREE(wanted_without_certs); if (new_hostkeys == NULL) { ssh_set_error_oom(session); return NULL; } if (ssh_fips_mode()) { /* Filter out algorithms not allowed in FIPS mode */ fips_hostkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, new_hostkeys); SAFE_FREE(new_hostkeys); if (fips_hostkeys == NULL) { SSH_LOG(SSH_LOG_WARNING, "None of the wanted host keys or keys in known_hosts files " "is allowed in FIPS mode."); return NULL; } new_hostkeys = fips_hostkeys; } SSH_LOG(SSH_LOG_DEBUG, "Changing host key method to \"%s\"", new_hostkeys); return new_hostkeys; } /** * @brief sets the key exchange parameters to be sent to the server, * in function of the options and available methods. */ int ssh_set_client_kex(ssh_session session) { struct ssh_kex_struct *client = &session->next_crypto->client_kex; const char *wanted; char *kex = NULL; char *kex_tmp = NULL; int ok; int i; size_t kex_len, len; ok = ssh_get_random(client->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return SSH_ERROR; } memset(client->methods, 0, SSH_KEX_METHODS * sizeof(char **)); /* Set the list of allowed algorithms in order of preference, if it hadn't * been set yet. */ for (i = 0; i < SSH_KEX_METHODS; i++) { if (i == SSH_HOSTKEYS) { /* Set the hostkeys in the following order: * - First: keys present in known_hosts files ordered by preference * - Next: other wanted algorithms ordered by preference */ client->methods[i] = ssh_client_select_hostkeys(session); if (client->methods[i] == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } continue; } wanted = session->opts.wanted_methods[i]; if (wanted == NULL) { if (ssh_fips_mode()) { wanted = fips_methods[i]; } else { wanted = default_methods[i]; } } client->methods[i] = strdup(wanted); if (client->methods[i] == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } } /* For rekeying, skip the extension negotiation */ if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { return SSH_OK; } /* Here we append ext-info-c to the list of kex algorithms */ kex = client->methods[SSH_KEX]; len = strlen(kex); if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) { /* Overflow */ return SSH_ERROR; } kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */ kex_tmp = realloc(kex, kex_len); if (kex_tmp == NULL) { free(kex); ssh_set_error_oom(session); return SSH_ERROR; } snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT); client->methods[SSH_KEX] = kex_tmp; return SSH_OK; } /** @brief Select the different methods on basis of client's and * server's kex messages, and watches out if a match is possible. */ int ssh_kex_select_methods (ssh_session session){ struct ssh_kex_struct *server = &session->next_crypto->server_kex; struct ssh_kex_struct *client = &session->next_crypto->client_kex; char *ext_start = NULL; int i; /* Here we should drop the ext-info-c from the list so we avoid matching. * it. We added it to the end, so we can just truncate the string here */ ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT); if (ext_start != NULL) { ext_start[0] = '\0'; } for (i = 0; i < SSH_KEX_METHODS; i++) { session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]); if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){ ssh_set_error(session,SSH_FATAL,"kex error : no match for method %s: server [%s], client [%s]", ssh_kex_descriptions[i],server->methods[i],client->methods[i]); return SSH_ERROR; } else if ((i >= SSH_LANG_C_S) && (session->next_crypto->kex_methods[i] == NULL)) { /* we can safely do that for languages */ session->next_crypto->kex_methods[i] = strdup(""); } } if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA256; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512; #ifdef WITH_GEX } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha1") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA1; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group-exchange-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_DH_GEX_SHA256; #endif /* WITH_GEX */ } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP384; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp521") == 0){ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP521; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256@libssh.org") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG; } else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "curve25519-sha256") == 0){ session->next_crypto->kex_type=SSH_KEX_CURVE25519_SHA256; } SSH_LOG(SSH_LOG_INFO, "Negotiated %s,%s,%s,%s,%s,%s,%s,%s,%s,%s", session->next_crypto->kex_methods[SSH_KEX], session->next_crypto->kex_methods[SSH_HOSTKEYS], session->next_crypto->kex_methods[SSH_CRYPT_C_S], session->next_crypto->kex_methods[SSH_CRYPT_S_C], session->next_crypto->kex_methods[SSH_MAC_C_S], session->next_crypto->kex_methods[SSH_MAC_S_C], session->next_crypto->kex_methods[SSH_COMP_C_S], session->next_crypto->kex_methods[SSH_COMP_S_C], session->next_crypto->kex_methods[SSH_LANG_C_S], session->next_crypto->kex_methods[SSH_LANG_S_C] ); return SSH_OK; } /* this function only sends the predefined set of kex methods */ int ssh_send_kex(ssh_session session, int server_kex) { struct ssh_kex_struct *kex = (server_kex ? &session->next_crypto->server_kex : &session->next_crypto->client_kex); ssh_string str = NULL; int i; int rc; rc = ssh_buffer_pack(session->out_buffer, "bP", SSH2_MSG_KEXINIT, 16, kex->cookie); /* cookie */ if (rc != SSH_OK) goto error; if (ssh_hashbufout_add_cookie(session) < 0) { goto error; } ssh_list_kex(kex); for (i = 0; i < SSH_KEX_METHODS; i++) { str = ssh_string_from_char(kex->methods[i]); if (str == NULL) { goto error; } if (ssh_buffer_add_ssh_string(session->out_hashbuf, str) < 0) { goto error; } if (ssh_buffer_add_ssh_string(session->out_buffer, str) < 0) { goto error; } SSH_STRING_FREE(str); str = NULL; } rc = ssh_buffer_pack(session->out_buffer, "bd", 0, 0); if (rc != SSH_OK) { goto error; } if (ssh_packet_send(session) == SSH_ERROR) { return -1; } SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_KEXINIT sent"); return 0; error: ssh_buffer_reinit(session->out_buffer); ssh_buffer_reinit(session->out_hashbuf); SSH_STRING_FREE(str); return -1; } /* * Key re-exchange (rekey) is triggered by this function. * It can not be called again after the rekey is initialized! */ int ssh_send_rekex(ssh_session session) { int rc; if (session->dh_handshake_state != DH_STATE_FINISHED) { /* Rekey/Key exchange is already in progress */ SSH_LOG(SSH_LOG_PACKET, "Attempting rekey in bad state"); return SSH_ERROR; } if (session->current_crypto == NULL) { /* No current crypto used -- can not exchange it */ SSH_LOG(SSH_LOG_PACKET, "No crypto to rekey"); return SSH_ERROR; } if (session->client) { rc = ssh_set_client_kex(session); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Failed to set client kex"); return rc; } } else { #ifdef WITH_SERVER rc = server_set_kex(session); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_PACKET, "Failed to set server kex"); return rc; } #else SSH_LOG(SSH_LOG_PACKET, "Invalid session state."); return SSH_ERROR; #endif /* WITH_SERVER */ } session->dh_handshake_state = DH_STATE_INIT; rc = ssh_send_kex(session, session->server); if (rc < 0) { SSH_LOG(SSH_LOG_PACKET, "Failed to send kex"); return rc; } /* Reset the handshake state */ session->dh_handshake_state = DH_STATE_INIT_SENT; return SSH_OK; } /* returns a copy of the provided list if everything is supported, * otherwise a new list of the supported algorithms */ char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list) { if (algo > SSH_LANG_S_C) { return NULL; } return ssh_find_all_matching(supported_methods[algo], list); } /** * @internal * * @brief Return a new allocated string containing only the FIPS allowed * algorithms from the list. * * @param[in] algo The type of the methods to filter * @param[in] list The list to be filtered * * @return A new allocated list containing only the FIPS allowed algorithms from * the list; NULL in case of error. */ char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list) { if (algo > SSH_LANG_S_C) { return NULL; } return ssh_find_all_matching(fips_methods[algo], list); } int ssh_make_sessionid(ssh_session session) { ssh_string num = NULL; ssh_buffer server_hash = NULL; ssh_buffer client_hash = NULL; ssh_buffer buf = NULL; ssh_string server_pubkey_blob = NULL; const_bignum client_pubkey, server_pubkey; #ifdef WITH_GEX const_bignum modulus, generator; #endif int rc = SSH_ERROR; buf = ssh_buffer_new(); if (buf == NULL) { return rc; } rc = ssh_buffer_pack(buf, "ss", session->clientbanner, session->serverbanner); if (rc == SSH_ERROR) { goto error; } if (session->client) { server_hash = session->in_hashbuf; client_hash = session->out_hashbuf; } else { server_hash = session->out_hashbuf; client_hash = session->in_hashbuf; } /* * Handle the two final fields for the KEXINIT message (RFC 4253 7.1): * * boolean first_kex_packet_follows * uint32 0 (reserved for future extension) */ rc = ssh_buffer_add_u8(server_hash, 0); if (rc < 0) { goto error; } rc = ssh_buffer_add_u32(server_hash, 0); if (rc < 0) { goto error; } /* These fields are handled for the server case in ssh_packet_kexinit. */ if (session->client) { rc = ssh_buffer_add_u8(client_hash, 0); if (rc < 0) { goto error; } rc = ssh_buffer_add_u32(client_hash, 0); if (rc < 0) { goto error; } } rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob); if (rc != SSH_OK) { goto error; } rc = ssh_buffer_pack(buf, "dPdPS", ssh_buffer_get_len(client_hash), ssh_buffer_get_len(client_hash), ssh_buffer_get(client_hash), ssh_buffer_get_len(server_hash), ssh_buffer_get_len(server_hash), ssh_buffer_get(server_hash), server_pubkey_blob); SSH_STRING_FREE(server_pubkey_blob); if(rc != SSH_OK){ goto error; } switch(session->next_crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: case SSH_KEX_DH_GROUP16_SHA512: case SSH_KEX_DH_GROUP18_SHA512: rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR, NULL, &client_pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, &server_pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_buffer_pack(buf, "BB", client_pubkey, server_pubkey); if (rc != SSH_OK) { goto error; } break; #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA1: case SSH_KEX_DH_GEX_SHA256: rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx, DH_CLIENT_KEYPAIR, NULL, &client_pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_dh_keypair_get_keys(session->next_crypto->dh_ctx, DH_SERVER_KEYPAIR, NULL, &server_pubkey); if (rc != SSH_OK) { goto error; } rc = ssh_dh_get_parameters(session->next_crypto->dh_ctx, &modulus, &generator); if (rc != SSH_OK) { goto error; } rc = ssh_buffer_pack(buf, "dddBBBB", session->next_crypto->dh_pmin, session->next_crypto->dh_pn, session->next_crypto->dh_pmax, modulus, generator, client_pubkey, server_pubkey); if (rc != SSH_OK) { goto error; } break; #endif /* WITH_GEX */ #ifdef HAVE_ECDH case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_ECDH_SHA2_NISTP384: case SSH_KEX_ECDH_SHA2_NISTP521: if (session->next_crypto->ecdh_client_pubkey == NULL || session->next_crypto->ecdh_server_pubkey == NULL) { SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing"); goto error; } rc = ssh_buffer_pack(buf, "SS", session->next_crypto->ecdh_client_pubkey, session->next_crypto->ecdh_server_pubkey); if (rc != SSH_OK) { goto error; } break; #endif #ifdef HAVE_CURVE25519 case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: rc = ssh_buffer_pack(buf, "dPdP", CURVE25519_PUBKEY_SIZE, (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_client_pubkey, CURVE25519_PUBKEY_SIZE, (size_t)CURVE25519_PUBKEY_SIZE, session->next_crypto->curve25519_server_pubkey); if (rc != SSH_OK) { goto error; } break; #endif } rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret); if (rc != SSH_OK) { goto error; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf)); #endif switch (session->next_crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA1: #endif /* WITH_GEX */ session->next_crypto->digest_len = SHA_DIGEST_LENGTH; session->next_crypto->digest_type = SSH_KDF_SHA1; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); goto error; } sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf), session->next_crypto->secret_hash); break; case SSH_KEX_DH_GROUP14_SHA256: case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA256: #endif /* WITH_GEX */ session->next_crypto->digest_len = SHA256_DIGEST_LENGTH; session->next_crypto->digest_type = SSH_KDF_SHA256; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); goto error; } sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf), session->next_crypto->secret_hash); break; case SSH_KEX_ECDH_SHA2_NISTP384: session->next_crypto->digest_len = SHA384_DIGEST_LENGTH; session->next_crypto->digest_type = SSH_KDF_SHA384; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); goto error; } sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf), session->next_crypto->secret_hash); break; case SSH_KEX_DH_GROUP16_SHA512: case SSH_KEX_DH_GROUP18_SHA512: case SSH_KEX_ECDH_SHA2_NISTP521: session->next_crypto->digest_len = SHA512_DIGEST_LENGTH; session->next_crypto->digest_type = SSH_KDF_SHA512; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); goto error; } sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf), session->next_crypto->secret_hash); break; } /* During the first kex, secret hash and session ID are equal. However, after * a key re-exchange, a new secret hash is calculated. This hash will not replace * but complement existing session id. */ if (!session->next_crypto->session_id) { session->next_crypto->session_id = malloc(session->next_crypto->digest_len); if (session->next_crypto->session_id == NULL) { ssh_set_error_oom(session); goto error; } memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash, session->next_crypto->digest_len); } #ifdef DEBUG_CRYPTO printf("Session hash: \n"); ssh_log_hexdump("secret hash", session->next_crypto->secret_hash, session->next_crypto->digest_len); ssh_log_hexdump("session id", session->next_crypto->session_id, session->next_crypto->digest_len); #endif rc = SSH_OK; error: SSH_BUFFER_FREE(buf); SSH_BUFFER_FREE(client_hash); SSH_BUFFER_FREE(server_hash); session->in_hashbuf = NULL; session->out_hashbuf = NULL; SSH_STRING_FREE(num); return rc; } int ssh_hashbufout_add_cookie(ssh_session session) { int rc; session->out_hashbuf = ssh_buffer_new(); if (session->out_hashbuf == NULL) { return -1; } rc = ssh_buffer_allocate_size(session->out_hashbuf, sizeof(uint8_t) + 16); if (rc < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } if (ssh_buffer_add_u8(session->out_hashbuf, 20) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } if (session->server) { if (ssh_buffer_add_data(session->out_hashbuf, session->next_crypto->server_kex.cookie, 16) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } } else { if (ssh_buffer_add_data(session->out_hashbuf, session->next_crypto->client_kex.cookie, 16) < 0) { ssh_buffer_reinit(session->out_hashbuf); return -1; } } return 0; } int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie) { int rc; session->in_hashbuf = ssh_buffer_new(); if (session->in_hashbuf == NULL) { return -1; } rc = ssh_buffer_allocate_size(session->in_hashbuf, sizeof(uint8_t) + 20 + 16); if (rc < 0) { ssh_buffer_reinit(session->in_hashbuf); return -1; } if (ssh_buffer_add_u8(session->in_hashbuf, 20) < 0) { ssh_buffer_reinit(session->in_hashbuf); return -1; } if (ssh_buffer_add_data(session->in_hashbuf,cookie, 16) < 0) { ssh_buffer_reinit(session->in_hashbuf); return -1; } return 0; } int ssh_generate_session_keys(ssh_session session) { ssh_string k_string = NULL; struct ssh_crypto_struct *crypto = session->next_crypto; unsigned char *key = NULL; unsigned char *IV_cli_to_srv = NULL; unsigned char *IV_srv_to_cli = NULL; unsigned char *enckey_cli_to_srv = NULL; unsigned char *enckey_srv_to_cli = NULL; unsigned char *intkey_cli_to_srv = NULL; unsigned char *intkey_srv_to_cli = NULL; size_t key_len = 0; size_t IV_len = 0; size_t enckey_cli_to_srv_len = 0; size_t enckey_srv_to_cli_len = 0; size_t intkey_cli_to_srv_len = 0; size_t intkey_srv_to_cli_len = 0; int rc = -1; k_string = ssh_make_bignum_string(crypto->shared_secret); if (k_string == NULL) { ssh_set_error_oom(session); goto error; } /* See RFC4251 Section 5 for the definition of mpint which is the * encoding we need to use for key in the SSH KDF */ key = (unsigned char *)k_string; key_len = ssh_string_len(k_string) + 4; IV_len = crypto->digest_len; if (session->client) { enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->in_cipher->keysize / 8; intkey_cli_to_srv_len = hmac_key_len(crypto->out_hmac); intkey_srv_to_cli_len = hmac_key_len(crypto->in_hmac); } else { enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8; enckey_srv_to_cli_len = crypto->out_cipher->keysize / 8; intkey_cli_to_srv_len = hmac_key_len(crypto->in_hmac); intkey_srv_to_cli_len = hmac_key_len(crypto->out_hmac); } IV_cli_to_srv = malloc(IV_len); IV_srv_to_cli = malloc(IV_len); enckey_cli_to_srv = malloc(enckey_cli_to_srv_len); enckey_srv_to_cli = malloc(enckey_srv_to_cli_len); intkey_cli_to_srv = malloc(intkey_cli_to_srv_len); intkey_srv_to_cli = malloc(intkey_srv_to_cli_len); if (IV_cli_to_srv == NULL || IV_srv_to_cli == NULL || enckey_cli_to_srv == NULL || enckey_srv_to_cli == NULL || intkey_cli_to_srv == NULL || intkey_srv_to_cli == NULL) { ssh_set_error_oom(session); goto error; } /* IV */ rc = ssh_kdf(crypto, key, key_len, 'A', IV_cli_to_srv, IV_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'B', IV_srv_to_cli, IV_len); if (rc < 0) { goto error; } /* Encryption Key */ rc = ssh_kdf(crypto, key, key_len, 'C', enckey_cli_to_srv, enckey_cli_to_srv_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'D', enckey_srv_to_cli, enckey_srv_to_cli_len); if (rc < 0) { goto error; } /* Integrity Key */ rc = ssh_kdf(crypto, key, key_len, 'E', intkey_cli_to_srv, intkey_cli_to_srv_len); if (rc < 0) { goto error; } rc = ssh_kdf(crypto, key, key_len, 'F', intkey_srv_to_cli, intkey_srv_to_cli_len); if (rc < 0) { goto error; } if (session->client) { crypto->encryptIV = IV_cli_to_srv; crypto->decryptIV = IV_srv_to_cli; crypto->encryptkey = enckey_cli_to_srv; crypto->decryptkey = enckey_srv_to_cli; crypto->encryptMAC = intkey_cli_to_srv; crypto->decryptMAC = intkey_srv_to_cli; } else { crypto->encryptIV = IV_srv_to_cli; crypto->decryptIV = IV_cli_to_srv; crypto->encryptkey = enckey_srv_to_cli; crypto->decryptkey = enckey_cli_to_srv; crypto->encryptMAC = intkey_srv_to_cli; crypto->decryptMAC = intkey_cli_to_srv; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("Client to Server IV", IV_cli_to_srv, IV_len); ssh_log_hexdump("Server to Client IV", IV_srv_to_cli, IV_len); ssh_log_hexdump("Client to Server Encryption Key", enckey_cli_to_srv, enckey_cli_to_srv_len); ssh_log_hexdump("Server to Client Encryption Key", enckey_srv_to_cli, enckey_srv_to_cli_len); ssh_log_hexdump("Client to Server Integrity Key", intkey_cli_to_srv, intkey_cli_to_srv_len); ssh_log_hexdump("Server to Client Integrity Key", intkey_srv_to_cli, intkey_srv_to_cli_len); #endif rc = 0; error: ssh_string_burn(k_string); SSH_STRING_FREE(k_string); if (rc != 0) { free(IV_cli_to_srv); free(IV_srv_to_cli); free(enckey_cli_to_srv); free(enckey_srv_to_cli); free(intkey_cli_to_srv); free(intkey_srv_to_cli); } return rc; } ================================================ FILE: src/libssh/src/known_hosts.c ================================================ /* * keyfiles.c - private and public key handling for authentication. * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * Copyright (c) 2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/buffer.h" #include "libssh/misc.h" #include "libssh/dh.h" #include "libssh/pki.h" #include "libssh/options.h" #include "libssh/knownhosts.h" /*todo: remove this include */ #include "libssh/string.h" #include "libssh/token.h" #ifndef _WIN32 # include # include #endif /** * @addtogroup libssh_session * * @{ */ /** * @internal * * @brief Return one line of known host file. * * This will return a token array containing (host|ip), keytype and key. * * @param[out] file A pointer to the known host file. Could be pointing to * NULL at start. * * @param[in] filename The file name of the known host file. * * @param[out] found_type A pointer to a string to be set with the found key * type. * * @returns The found_type type of key (ie "dsa","ssh-rsa"). Don't * free that value. NULL if no match was found or the file * was not found. */ static struct ssh_tokens_st *ssh_get_knownhost_line(FILE **file, const char *filename, const char **found_type) { char buffer[4096] = {0}; char *ptr; struct ssh_tokens_st *tokens; if (*file == NULL) { *file = fopen(filename,"r"); if (*file == NULL) { return NULL; } } while (fgets(buffer, sizeof(buffer), *file)) { ptr = strchr(buffer, '\n'); if (ptr) { *ptr = '\0'; } ptr = strchr(buffer,'\r'); if (ptr) { *ptr = '\0'; } if (buffer[0] == '\0' || buffer[0] == '#') { continue; /* skip empty lines */ } tokens = ssh_tokenize(buffer, ' '); if (tokens == NULL) { fclose(*file); *file = NULL; return NULL; } if (tokens->tokens[0] == NULL || tokens->tokens[1] == NULL || tokens->tokens[2] == NULL) { /* it should have at least 3 tokens */ ssh_tokens_free(tokens); continue; } *found_type = tokens->tokens[1]; return tokens; } fclose(*file); *file = NULL; /* we did not find anything, end of file*/ return NULL; } /** * @internal * * @brief Check the public key in the known host line matches the public key of * the currently connected server. * * @param[in] session The SSH session to use. * * @param[in] tokens A list of tokens in the known_hosts line. * * @returns 1 if the key matches, 0 if the key doesn't match and -1 * on error. */ static int check_public_key(ssh_session session, char **tokens) { ssh_string pubkey_blob = NULL; ssh_buffer pubkey_buffer; char *pubkey_64; int rc; /* ssh-dss or ssh-rsa */ pubkey_64 = tokens[2]; pubkey_buffer = base64_to_bin(pubkey_64); if (pubkey_buffer == NULL) { ssh_set_error(session, SSH_FATAL, "Verifying that server is a known host: base64 error"); return -1; } rc = ssh_dh_get_current_server_publickey_blob(session, &pubkey_blob); if (rc != 0) { ssh_buffer_free(pubkey_buffer); return -1; } if (ssh_buffer_get_len(pubkey_buffer) != ssh_string_len(pubkey_blob)) { ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 0; } /* now test that they are identical */ if (memcmp(ssh_buffer_get(pubkey_buffer), ssh_string_data(pubkey_blob), ssh_buffer_get_len(pubkey_buffer)) != 0) { ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 0; } ssh_string_free(pubkey_blob); ssh_buffer_free(pubkey_buffer); return 1; } /** * @internal * @brief Check if a hostname matches a openssh-style hashed known host. * * @param[in] host The host to check. * * @param[in] hashed The hashed value. * * @returns 1 if it matches, 0 otherwise. */ static int match_hashed_host(const char *host, const char *sourcehash) { /* Openssh hash structure : * |1|base64 encoded salt|base64 encoded hash * hash is produced that way : * hash := HMAC_SHA1(key=salt,data=host) */ unsigned char buffer[256] = {0}; ssh_buffer salt; ssh_buffer hash; HMACCTX mac; char *source; char *b64hash; int match; unsigned int size; if (strncmp(sourcehash, "|1|", 3) != 0) { return 0; } source = strdup(sourcehash + 3); if (source == NULL) { return 0; } b64hash = strchr(source, '|'); if (b64hash == NULL) { /* Invalid hash */ SAFE_FREE(source); return 0; } *b64hash = '\0'; b64hash++; salt = base64_to_bin(source); if (salt == NULL) { SAFE_FREE(source); return 0; } hash = base64_to_bin(b64hash); SAFE_FREE(source); if (hash == NULL) { ssh_buffer_free(salt); return 0; } mac = hmac_init(ssh_buffer_get(salt), ssh_buffer_get_len(salt), SSH_HMAC_SHA1); if (mac == NULL) { ssh_buffer_free(salt); ssh_buffer_free(hash); return 0; } size = sizeof(buffer); hmac_update(mac, host, strlen(host)); hmac_final(mac, buffer, &size, SSH_HMAC_SHA1); if (size == ssh_buffer_get_len(hash) && memcmp(buffer, ssh_buffer_get(hash), size) == 0) { match = 1; } else { match = 0; } ssh_buffer_free(salt); ssh_buffer_free(hash); SSH_LOG(SSH_LOG_PACKET, "Matching a hashed host: %s match=%d", host, match); return match; } /* How it's working : * 1- we open the known host file and bitch if it doesn't exist * 2- we need to examine each line of the file, until going on state SSH_SERVER_KNOWN_OK: * - there's a match. if the key is good, state is SSH_SERVER_KNOWN_OK, * else it's SSH_SERVER_KNOWN_CHANGED (or SSH_SERVER_FOUND_OTHER) * - there's no match : no change */ /** * @brief This function is deprecated * * @deprecated Please use ssh_session_is_known_server() * @see ssh_session_is_known_server() */ int ssh_is_server_known(ssh_session session) { FILE *file = NULL; char *host; char *hostport; const char *type; int match; int i = 0; char *files[3]; struct ssh_tokens_st *tokens; int ret = SSH_SERVER_NOT_KNOWN; if (session->opts.knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't find a known_hosts file"); return SSH_SERVER_FILE_NOT_FOUND; } } if (session->opts.host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't verify host in known hosts if the hostname isn't known"); return SSH_SERVER_ERROR; } if (session->current_crypto == NULL){ ssh_set_error(session, SSH_FATAL, "ssh_is_host_known called without cryptographic context"); return SSH_SERVER_ERROR; } host = ssh_lowercase(session->opts.host); hostport = ssh_hostport(host, session->opts.port > 0 ? session->opts.port : 22); if (host == NULL || hostport == NULL) { ssh_set_error_oom(session); SAFE_FREE(host); SAFE_FREE(hostport); return SSH_SERVER_ERROR; } /* Set the list of known hosts files */ i = 0; if (session->opts.global_knownhosts != NULL){ files[i++] = session->opts.global_knownhosts; } files[i++] = session->opts.knownhosts; files[i] = NULL; i = 0; do { tokens = ssh_get_knownhost_line(&file, files[i], &type); /* End of file, return the current state or use next file */ if (tokens == NULL) { ++i; if(files[i] == NULL) break; else continue; } match = match_hashed_host(host, tokens->tokens[0]); if (match == 0){ match = match_hostname(hostport, tokens->tokens[0], strlen(tokens->tokens[0])); } if (match == 0) { match = match_hostname(host, tokens->tokens[0], strlen(tokens->tokens[0])); } if (match == 0) { match = match_hashed_host(hostport, tokens->tokens[0]); } if (match) { ssh_key pubkey = ssh_dh_get_current_server_publickey(session); const char *pubkey_type = ssh_key_type_to_char(ssh_key_type(pubkey)); /* We got a match. Now check the key type */ if (strcmp(pubkey_type, type) != 0) { SSH_LOG(SSH_LOG_PACKET, "ssh_is_server_known: server type [%s] doesn't match the " "type [%s] in known_hosts file", pubkey_type, type); /* Different type. We don't override the known_changed error which is * more important */ if (ret != SSH_SERVER_KNOWN_CHANGED) ret = SSH_SERVER_FOUND_OTHER; ssh_tokens_free(tokens); continue; } /* so we know the key type is good. We may get a good key or a bad key. */ match = check_public_key(session, tokens->tokens); ssh_tokens_free(tokens); if (match < 0) { ret = SSH_SERVER_ERROR; break; } else if (match == 1) { ret = SSH_SERVER_KNOWN_OK; break; } else if(match == 0) { /* We override the status with the wrong key state */ ret = SSH_SERVER_KNOWN_CHANGED; } } else { ssh_tokens_free(tokens); } } while (1); if ((ret == SSH_SERVER_NOT_KNOWN) && (session->opts.StrictHostKeyChecking == 0)) { int rv = ssh_session_update_known_hosts(session); if (rv != SSH_OK) { ret = SSH_SERVER_ERROR; } else { ret = SSH_SERVER_KNOWN_OK; } } SAFE_FREE(host); SAFE_FREE(hostport); if (file != NULL) { fclose(file); } /* Return the current state at end of file */ return ret; } /** * @deprecated Please use ssh_session_export_known_hosts_entry() * @brief This function is deprecated. */ char * ssh_dump_knownhost(ssh_session session) { ssh_key server_pubkey = NULL; char *host; char *hostport; size_t len = 4096; char *buffer; char *b64_key; int rc; if (session->opts.host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't write host in known hosts if the hostname isn't known"); return NULL; } host = ssh_lowercase(session->opts.host); /* If using a nonstandard port, save the host in the [host]:port format */ if (session->opts.port > 0 && session->opts.port != 22) { hostport = ssh_hostport(host, session->opts.port); SAFE_FREE(host); if (hostport == NULL) { return NULL; } host = hostport; hostport = NULL; } if (session->current_crypto==NULL) { ssh_set_error(session, SSH_FATAL, "No current crypto context"); SAFE_FREE(host); return NULL; } server_pubkey = ssh_dh_get_current_server_publickey(session); if (server_pubkey == NULL){ ssh_set_error(session, SSH_FATAL, "No public key present"); SAFE_FREE(host); return NULL; } buffer = calloc (1, 4096); if (!buffer) { SAFE_FREE(host); return NULL; } rc = ssh_pki_export_pubkey_base64(server_pubkey, &b64_key); if (rc < 0) { SAFE_FREE(buffer); SAFE_FREE(host); return NULL; } snprintf(buffer, len, "%s %s %s\n", host, server_pubkey->type_c, b64_key); SAFE_FREE(host); SAFE_FREE(b64_key); return buffer; } /** * @deprecated Please use ssh_session_update_known_hosts() * @brief This function is deprecated */ int ssh_write_knownhost(ssh_session session) { FILE *file; char *buffer = NULL; char *dir; int rc; if (session->opts.knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); return SSH_ERROR; } } errno = 0; file = fopen(session->opts.knownhosts, "a"); if (file == NULL) { if (errno == ENOENT) { dir = ssh_dirname(session->opts.knownhosts); if (dir == NULL) { ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); return SSH_ERROR; } rc = ssh_mkdirs(dir, 0700); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot create %s directory: %s", dir, strerror(errno)); SAFE_FREE(dir); return SSH_ERROR; } SAFE_FREE(dir); errno = 0; file = fopen(session->opts.knownhosts, "a"); if (file == NULL) { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s" " for appending: %s", session->opts.knownhosts, strerror(errno)); return SSH_ERROR; } } else { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s for appending: %s", session->opts.knownhosts, strerror(errno)); return SSH_ERROR; } } rc = ssh_session_export_known_hosts_entry(session, &buffer); if (rc != SSH_OK) { fclose(file); return SSH_ERROR; } if (fwrite(buffer, strlen(buffer), 1, file) != 1 || ferror(file)) { SAFE_FREE(buffer); fclose(file); return -1; } SAFE_FREE(buffer); fclose(file); return 0; } #define KNOWNHOSTS_MAXTYPES 10 /** @} */ ================================================ FILE: src/libssh/src/knownhosts.c ================================================ /* * known_hosts: Host and public key verification. * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * Copyright (c) 2009-2017 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/dh.h" #include "libssh/session.h" #include "libssh/options.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/dh.h" #include "libssh/knownhosts.h" #include "libssh/token.h" /** * @addtogroup libssh_session * * @{ */ static int hash_hostname(const char *name, unsigned char *salt, unsigned int salt_size, unsigned char **hash, unsigned int *hash_size) { HMACCTX mac_ctx; mac_ctx = hmac_init(salt, salt_size, SSH_HMAC_SHA1); if (mac_ctx == NULL) { return SSH_ERROR; } hmac_update(mac_ctx, name, strlen(name)); hmac_final(mac_ctx, *hash, hash_size, SSH_HMAC_SHA1); return SSH_OK; } static int match_hashed_hostname(const char *host, const char *hashed_host) { char *hashed; char *b64_hash; ssh_buffer salt = NULL; ssh_buffer hash = NULL; unsigned char hashed_buf[256] = {0}; unsigned char *hashed_buf_ptr = hashed_buf; unsigned int hashed_buf_size = sizeof(hashed_buf); int cmp; int rc; int match = 0; cmp = strncmp(hashed_host, "|1|", 3); if (cmp != 0) { return 0; } hashed = strdup(hashed_host + 3); if (hashed == NULL) { return 0; } b64_hash = strchr(hashed, '|'); if (b64_hash == NULL) { goto error; } *b64_hash = '\0'; b64_hash++; salt = base64_to_bin(hashed); if (salt == NULL) { goto error; } hash = base64_to_bin(b64_hash); if (hash == NULL) { goto error; } rc = hash_hostname(host, ssh_buffer_get(salt), ssh_buffer_get_len(salt), &hashed_buf_ptr, &hashed_buf_size); if (rc != SSH_OK) { goto error; } if (hashed_buf_size != ssh_buffer_get_len(hash)) { goto error; } cmp = memcmp(hashed_buf, ssh_buffer_get(hash), hashed_buf_size); if (cmp == 0) { match = 1; } error: free(hashed); SSH_BUFFER_FREE(salt); SSH_BUFFER_FREE(hash); return match; } /** * @brief Free an allocated ssh_knownhosts_entry. * * Use SSH_KNOWNHOSTS_ENTRY_FREE() to set the pointer to NULL. * * @param[in] entry The entry to free. */ void ssh_knownhosts_entry_free(struct ssh_knownhosts_entry *entry) { if (entry == NULL) { return; } SAFE_FREE(entry->hostname); SAFE_FREE(entry->unparsed); ssh_key_free(entry->publickey); SAFE_FREE(entry->comment); SAFE_FREE(entry); } static int known_hosts_read_line(FILE *fp, char *buf, size_t buf_size, size_t *buf_len, size_t *lineno) { while (fgets(buf, buf_size, fp) != NULL) { size_t len; if (buf[0] == '\0') { continue; } *lineno += 1; len = strlen(buf); if (buf_len != NULL) { *buf_len = len; } if (buf[len - 1] == '\n' || feof(fp)) { return 0; } else { errno = E2BIG; return -1; } } return -1; } static int ssh_known_hosts_entries_compare(struct ssh_knownhosts_entry *k1, struct ssh_knownhosts_entry *k2) { int cmp; if (k1 == NULL || k2 == NULL) { return 1; } cmp = strcmp(k1->hostname, k2->hostname); if (cmp != 0) { return cmp; } cmp = ssh_key_cmp(k1->publickey, k2->publickey, SSH_KEY_CMP_PUBLIC); if (cmp != 0) { return cmp; } return 0; } /* This method reads the known_hosts file referenced by the path * in filename argument, and entries matching the match argument * will be added to the list in entries argument. * If the entries list is NULL, it will allocate a new list. Caller * is responsible to free it even if an error occurs. */ static int ssh_known_hosts_read_entries(const char *match, const char *filename, struct ssh_list **entries) { char line[8192]; size_t lineno = 0; size_t len = 0; FILE *fp; int rc; fp = fopen(filename, "r"); if (fp == NULL) { SSH_LOG(SSH_LOG_WARN, "Failed to open the known_hosts file '%s': %s", filename, strerror(errno)); /* The missing file is not an error here */ return SSH_OK; } if (*entries == NULL) { *entries = ssh_list_new(); if (*entries == NULL) { fclose(fp); return SSH_ERROR; } } for (rc = known_hosts_read_line(fp, line, sizeof(line), &len, &lineno); rc == 0; rc = known_hosts_read_line(fp, line, sizeof(line), &len, &lineno)) { struct ssh_knownhosts_entry *entry = NULL; struct ssh_iterator *it = NULL; char *p = NULL; if (line[len] != '\n') { len = strcspn(line, "\n"); } line[len] = '\0'; /* Skip leading spaces */ for (p = line; isspace((int)p[0]); p++); /* Skip comments and empty lines */ if (p[0] == '\0' || p[0] == '#') { continue; } /* Skip lines starting with markers (@cert-authority, @revoked): * we do not completely support them anyway */ if (p[0] == '@') { continue; } rc = ssh_known_hosts_parse_line(match, line, &entry); if (rc == SSH_AGAIN) { continue; } else if (rc != SSH_OK) { goto error; } /* Check for duplicates */ for (it = ssh_list_get_iterator(*entries); it != NULL; it = it->next) { struct ssh_knownhosts_entry *entry2; int cmp; entry2 = ssh_iterator_value(struct ssh_knownhosts_entry *, it); cmp = ssh_known_hosts_entries_compare(entry, entry2); if (cmp == 0) { ssh_knownhosts_entry_free(entry); entry = NULL; break; } } if (entry != NULL) { ssh_list_append(*entries, entry); } } fclose(fp); return SSH_OK; error: fclose(fp); return SSH_ERROR; } static char *ssh_session_get_host_port(ssh_session session) { char *host_port; char *host; if (session->opts.host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't verify server in known hosts if the host we " "should connect to has not been set"); return NULL; } host = ssh_lowercase(session->opts.host); if (host == NULL) { ssh_set_error_oom(session); return NULL; } if (session->opts.port == 0 || session->opts.port == 22) { host_port = host; } else { host_port = ssh_hostport(host, session->opts.port); SAFE_FREE(host); if (host_port == NULL) { ssh_set_error_oom(session); return NULL; } } return host_port; } /** * @internal * @brief Check which host keys should be preferred for the session. * * This checks the known_hosts file to find out which algorithms should be * preferred for the connection we are going to establish. * * @param[in] session The ssh session to use. * * @return A list of supported key types, NULL on error. */ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session) { struct ssh_list *entry_list = NULL; struct ssh_iterator *it = NULL; char *host_port = NULL; size_t count; struct ssh_list *list = NULL; int list_error = 0; int rc; if (session->opts.knownhosts == NULL || session->opts.global_knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't find a known_hosts file"); return NULL; } } host_port = ssh_session_get_host_port(session); if (host_port == NULL) { return NULL; } list = ssh_list_new(); if (list == NULL) { SAFE_FREE(host_port); return NULL; } rc = ssh_known_hosts_read_entries(host_port, session->opts.knownhosts, &entry_list); if (rc != 0) { ssh_list_free(entry_list); ssh_list_free(list); return NULL; } rc = ssh_known_hosts_read_entries(host_port, session->opts.global_knownhosts, &entry_list); SAFE_FREE(host_port); if (rc != 0) { ssh_list_free(entry_list); ssh_list_free(list); return NULL; } if (entry_list == NULL) { ssh_list_free(list); return NULL; } count = ssh_list_count(entry_list); if (count == 0) { ssh_list_free(list); ssh_list_free(entry_list); return NULL; } for (it = ssh_list_get_iterator(entry_list); it != NULL; it = ssh_list_get_iterator(entry_list)) { struct ssh_iterator *it2 = NULL; struct ssh_knownhosts_entry *entry = NULL; const char *algo = NULL; bool present = false; entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); algo = entry->publickey->type_c; /* Check for duplicates */ for (it2 = ssh_list_get_iterator(list); it2 != NULL; it2 = it2->next) { char *alg2 = ssh_iterator_value(char *, it2); int cmp = strcmp(alg2, algo); if (cmp == 0) { present = true; break; } } /* Add to the new list only if it is unique */ if (!present) { rc = ssh_list_append(list, algo); if (rc != SSH_OK) { list_error = 1; } } ssh_knownhosts_entry_free(entry); ssh_list_remove(entry_list, it); } ssh_list_free(entry_list); if (list_error) { goto error; } return list; error: ssh_list_free(list); return NULL; } /** * @internal * * @brief Returns a static string containing a list of the signature types the * given key type can generate. * * @returns A static cstring containing the signature types the key is able to * generate separated by commas; NULL in case of error */ static const char *ssh_known_host_sigs_from_hostkey_type(enum ssh_keytypes_e type) { switch (type) { case SSH_KEYTYPE_RSA: return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; case SSH_KEYTYPE_ED25519: return "ssh-ed25519"; #ifdef HAVE_DSA case SSH_KEYTYPE_DSS: return "ssh-dss"; #endif #ifdef HAVE_ECDH case SSH_KEYTYPE_ECDSA_P256: return "ecdsa-sha2-nistp256"; case SSH_KEYTYPE_ECDSA_P384: return "ecdsa-sha2-nistp384"; case SSH_KEYTYPE_ECDSA_P521: return "ecdsa-sha2-nistp521"; #endif case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "The given type %d is not a base private key type " "or is unsupported", type); return NULL; } } /** * @internal * @brief Get the host keys algorithms identifiers from the known_hosts files * * This expands the signatures types that can be generated from the keys types * present in the known_hosts files * * @param[in] session The ssh session to use. * * @return A newly allocated cstring containing a list of signature algorithms * that can be generated by the host using the keys listed in the known_hosts * files, NULL on error. */ char *ssh_known_hosts_get_algorithms_names(ssh_session session) { char methods_buffer[256 + 1] = {0}; struct ssh_list *entry_list = NULL; struct ssh_iterator *it = NULL; char *host_port = NULL; size_t count; bool needcomma = false; char *names; int rc; if (session->opts.knownhosts == NULL || session->opts.global_knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't find a known_hosts file"); return NULL; } } host_port = ssh_session_get_host_port(session); if (host_port == NULL) { return NULL; } rc = ssh_known_hosts_read_entries(host_port, session->opts.knownhosts, &entry_list); if (rc != 0) { SAFE_FREE(host_port); ssh_list_free(entry_list); return NULL; } rc = ssh_known_hosts_read_entries(host_port, session->opts.global_knownhosts, &entry_list); SAFE_FREE(host_port); if (rc != 0) { ssh_list_free(entry_list); return NULL; } if (entry_list == NULL) { return NULL; } count = ssh_list_count(entry_list); if (count == 0) { ssh_list_free(entry_list); return NULL; } for (it = ssh_list_get_iterator(entry_list); it != NULL; it = ssh_list_get_iterator(entry_list)) { struct ssh_knownhosts_entry *entry = NULL; const char *algo = NULL; entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); algo = ssh_known_host_sigs_from_hostkey_type(entry->publickey->type); if (algo == NULL) { continue; } if (needcomma) { strncat(methods_buffer, ",", sizeof(methods_buffer) - strlen(methods_buffer) - 1); } strncat(methods_buffer, algo, sizeof(methods_buffer) - strlen(methods_buffer) - 1); needcomma = true; ssh_knownhosts_entry_free(entry); ssh_list_remove(entry_list, it); } ssh_list_free(entry_list); names = ssh_remove_duplicates(methods_buffer); return names; } /** * @brief Parse a line from a known_hosts entry into a structure * * This parses an known_hosts entry into a structure with the key in a libssh * consumeable form. You can use the PKI key function to further work with it. * * @param[in] hostname The hostname to match the line to * * @param[in] line The line to compare and parse if we have a hostname * match. * * @param[in] entry A pointer to store the the allocated known_hosts * entry structure. The user needs to free the memory * using SSH_KNOWNHOSTS_ENTRY_FREE(). * * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_known_hosts_parse_line(const char *hostname, const char *line, struct ssh_knownhosts_entry **entry) { struct ssh_knownhosts_entry *e = NULL; char *known_host = NULL; char *p; enum ssh_keytypes_e key_type; int match = 0; int rc = SSH_OK; known_host = strdup(line); if (known_host == NULL) { return SSH_ERROR; } /* match pattern for hostname or hashed hostname */ p = strtok(known_host, " "); if (p == NULL ) { free(known_host); return SSH_ERROR; } e = calloc(1, sizeof(struct ssh_knownhosts_entry)); if (e == NULL) { free(known_host); return SSH_ERROR; } if (hostname != NULL) { char *host_port = NULL; char *q = NULL; /* Hashed */ if (p[0] == '|') { match = match_hashed_hostname(hostname, p); } for (q = strtok(p, ","); q != NULL; q = strtok(NULL, ",")) { int cmp; if (q[0] == '[' && hostname[0] != '[') { /* Corner case: We have standard port so we do not have * hostname in square braces. But the patern is enclosed * in braces with, possibly standard or wildcard, port. * We need to test against [host]:port pair here. */ if (host_port == NULL) { host_port = ssh_hostport(hostname, 22); if (host_port == NULL) { rc = SSH_ERROR; goto out; } } cmp = match_hostname(host_port, q, strlen(q)); } else { cmp = match_hostname(hostname, q, strlen(q)); } if (cmp == 1) { match = 1; break; } } free(host_port); if (match == 0) { rc = SSH_AGAIN; goto out; } e->hostname = strdup(hostname); if (e->hostname == NULL) { rc = SSH_ERROR; goto out; } } /* Restart parsing */ SAFE_FREE(known_host); known_host = strdup(line); if (known_host == NULL) { rc = SSH_ERROR; goto out; } p = strtok(known_host, " "); if (p == NULL ) { rc = SSH_ERROR; goto out; } e->unparsed = strdup(p); if (e->unparsed == NULL) { rc = SSH_ERROR; goto out; } /* pubkey type */ p = strtok(NULL, " "); if (p == NULL) { rc = SSH_ERROR; goto out; } key_type = ssh_key_type_from_name(p); if (key_type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "key type '%s' unknown!", p); rc = SSH_ERROR; goto out; } /* public key */ p = strtok(NULL, " "); if (p == NULL) { rc = SSH_ERROR; goto out; } rc = ssh_pki_import_pubkey_base64(p, key_type, &e->publickey); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Failed to parse %s key for entry: %s!", ssh_key_type_to_char(key_type), e->unparsed); goto out; } /* comment */ p = strtok(NULL, " "); if (p != NULL) { p = strstr(line, p); if (p != NULL) { e->comment = strdup(p); if (e->comment == NULL) { rc = SSH_ERROR; goto out; } } } *entry = e; SAFE_FREE(known_host); return SSH_OK; out: SAFE_FREE(known_host); ssh_knownhosts_entry_free(e); return rc; } /** * @brief Check if the set hostname and port matches an entry in known_hosts. * * This check if the set hostname and port has an entry in the known_hosts file. * You need to set at least the hostname using ssh_options_set(). * * @param[in] session The session with with the values set to check. * * @return A ssh_known_hosts_e return value. */ enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session) { struct ssh_list *entry_list = NULL; struct ssh_iterator *it = NULL; char *host_port = NULL; bool global_known_hosts_found = false; bool known_hosts_found = false; int rc; if (session->opts.knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Cannot find a known_hosts file"); return SSH_KNOWN_HOSTS_NOT_FOUND; } } if (session->opts.knownhosts == NULL && session->opts.global_knownhosts == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "No path set for a known_hosts file"); return SSH_KNOWN_HOSTS_NOT_FOUND; } if (session->opts.knownhosts != NULL) { known_hosts_found = ssh_file_readaccess_ok(session->opts.knownhosts); if (!known_hosts_found) { SSH_LOG(SSH_LOG_WARN, "Cannot access file %s", session->opts.knownhosts); } } if (session->opts.global_knownhosts != NULL) { global_known_hosts_found = ssh_file_readaccess_ok(session->opts.global_knownhosts); if (!global_known_hosts_found) { SSH_LOG(SSH_LOG_WARN, "Cannot access file %s", session->opts.global_knownhosts); } } if ((!known_hosts_found) && (!global_known_hosts_found)) { ssh_set_error(session, SSH_REQUEST_DENIED, "Cannot find a known_hosts file"); return SSH_KNOWN_HOSTS_NOT_FOUND; } host_port = ssh_session_get_host_port(session); if (host_port == NULL) { return SSH_KNOWN_HOSTS_ERROR; } if (known_hosts_found) { rc = ssh_known_hosts_read_entries(host_port, session->opts.knownhosts, &entry_list); if (rc != 0) { SAFE_FREE(host_port); ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_ERROR; } } if (global_known_hosts_found) { rc = ssh_known_hosts_read_entries(host_port, session->opts.global_knownhosts, &entry_list); if (rc != 0) { SAFE_FREE(host_port); ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_ERROR; } } SAFE_FREE(host_port); if (ssh_list_count(entry_list) == 0) { ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_UNKNOWN; } for (it = ssh_list_get_iterator(entry_list); it != NULL; it = ssh_list_get_iterator(entry_list)) { struct ssh_knownhosts_entry *entry = NULL; entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); ssh_knownhosts_entry_free(entry); ssh_list_remove(entry_list, it); } ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_OK; } /** * @brief Export the current session information to a known_hosts string. * * This exports the current information of a session which is connected so a * ssh server into an entry line which can be added to a known_hosts file. * * @param[in] session The session with information to export. * * @param[in] pentry_string A pointer to a string to store the alloocated * line of the entry. The user must free it using * ssh_string_free_char(). * * @return SSH_OK on succcess, SSH_ERROR otherwise. */ int ssh_session_export_known_hosts_entry(ssh_session session, char **pentry_string) { ssh_key server_pubkey = NULL; char *host = NULL; char entry_buf[4096] = {0}; char *b64_key = NULL; int rc; if (pentry_string == NULL) { ssh_set_error_invalid(session); return SSH_ERROR; } if (session->opts.host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't create known_hosts entry - hostname unknown"); return SSH_ERROR; } host = ssh_session_get_host_port(session); if (host == NULL) { return SSH_ERROR; } if (session->current_crypto == NULL) { ssh_set_error(session, SSH_FATAL, "No current crypto context, please connect first"); SAFE_FREE(host); return SSH_ERROR; } server_pubkey = ssh_dh_get_current_server_publickey(session); if (server_pubkey == NULL){ ssh_set_error(session, SSH_FATAL, "No public key present"); SAFE_FREE(host); return SSH_ERROR; } rc = ssh_pki_export_pubkey_base64(server_pubkey, &b64_key); if (rc < 0) { SAFE_FREE(host); return SSH_ERROR; } snprintf(entry_buf, sizeof(entry_buf), "%s %s %s\n", host, server_pubkey->type_c, b64_key); SAFE_FREE(host); SAFE_FREE(b64_key); *pentry_string = strdup(entry_buf); if (*pentry_string == NULL) { return SSH_ERROR; } return SSH_OK; } /** * @brief Add the current connected server to the user known_hosts file. * * This adds the currently connected server to the known_hosts file by * appending a new line at the end. The global known_hosts file is considered * read-only so it is not touched by this function. * * @param[in] session The session to use to write the entry. * * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_session_update_known_hosts(ssh_session session) { FILE *fp = NULL; char *entry = NULL; char *dir = NULL; size_t nwritten; size_t len; int rc; if (session->opts.knownhosts == NULL) { rc = ssh_options_apply(session); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); return SSH_ERROR; } } errno = 0; fp = fopen(session->opts.knownhosts, "a"); if (fp == NULL) { if (errno == ENOENT) { dir = ssh_dirname(session->opts.knownhosts); if (dir == NULL) { ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); return SSH_ERROR; } rc = ssh_mkdirs(dir, 0700); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Cannot create %s directory: %s", dir, strerror(errno)); SAFE_FREE(dir); return SSH_ERROR; } SAFE_FREE(dir); errno = 0; fp = fopen(session->opts.knownhosts, "a"); if (fp == NULL) { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s" " for appending: %s", session->opts.knownhosts, strerror(errno)); return SSH_ERROR; } } else { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s for appending: %s", session->opts.knownhosts, strerror(errno)); return SSH_ERROR; } } rc = ssh_session_export_known_hosts_entry(session, &entry); if (rc != SSH_OK) { fclose(fp); return rc; } len = strlen(entry); nwritten = fwrite(entry, sizeof(char), len, fp); SAFE_FREE(entry); if (nwritten != len || ferror(fp)) { ssh_set_error(session, SSH_FATAL, "Couldn't append to known_hosts file %s: %s", session->opts.knownhosts, strerror(errno)); fclose(fp); return SSH_ERROR; } fclose(fp); return SSH_OK; } static enum ssh_known_hosts_e ssh_known_hosts_check_server_key(const char *hosts_entry, const char *filename, ssh_key server_key, struct ssh_knownhosts_entry **pentry) { struct ssh_list *entry_list = NULL; struct ssh_iterator *it = NULL; enum ssh_known_hosts_e found = SSH_KNOWN_HOSTS_UNKNOWN; int rc; rc = ssh_known_hosts_read_entries(hosts_entry, filename, &entry_list); if (rc != 0) { ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_UNKNOWN; } it = ssh_list_get_iterator(entry_list); if (it == NULL) { ssh_list_free(entry_list); return SSH_KNOWN_HOSTS_UNKNOWN; } for (;it != NULL; it = it->next) { struct ssh_knownhosts_entry *entry = NULL; int cmp; entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); cmp = ssh_key_cmp(server_key, entry->publickey, SSH_KEY_CMP_PUBLIC); if (cmp == 0) { found = SSH_KNOWN_HOSTS_OK; if (pentry != NULL) { *pentry = entry; ssh_list_remove(entry_list, it); } break; } if (ssh_key_type(server_key) == ssh_key_type(entry->publickey)) { found = SSH_KNOWN_HOSTS_CHANGED; continue; } if (found != SSH_KNOWN_HOSTS_CHANGED) { found = SSH_KNOWN_HOSTS_OTHER; } } for (it = ssh_list_get_iterator(entry_list); it != NULL; it = ssh_list_get_iterator(entry_list)) { struct ssh_knownhosts_entry *entry = NULL; entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); ssh_knownhosts_entry_free(entry); ssh_list_remove(entry_list, it); } ssh_list_free(entry_list); return found; } /** * @brief Get the known_hosts entry for the current connected session. * * @param[in] session The session to validate. * * @param[in] pentry A pointer to store the allocated known hosts entry. * * @returns SSH_KNOWN_HOSTS_OK: The server is known and has not changed.\n * SSH_KNOWN_HOSTS_CHANGED: The server key has changed. Either you * are under attack or the administrator * changed the key. You HAVE to warn the * user about a possible attack.\n * SSH_KNOWN_HOSTS_OTHER: The server gave use a key of a type while * we had an other type recorded. It is a * possible attack.\n * SSH_KNOWN_HOSTS_UNKNOWN: The server is unknown. User should * confirm the public key hash is correct.\n * SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The * host is thus unknown. File will be * created if host key is accepted.\n * SSH_KNOWN_HOSTS_ERROR: There had been an eror checking the host. * * @see ssh_knownhosts_entry_free() */ enum ssh_known_hosts_e ssh_session_get_known_hosts_entry(ssh_session session, struct ssh_knownhosts_entry **pentry) { enum ssh_known_hosts_e old_rv, rv = SSH_KNOWN_HOSTS_UNKNOWN; if (session->opts.knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Can't find a known_hosts file"); return SSH_KNOWN_HOSTS_NOT_FOUND; } } rv = ssh_session_get_known_hosts_entry_file(session, session->opts.knownhosts, pentry); if (rv == SSH_KNOWN_HOSTS_OK) { /* We already found a match in the first file: return */ return rv; } old_rv = rv; rv = ssh_session_get_known_hosts_entry_file(session, session->opts.global_knownhosts, pentry); /* If we did not find any match at all: we report the previous result */ if (rv == SSH_KNOWN_HOSTS_UNKNOWN) { if (session->opts.StrictHostKeyChecking == 0) { return SSH_KNOWN_HOSTS_OK; } return old_rv; } /* We found some match: return it */ return rv; } /** * @brief Get the known_hosts entry for the current connected session * from the given known_hosts file. * * @param[in] session The session to validate. * * @param[in] filename The filename to parse. * * @param[in] pentry A pointer to store the allocated known hosts entry. * * @returns SSH_KNOWN_HOSTS_OK: The server is known and has not changed.\n * SSH_KNOWN_HOSTS_CHANGED: The server key has changed. Either you * are under attack or the administrator * changed the key. You HAVE to warn the * user about a possible attack.\n * SSH_KNOWN_HOSTS_OTHER: The server gave use a key of a type while * we had an other type recorded. It is a * possible attack.\n * SSH_KNOWN_HOSTS_UNKNOWN: The server is unknown. User should * confirm the public key hash is correct.\n * SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The * host is thus unknown. File will be * created if host key is accepted.\n * SSH_KNOWN_HOSTS_ERROR: There had been an eror checking the host. * * @see ssh_knownhosts_entry_free() */ enum ssh_known_hosts_e ssh_session_get_known_hosts_entry_file(ssh_session session, const char *filename, struct ssh_knownhosts_entry **pentry) { ssh_key server_pubkey = NULL; char *host_port = NULL; enum ssh_known_hosts_e found = SSH_KNOWN_HOSTS_UNKNOWN; server_pubkey = ssh_dh_get_current_server_publickey(session); if (server_pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "ssh_session_is_known_host called without a " "server_key!"); return SSH_KNOWN_HOSTS_ERROR; } host_port = ssh_session_get_host_port(session); if (host_port == NULL) { return SSH_KNOWN_HOSTS_ERROR; } found = ssh_known_hosts_check_server_key(host_port, filename, server_pubkey, pentry); SAFE_FREE(host_port); return found; } /** * @brief Check if the servers public key for the connected session is known. * * This checks if we already know the public key of the server we want to * connect to. This allows to detect if there is a MITM attach going on * of if there have been changes on the server we don't know about. * * @param[in] session The SSH to validate. * * @returns SSH_KNOWN_HOSTS_OK: The server is known and has not changed.\n * SSH_KNOWN_HOSTS_CHANGED: The server key has changed. Either you * are under attack or the administrator * changed the key. You HAVE to warn the * user about a possible attack.\n * SSH_KNOWN_HOSTS_OTHER: The server gave use a key of a type while * we had an other type recorded. It is a * possible attack.\n * SSH_KNOWN_HOSTS_UNKNOWN: The server is unknown. User should * confirm the public key hash is correct.\n * SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The * host is thus unknown. File will be * created if host key is accepted.\n * SSH_KNOWN_HOSTS_ERROR: There had been an error checking the host. */ enum ssh_known_hosts_e ssh_session_is_known_server(ssh_session session) { return ssh_session_get_known_hosts_entry(session, NULL); } /** @} */ ================================================ FILE: src/libssh/src/legacy.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /** functions in that file are wrappers to the newly named functions. All * of them are depreciated, but these wrapper will avoid breaking backward * compatibility */ #include "config.h" #include #include #include #include #include #include #include #include #include "libssh/pki_priv.h" #include #include #include "libssh/options.h" /* AUTH FUNCTIONS */ int ssh_auth_list(ssh_session session) { return ssh_userauth_list(session, NULL); } int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey) { ssh_key key; int rc; (void) type; /* unused */ rc = ssh_pki_import_pubkey_blob(publickey, &key); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Failed to convert public key"); return SSH_AUTH_ERROR; } rc = ssh_userauth_try_publickey(session, username, key); ssh_key_free(key); return rc; } int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey) { ssh_key key; int rc; (void) publickey; /* unused */ key = ssh_key_new(); if (key == NULL) { return SSH_AUTH_ERROR; } key->type = privatekey->type; key->type_c = ssh_key_type_to_char(key->type); key->flags = SSH_KEY_FLAG_PRIVATE|SSH_KEY_FLAG_PUBLIC; key->dsa = privatekey->dsa_priv; key->rsa = privatekey->rsa_priv; rc = ssh_userauth_publickey(session, username, key); key->dsa = NULL; key->rsa = NULL; ssh_key_free(key); return rc; } int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { return ssh_userauth_publickey_auto(session, NULL, passphrase); } int ssh_userauth_privatekey_file(ssh_session session, const char *username, const char *filename, const char *passphrase) { char *pubkeyfile = NULL; ssh_string pubkey = NULL; ssh_private_key privkey = NULL; int type = 0; int rc = SSH_AUTH_ERROR; size_t klen = strlen(filename) + 4 + 1; pubkeyfile = malloc(klen); if (pubkeyfile == NULL) { ssh_set_error_oom(session); return SSH_AUTH_ERROR; } snprintf(pubkeyfile, klen, "%s.pub", filename); pubkey = publickey_from_file(session, pubkeyfile, &type); if (pubkey == NULL) { SSH_LOG(SSH_LOG_RARE, "Public key file %s not found. Trying to generate it.", pubkeyfile); /* auto-detect the key type with type=0 */ privkey = privatekey_from_file(session, filename, 0, passphrase); } else { SSH_LOG(SSH_LOG_RARE, "Public key file %s loaded.", pubkeyfile); privkey = privatekey_from_file(session, filename, type, passphrase); } if (privkey == NULL) { goto error; } /* ssh_userauth_pubkey is responsible for taking care of null-pubkey */ rc = ssh_userauth_pubkey(session, username, pubkey, privkey); privatekey_free(privkey); error: SAFE_FREE(pubkeyfile); ssh_string_free(pubkey); return rc; } /* BUFFER FUNCTIONS */ void buffer_free(ssh_buffer buffer){ ssh_buffer_free(buffer); } void *buffer_get(ssh_buffer buffer){ return ssh_buffer_get(buffer); } uint32_t buffer_get_len(ssh_buffer buffer){ return ssh_buffer_get_len(buffer); } ssh_buffer buffer_new(void){ return ssh_buffer_new(); } ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms){ return ssh_channel_accept_x11(channel, timeout_ms); } int channel_change_pty_size(ssh_channel channel,int cols,int rows){ return ssh_channel_change_pty_size(channel,cols,rows); } ssh_channel channel_forward_accept(ssh_session session, int timeout_ms){ return ssh_channel_accept_forward(session, timeout_ms, NULL); } int channel_close(ssh_channel channel){ return ssh_channel_close(channel); } int channel_forward_cancel(ssh_session session, const char *address, int port){ return ssh_channel_cancel_forward(session, address, port); } int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port){ return ssh_channel_listen_forward(session, address, port, bound_port); } void channel_free(ssh_channel channel){ ssh_channel_free(channel); } int channel_get_exit_status(ssh_channel channel){ return ssh_channel_get_exit_status(channel); } ssh_session channel_get_session(ssh_channel channel){ return ssh_channel_get_session(channel); } int channel_is_closed(ssh_channel channel){ return ssh_channel_is_closed(channel); } int channel_is_eof(ssh_channel channel){ return ssh_channel_is_eof(channel); } int channel_is_open(ssh_channel channel){ return ssh_channel_is_open(channel); } ssh_channel channel_new(ssh_session session){ return ssh_channel_new(session); } int channel_open_forward(ssh_channel channel, const char *remotehost, int remoteport, const char *sourcehost, int localport){ return ssh_channel_open_forward(channel, remotehost, remoteport, sourcehost,localport); } int channel_open_session(ssh_channel channel){ return ssh_channel_open_session(channel); } int channel_poll(ssh_channel channel, int is_stderr){ return ssh_channel_poll(channel, is_stderr); } int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr){ return ssh_channel_read(channel, dest, count, is_stderr); } /* * This function will completely be depreciated. The old implementation was not * renamed. * int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count, * int is_stderr); */ int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count, int is_stderr){ return ssh_channel_read_nonblocking(channel, dest, count, is_stderr); } int channel_request_env(ssh_channel channel, const char *name, const char *value){ return ssh_channel_request_env(channel, name, value); } int channel_request_exec(ssh_channel channel, const char *cmd){ return ssh_channel_request_exec(channel, cmd); } int channel_request_pty(ssh_channel channel){ return ssh_channel_request_pty(channel); } int channel_request_pty_size(ssh_channel channel, const char *term, int cols, int rows){ return ssh_channel_request_pty_size(channel, term, cols, rows); } int channel_request_shell(ssh_channel channel){ return ssh_channel_request_shell(channel); } int channel_request_send_signal(ssh_channel channel, const char *signum){ return ssh_channel_request_send_signal(channel, signum); } int channel_request_sftp(ssh_channel channel){ return ssh_channel_request_sftp(channel); } int channel_request_subsystem(ssh_channel channel, const char *subsystem){ return ssh_channel_request_subsystem(channel, subsystem); } int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol, const char *cookie, int screen_number){ return ssh_channel_request_x11(channel, single_connection, protocol, cookie, screen_number); } int channel_send_eof(ssh_channel channel){ return ssh_channel_send_eof(channel); } int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout){ return ssh_channel_select(readchans, writechans, exceptchans, timeout); } void channel_set_blocking(ssh_channel channel, int blocking){ ssh_channel_set_blocking(channel, blocking); } int channel_write(ssh_channel channel, const void *data, uint32_t len){ return ssh_channel_write(channel, data, len); } /* * These functions have to be wrapped around the pki.c functions. void privatekey_free(ssh_private_key prv); ssh_private_key privatekey_from_file(ssh_session session, const char *filename, int type, const char *passphrase); int ssh_publickey_to_file(ssh_session session, const char *file, ssh_string pubkey, int type); ssh_string publickey_to_string(ssh_public_key key); * */ void string_burn(ssh_string str){ ssh_string_burn(str); } ssh_string string_copy(ssh_string str){ return ssh_string_copy(str); } void *string_data(ssh_string str){ return ssh_string_data(str); } int string_fill(ssh_string str, const void *data, size_t len){ return ssh_string_fill(str,data,len); } void string_free(ssh_string str){ ssh_string_free(str); } ssh_string string_from_char(const char *what){ return ssh_string_from_char(what); } size_t string_len(ssh_string str){ return ssh_string_len(str); } ssh_string string_new(size_t size){ return ssh_string_new(size); } char *string_to_char(ssh_string str){ return ssh_string_to_char(str); } /* OLD PKI FUNCTIONS */ void publickey_free(ssh_public_key key) { if (key == NULL) { return; } switch(key->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(key->dsa_pub); #elif defined HAVE_LIBCRYPTO DSA_free(key->dsa_pub); #endif break; case SSH_KEYTYPE_RSA: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(key->rsa_pub); #elif defined HAVE_LIBCRYPTO RSA_free(key->rsa_pub); #elif defined HAVE_LIBMBEDCRYPTO mbedtls_pk_free(key->rsa_pub); SAFE_FREE(key->rsa_pub); #endif break; default: break; } SAFE_FREE(key); } ssh_public_key publickey_from_privatekey(ssh_private_key prv) { struct ssh_public_key_struct *p; ssh_key privkey; ssh_key pubkey; int rc; privkey = ssh_key_new(); if (privkey == NULL) { return NULL; } privkey->type = prv->type; privkey->type_c = ssh_key_type_to_char(privkey->type); privkey->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; privkey->dsa = prv->dsa_priv; privkey->rsa = prv->rsa_priv; rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); privkey->dsa = NULL; privkey->rsa = NULL; ssh_key_free(privkey); if (rc < 0) { return NULL; } p = ssh_pki_convert_key_to_publickey(pubkey); ssh_key_free(pubkey); return p; } ssh_private_key privatekey_from_file(ssh_session session, const char *filename, int type, const char *passphrase) { ssh_auth_callback auth_fn = NULL; void *auth_data = NULL; ssh_private_key privkey; ssh_key key; int rc; (void) type; /* unused */ if (session->common.callbacks) { auth_fn = session->common.callbacks->auth_function; auth_data = session->common.callbacks->userdata; } rc = ssh_pki_import_privkey_file(filename, passphrase, auth_fn, auth_data, &key); if (rc == SSH_ERROR) { return NULL; } privkey = malloc(sizeof(struct ssh_private_key_struct)); if (privkey == NULL) { ssh_key_free(key); return NULL; } privkey->type = key->type; privkey->dsa_priv = key->dsa; privkey->rsa_priv = key->rsa; key->dsa = NULL; key->rsa = NULL; ssh_key_free(key); return privkey; } enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey){ if (privatekey==NULL) return SSH_KEYTYPE_UNKNOWN; return privatekey->type; } void privatekey_free(ssh_private_key prv) { if (prv == NULL) { return; } #ifdef HAVE_LIBGCRYPT gcry_sexp_release(prv->dsa_priv); gcry_sexp_release(prv->rsa_priv); #elif defined HAVE_LIBCRYPTO DSA_free(prv->dsa_priv); RSA_free(prv->rsa_priv); #elif defined HAVE_LIBMBEDCRYPTO mbedtls_pk_free(prv->rsa_priv); SAFE_FREE(prv->rsa_priv); #endif memset(prv, 0, sizeof(struct ssh_private_key_struct)); SAFE_FREE(prv); } ssh_string publickey_from_file(ssh_session session, const char *filename, int *type) { ssh_key key; ssh_string key_str = NULL; int rc; (void) session; /* unused */ rc = ssh_pki_import_pubkey_file(filename, &key); if (rc < 0) { return NULL; } rc = ssh_pki_export_pubkey_blob(key, &key_str); if (rc < 0) { ssh_key_free(key); return NULL; } if (type) { *type = key->type; } ssh_key_free(key); return key_str; } const char *ssh_type_to_char(int type) { return ssh_key_type_to_char(type); } int ssh_type_from_name(const char *name) { return ssh_key_type_from_name(name); } ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) { struct ssh_public_key_struct *pubkey; ssh_key key; int rc; (void) session; /* unused */ rc = ssh_pki_import_pubkey_blob(pubkey_s, &key); if (rc < 0) { return NULL; } pubkey = malloc(sizeof(struct ssh_public_key_struct)); if (pubkey == NULL) { ssh_key_free(key); return NULL; } pubkey->type = key->type; pubkey->type_c = key->type_c; pubkey->dsa_pub = key->dsa; key->dsa = NULL; pubkey->rsa_pub = key->rsa; key->rsa = NULL; ssh_key_free(key); return pubkey; } ssh_string publickey_to_string(ssh_public_key pubkey) { ssh_key key; ssh_string key_blob; int rc; if (pubkey == NULL) { return NULL; } key = ssh_key_new(); if (key == NULL) { return NULL; } key->type = pubkey->type; key->type_c = pubkey->type_c; key->dsa = pubkey->dsa_pub; key->rsa = pubkey->rsa_pub; rc = ssh_pki_export_pubkey_blob(key, &key_blob); if (rc < 0) { key_blob = NULL; } key->dsa = NULL; key->rsa = NULL; ssh_key_free(key); return key_blob; } int ssh_publickey_to_file(ssh_session session, const char *file, ssh_string pubkey, int type) { FILE *fp; char *user; char buffer[1024]; char host[256]; unsigned char *pubkey_64; size_t len; int rc; if(session==NULL) return SSH_ERROR; if(file==NULL || pubkey==NULL){ ssh_set_error(session, SSH_FATAL, "Invalid parameters"); return SSH_ERROR; } pubkey_64 = bin_to_base64(ssh_string_data(pubkey), ssh_string_len(pubkey)); if (pubkey_64 == NULL) { return SSH_ERROR; } user = ssh_get_local_username(); if (user == NULL) { SAFE_FREE(pubkey_64); return SSH_ERROR; } rc = gethostname(host, sizeof(host)); if (rc < 0) { SAFE_FREE(user); SAFE_FREE(pubkey_64); return SSH_ERROR; } snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n", ssh_type_to_char(type), pubkey_64, user, host); SAFE_FREE(pubkey_64); SAFE_FREE(user); SSH_LOG(SSH_LOG_RARE, "Trying to write public key file: %s", file); SSH_LOG(SSH_LOG_PACKET, "public key file content: %s", buffer); fp = fopen(file, "w+"); if (fp == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Error opening %s: %s", file, strerror(errno)); return SSH_ERROR; } len = strlen(buffer); if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) { ssh_set_error(session, SSH_REQUEST_DENIED, "Unable to write to %s", file); fclose(fp); unlink(file); return SSH_ERROR; } fclose(fp); return SSH_OK; } int ssh_try_publickey_from_file(ssh_session session, const char *keyfile, ssh_string *publickey, int *type) { char *pubkey_file; size_t len; ssh_string pubkey_string; int pubkey_type; if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) { return -1; } if (session->opts.sshdir == NULL) { if (ssh_options_apply(session) < 0) { return -1; } } SSH_LOG(SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile); if (!ssh_file_readaccess_ok(keyfile)) { SSH_LOG(SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile); return -1; } len = strlen(keyfile) + 5; pubkey_file = malloc(len); if (pubkey_file == NULL) { return -1; } snprintf(pubkey_file, len, "%s.pub", keyfile); SSH_LOG(SSH_LOG_PACKET, "Trying to open publickey %s", pubkey_file); if (!ssh_file_readaccess_ok(pubkey_file)) { SSH_LOG(SSH_LOG_PACKET, "Failed to open publickey %s", pubkey_file); SAFE_FREE(pubkey_file); return 1; } SSH_LOG(SSH_LOG_PACKET, "Success opening public and private key"); /* * We are sure both the private and public key file is readable. We return * the public as a string, and the private filename as an argument */ pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type); if (pubkey_string == NULL) { SSH_LOG(SSH_LOG_PACKET, "Wasn't able to open public key file %s: %s", pubkey_file, ssh_get_error(session)); SAFE_FREE(pubkey_file); return -1; } SAFE_FREE(pubkey_file); *publickey = pubkey_string; *type = pubkey_type; return 0; } ssh_string ssh_get_pubkey(ssh_session session) { ssh_string pubkey_blob = NULL; int rc; if (session == NULL || session->current_crypto == NULL || session->current_crypto->server_pubkey == NULL) { return NULL; } rc = ssh_dh_get_current_server_publickey_blob(session, &pubkey_blob); if (rc != 0) { return NULL; } return pubkey_blob; } /**************************************************************************** * SERVER SUPPORT ****************************************************************************/ #ifdef WITH_SERVER int ssh_accept(ssh_session session) { return ssh_handle_key_exchange(session); } int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) { return ssh_channel_write(channel, data, len); } /** @deprecated * @brief Interface previously exported by error. */ ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){ (void) packettype; ssh_set_error(session, SSH_FATAL, "ssh_message_retrieve: obsolete libssh call"); return NULL; } #endif /* WITH_SERVER */ ================================================ FILE: src/libssh/src/libcrypto-compat.c ================================================ /* * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include "config.h" #include #include "libcrypto-compat.h" #ifndef OPENSSL_NO_ENGINE #include #endif static void *OPENSSL_zalloc(size_t num) { void *ret = OPENSSL_malloc(num); if (ret != NULL) memset(ret, 0, num); return ret; } int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { /* If the fields n and e in r are NULL, the corresponding input * parameters MUST be non-NULL for n and e. d may be * left NULL (in case only the public key is used). */ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) return 0; if (n != NULL) { BN_free(r->n); r->n = n; } if (e != NULL) { BN_free(r->e); r->e = e; } if (d != NULL) { BN_free(r->d); r->d = d; } return 1; } int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) { /* If the fields p and q in r are NULL, the corresponding input * parameters MUST be non-NULL. */ if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) return 0; if (p != NULL) { BN_free(r->p); r->p = p; } if (q != NULL) { BN_free(r->q); r->q = q; } return 1; } int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) { /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input * parameters MUST be non-NULL. */ if ((r->dmp1 == NULL && dmp1 == NULL) || (r->dmq1 == NULL && dmq1 == NULL) || (r->iqmp == NULL && iqmp == NULL)) return 0; if (dmp1 != NULL) { BN_free(r->dmp1); r->dmp1 = dmp1; } if (dmq1 != NULL) { BN_free(r->dmq1); r->dmq1 = dmq1; } if (iqmp != NULL) { BN_free(r->iqmp); r->iqmp = iqmp; } return 1; } void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { if (n != NULL) *n = r->n; if (e != NULL) *e = r->e; if (d != NULL) *d = r->d; } void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) { if (p != NULL) *p = r->p; if (q != NULL) *q = r->q; } void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { if (dmp1 != NULL) *dmp1 = r->dmp1; if (dmq1 != NULL) *dmq1 = r->dmq1; if (iqmp != NULL) *iqmp = r->iqmp; } void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { if (p != NULL) *p = d->p; if (q != NULL) *q = d->q; if (g != NULL) *g = d->g; } int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) { /* If the fields p, q and g in d are NULL, the corresponding input * parameters MUST be non-NULL. */ if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) || (d->g == NULL && g == NULL)) return 0; if (p != NULL) { BN_free(d->p); d->p = p; } if (q != NULL) { BN_free(d->q); d->q = q; } if (g != NULL) { BN_free(d->g); d->g = g; } return 1; } void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { if (pub_key != NULL) *pub_key = d->pub_key; if (priv_key != NULL) *priv_key = d->priv_key; } int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) { /* If the field pub_key in d is NULL, the corresponding input * parameters MUST be non-NULL. The priv_key field may * be left NULL. */ if (d->pub_key == NULL && pub_key == NULL) return 0; if (pub_key != NULL) { BN_free(d->pub_key); d->pub_key = pub_key; } if (priv_key != NULL) { BN_free(d->priv_key); d->priv_key = priv_key; } return 1; } void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr != NULL) *pr = sig->r; if (ps != NULL) *ps = sig->s; } int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if (r == NULL || s == NULL) return 0; BN_clear_free(sig->r); BN_clear_free(sig->s); sig->r = r; sig->s = s; return 1; } void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr != NULL) *pr = sig->r; if (ps != NULL) *ps = sig->s; } int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if (r == NULL || s == NULL) return 0; BN_clear_free(sig->r); BN_clear_free(sig->s); sig->r = r; sig->s = s; return 1; } EVP_MD_CTX *EVP_MD_CTX_new(void) { return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); } static void OPENSSL_clear_free(void *str, size_t num) { if (str == NULL) return; if (num) OPENSSL_cleanse(str, num); OPENSSL_free(str); } /* This call frees resources associated with the context */ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) { if (ctx == NULL) return 1; /* * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because * sometimes only copies of the context are ever finalised. */ if (ctx->digest && ctx->digest->cleanup && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) ctx->digest->cleanup(ctx); if (ctx->digest && ctx->digest->ctx_size && ctx->md_data && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); } EVP_PKEY_CTX_free(ctx->pctx); #ifndef OPENSSL_NO_ENGINE ENGINE_finish(ctx->engine); #endif OPENSSL_cleanse(ctx, sizeof(*ctx)); return 1; } void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { EVP_MD_CTX_reset(ctx); OPENSSL_free(ctx); } int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) { EVP_CIPHER_CTX_init(ctx); return 1; } HMAC_CTX *HMAC_CTX_new(void) { HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX)); if (ctx != NULL) { if (!HMAC_CTX_reset(ctx)) { HMAC_CTX_free(ctx); return NULL; } } return ctx; } static void hmac_ctx_cleanup(HMAC_CTX *ctx) { EVP_MD_CTX_reset(&ctx->i_ctx); EVP_MD_CTX_reset(&ctx->o_ctx); EVP_MD_CTX_reset(&ctx->md_ctx); ctx->md = NULL; ctx->key_length = 0; OPENSSL_cleanse(ctx->key, sizeof(ctx->key)); } void HMAC_CTX_free(HMAC_CTX *ctx) { if (ctx != NULL) { hmac_ctx_cleanup(ctx); #if OPENSSL_VERSION_NUMBER > 0x10100000L EVP_MD_CTX_free(&ctx->i_ctx); EVP_MD_CTX_free(&ctx->o_ctx); EVP_MD_CTX_free(&ctx->md_ctx); #endif OPENSSL_free(ctx); } } int HMAC_CTX_reset(HMAC_CTX *ctx) { HMAC_CTX_init(ctx); return 1; } #ifndef HAVE_OPENSSL_EVP_CIPHER_CTX_NEW EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) { return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); } void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) { /* EVP_CIPHER_CTX_reset(ctx); alias */ EVP_CIPHER_CTX_init(ctx); OPENSSL_free(ctx); } #endif void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) { if (p) { *p = dh->p; } if (q) { *q = NULL; } if (g) { *g = dh->g; } } int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) { if (p) { if (dh->p) { BN_free(dh->p); } dh->p = p; } if (g) { if (dh->g) { BN_free(dh->g); } dh->g = g; } return 1; } void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { if (pub_key) { *pub_key = dh->pub_key; } if (priv_key) { *priv_key = dh->priv_key; } } int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) { if (pub_key) { if (dh->pub_key) { BN_free(dh->pub_key); } dh->pub_key = pub_key; } if (priv_key) { if (dh->priv_key) { BN_free(dh->priv_key); } dh->priv_key = priv_key; } return 1; } const char *OpenSSL_version(int type) { return SSLeay_version(type); } unsigned long OpenSSL_version_num(void) { return SSLeay(); } ================================================ FILE: src/libssh/src/libcrypto-compat.h ================================================ #ifndef LIBCRYPTO_COMPAT_H #define LIBCRYPTO_COMPAT_H #include #if OPENSSL_VERSION_NUMBER < 0x10100000L #include #include #include #include #include #include #include int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp); void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); EVP_MD_CTX *EVP_MD_CTX_new(void); void EVP_MD_CTX_free(EVP_MD_CTX *ctx); int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx); HMAC_CTX *HMAC_CTX_new(void); int HMAC_CTX_reset(HMAC_CTX *ctx); void HMAC_CTX_free(HMAC_CTX *ctx); void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); const char *OpenSSL_version(int type); unsigned long OpenSSL_version_num(void); #endif /* OPENSSL_VERSION_NUMBER */ #endif /* LIBCRYPTO_COMPAT_H */ ================================================ FILE: src/libssh/src/libcrypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/wrapper.h" #include "libssh/libcrypto.h" #ifdef HAVE_LIBCRYPTO #include #include #include #include #include #include #include #include "libcrypto-compat.h" #ifdef HAVE_OPENSSL_AES_H #define HAS_AES #include #endif #ifdef HAVE_OPENSSL_DES_H #define HAS_DES #include #endif #if (defined(HAVE_VALGRIND_VALGRIND_H) && defined(HAVE_OPENSSL_IA32CAP_LOC)) #include #define CAN_DISABLE_AESNI #endif #include "libssh/crypto.h" #ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID #include #endif #ifdef HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT #include #endif #include "libssh/crypto.h" static int libcrypto_initialized = 0; void ssh_reseed(void){ #ifndef _WIN32 struct timeval tv; gettimeofday(&tv, NULL); RAND_add(&tv, sizeof(tv), 0.0); #endif } /** * @brief Get random bytes * * Make sure to always check the return code of this function! * * @param[in] where The buffer to fill with random bytes * * @param[in] len The size of the buffer to fill. * * @param[in] strong Use a strong or private RNG source. * * @return 1 on success, 0 on error. */ int ssh_get_random(void *where, int len, int strong) { #ifdef HAVE_OPENSSL_RAND_PRIV_BYTES if (strong) { /* Returns -1 when not supported, 0 on error, 1 on success */ return !!RAND_priv_bytes(where, len); } #else (void)strong; #endif /* HAVE_RAND_PRIV_BYTES */ /* Returns -1 when not supported, 0 on error, 1 on success */ return !!RAND_bytes(where, len); } SHACTX sha1_init(void) { int rc; SHACTX c = EVP_MD_CTX_create(); if (c == NULL) { return NULL; } EVP_MD_CTX_init(c); rc = EVP_DigestInit_ex(c, EVP_sha1(), NULL); if (rc == 0) { EVP_MD_CTX_destroy(c); c = NULL; } return c; } void sha1_update(SHACTX c, const void *data, unsigned long len) { EVP_DigestUpdate(c, data, len); } void sha1_final(unsigned char *md, SHACTX c) { unsigned int mdlen = 0; EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } void sha1(const unsigned char *digest, int len, unsigned char *hash) { SHACTX c = sha1_init(); if (c != NULL) { sha1_update(c, digest, len); sha1_final(hash, c); } } #ifdef HAVE_OPENSSL_ECC static const EVP_MD *nid_to_evpmd(int nid) { switch (nid) { case NID_X9_62_prime256v1: return EVP_sha256(); case NID_secp384r1: return EVP_sha384(); case NID_secp521r1: return EVP_sha512(); default: return NULL; } return NULL; } void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) { const EVP_MD *evp_md = nid_to_evpmd(nid); EVP_MD_CTX *md = EVP_MD_CTX_new(); EVP_DigestInit(md, evp_md); EVP_DigestUpdate(md, digest, len); EVP_DigestFinal(md, hash, hlen); EVP_MD_CTX_free(md); } EVPCTX evp_init(int nid) { const EVP_MD *evp_md = nid_to_evpmd(nid); EVPCTX ctx = EVP_MD_CTX_new(); if (ctx == NULL) { return NULL; } EVP_DigestInit(ctx, evp_md); return ctx; } void evp_update(EVPCTX ctx, const void *data, unsigned long len) { EVP_DigestUpdate(ctx, data, len); } void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) { EVP_DigestFinal(ctx, md, mdlen); EVP_MD_CTX_free(ctx); } #endif SHA256CTX sha256_init(void) { int rc; SHA256CTX c = EVP_MD_CTX_create(); if (c == NULL) { return NULL; } EVP_MD_CTX_init(c); rc = EVP_DigestInit_ex(c, EVP_sha256(), NULL); if (rc == 0) { EVP_MD_CTX_destroy(c); c = NULL; } return c; } void sha256_update(SHA256CTX c, const void *data, unsigned long len) { EVP_DigestUpdate(c, data, len); } void sha256_final(unsigned char *md, SHA256CTX c) { unsigned int mdlen = 0; EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } void sha256(const unsigned char *digest, int len, unsigned char *hash) { SHA256CTX c = sha256_init(); if (c != NULL) { sha256_update(c, digest, len); sha256_final(hash, c); } } SHA384CTX sha384_init(void) { int rc; SHA384CTX c = EVP_MD_CTX_create(); if (c == NULL) { return NULL; } EVP_MD_CTX_init(c); rc = EVP_DigestInit_ex(c, EVP_sha384(), NULL); if (rc == 0) { EVP_MD_CTX_destroy(c); c = NULL; } return c; } void sha384_update(SHA384CTX c, const void *data, unsigned long len) { EVP_DigestUpdate(c, data, len); } void sha384_final(unsigned char *md, SHA384CTX c) { unsigned int mdlen = 0; EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } void sha384(const unsigned char *digest, int len, unsigned char *hash) { SHA384CTX c = sha384_init(); if (c != NULL) { sha384_update(c, digest, len); sha384_final(hash, c); } } SHA512CTX sha512_init(void) { int rc = 0; SHA512CTX c = EVP_MD_CTX_create(); if (c == NULL) { return NULL; } EVP_MD_CTX_init(c); rc = EVP_DigestInit_ex(c, EVP_sha512(), NULL); if (rc == 0) { EVP_MD_CTX_destroy(c); c = NULL; } return c; } void sha512_update(SHA512CTX c, const void *data, unsigned long len) { EVP_DigestUpdate(c, data, len); } void sha512_final(unsigned char *md, SHA512CTX c) { unsigned int mdlen = 0; EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } void sha512(const unsigned char *digest, int len, unsigned char *hash) { SHA512CTX c = sha512_init(); if (c != NULL) { sha512_update(c, digest, len); sha512_final(hash, c); } } MD5CTX md5_init(void) { int rc; MD5CTX c = EVP_MD_CTX_create(); if (c == NULL) { return NULL; } EVP_MD_CTX_init(c); rc = EVP_DigestInit_ex(c, EVP_md5(), NULL); if(rc == 0) { EVP_MD_CTX_destroy(c); c = NULL; } return c; } void md5_update(MD5CTX c, const void *data, unsigned long len) { EVP_DigestUpdate(c, data, len); } void md5_final(unsigned char *md, MD5CTX c) { unsigned int mdlen = 0; EVP_DigestFinal(c, md, &mdlen); EVP_MD_CTX_destroy(c); } #ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type) { switch (digest_type) { case SSH_KDF_SHA1: return EVP_sha1(); case SSH_KDF_SHA256: return EVP_sha256(); case SSH_KDF_SHA384: return EVP_sha384(); case SSH_KDF_SHA512: return EVP_sha512(); } return NULL; } int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); int rc; if (ctx == NULL) { return -1; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, sshkdf_digest_to_md(crypto->digest_type)); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key, key_len); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, crypto->secret_hash, crypto->digest_len); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, key_type); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, crypto->session_id, crypto->digest_len); if (rc != 1) { goto out; } rc = EVP_KDF_derive(ctx, output, requested_len); if (rc != 1) { goto out; } out: EVP_KDF_CTX_free(ctx); if (rc < 0) { return rc; } return 0; } #else int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { return sshkdf_derive_key(crypto, key, key_len, key_type, output, requested_len); } #endif HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { HMACCTX ctx = NULL; ctx = HMAC_CTX_new(); if (ctx == NULL) { return NULL; } switch(type) { case SSH_HMAC_SHA1: case SSH_HMAC_SHA1_96: HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL); break; case SSH_HMAC_SHA256: HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL); break; case SSH_HMAC_SHA512: HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL); break; case SSH_HMAC_MD5: case SSH_HMAC_MD5_96: HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL); break; default: HMAC_CTX_free(ctx); ctx = NULL; } return ctx; } void hmac_update(HMACCTX ctx, const void *data, unsigned long len) { HMAC_Update(ctx, data, len); } void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len, enum ssh_hmac_e type) { HMAC_Final(ctx,hashmacbuf,len); switch (type) { case SSH_HMAC_SHA1_96: case SSH_HMAC_MD5_96: *len = hmac_digest_len(type); break; } #if OPENSSL_VERSION_NUMBER > 0x10100000L HMAC_CTX_free(ctx); ctx = NULL; #else HMAC_cleanup(ctx); SAFE_FREE(ctx); ctx = NULL; #endif } static void evp_cipher_init(struct ssh_cipher_struct *cipher) { if (cipher->ctx == NULL) { cipher->ctx = EVP_CIPHER_CTX_new(); } switch(cipher->ciphertype){ case SSH_AES128_CBC: cipher->cipher = EVP_aes_128_cbc(); break; case SSH_AES192_CBC: cipher->cipher = EVP_aes_192_cbc(); break; case SSH_AES256_CBC: cipher->cipher = EVP_aes_256_cbc(); break; #ifdef HAVE_OPENSSL_EVP_AES_CTR case SSH_AES128_CTR: cipher->cipher = EVP_aes_128_ctr(); break; case SSH_AES192_CTR: cipher->cipher = EVP_aes_192_ctr(); break; case SSH_AES256_CTR: cipher->cipher = EVP_aes_256_ctr(); break; #else case SSH_AES128_CTR: case SSH_AES192_CTR: case SSH_AES256_CTR: SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init"); break; #endif #ifdef HAVE_OPENSSL_EVP_AES_GCM case SSH_AEAD_AES128_GCM: cipher->cipher = EVP_aes_128_gcm(); break; case SSH_AEAD_AES256_GCM: cipher->cipher = EVP_aes_256_gcm(); break; #else case SSH_AEAD_AES128_GCM: case SSH_AEAD_AES256_GCM: SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init"); break; #endif /* HAVE_OPENSSL_EVP_AES_GCM */ case SSH_3DES_CBC: cipher->cipher = EVP_des_ede3_cbc(); break; #ifdef WITH_BLOWFISH_CIPHER case SSH_BLOWFISH_CBC: cipher->cipher = EVP_bf_cbc(); break; /* ciphers not using EVP */ #endif case SSH_AEAD_CHACHA20_POLY1305: SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here"); break; case SSH_NO_CIPHER: SSH_LOG(SSH_LOG_WARNING, "No valid ciphertype found"); break; } } static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; evp_cipher_init(cipher); EVP_CIPHER_CTX_reset(cipher->ctx); rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV); if (rc != 1){ SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptInit_ex failed"); return SSH_ERROR; } #ifdef HAVE_OPENSSL_EVP_AES_GCM /* For AES-GCM we need to set IV in specific way */ if (cipher->ciphertype == SSH_AEAD_AES128_GCM || cipher->ciphertype == SSH_AEAD_AES256_GCM) { rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, (uint8_t *)IV); if (rc != 1) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed"); return SSH_ERROR; } } #endif /* HAVE_OPENSSL_EVP_AES_GCM */ EVP_CIPHER_CTX_set_padding(cipher->ctx, 0); return SSH_OK; } static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; evp_cipher_init(cipher); EVP_CIPHER_CTX_reset(cipher->ctx); rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV); if (rc != 1){ SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptInit_ex failed"); return SSH_ERROR; } #ifdef HAVE_OPENSSL_EVP_AES_GCM /* For AES-GCM we need to set IV in specific way */ if (cipher->ciphertype == SSH_AEAD_AES128_GCM || cipher->ciphertype == SSH_AEAD_AES256_GCM) { rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, (uint8_t *)IV); if (rc != 1) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_IV_FIXED failed"); return SSH_ERROR; } } #endif /* HAVE_OPENSSL_EVP_AES_GCM */ EVP_CIPHER_CTX_set_padding(cipher->ctx, 0); return SSH_OK; } /* EVP wrapper function for encrypt/decrypt */ static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { int outlen = 0; int rc = 0; rc = EVP_EncryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, (int)len); if (rc != 1){ SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed"); return; } if (outlen != (int)len){ SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate: output size %d for %zu in", outlen, len); return; } } static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { int outlen = 0; int rc = 0; rc = EVP_DecryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, (int)len); if (rc != 1){ SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed"); return; } if (outlen != (int)len){ SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate: output size %d for %zu in", outlen, len); return; } } static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) { if (cipher->ctx != NULL) { EVP_CIPHER_CTX_free(cipher->ctx); } } #ifndef HAVE_OPENSSL_EVP_AES_CTR /* Some OS (osx, OpenIndiana, ...) have no support for CTR ciphers in EVP_aes */ struct ssh_aes_key_schedule { AES_KEY key; uint8_t IV[AES_BLOCK_SIZE]; }; static int aes_ctr_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; if (cipher->aes_key == NULL) { cipher->aes_key = malloc(sizeof (struct ssh_aes_key_schedule)); } if (cipher->aes_key == NULL) { return SSH_ERROR; } ZERO_STRUCTP(cipher->aes_key); /* CTR doesn't need a decryption key */ rc = AES_set_encrypt_key(key, cipher->keysize, &cipher->aes_key->key); if (rc < 0) { SAFE_FREE(cipher->aes_key); return SSH_ERROR; } memcpy(cipher->aes_key->IV, IV, AES_BLOCK_SIZE); return SSH_OK; } static void aes_ctr_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { unsigned char tmp_buffer[AES_BLOCK_SIZE]; unsigned int num=0; /* Some things are special with ctr128 : * In this case, tmp_buffer is not being used, because it is used to store temporary data * when an encryption is made on lengths that are not multiple of blocksize. * Same for num, which is being used to store the current offset in blocksize in CTR * function. */ #ifdef HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT CRYPTO_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num, (block128_f)AES_encrypt); #else AES_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num); #endif /* HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT */ } static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){ if (cipher != NULL) { if (cipher->aes_key != NULL) { explicit_bzero(cipher->aes_key, sizeof(*cipher->aes_key)); } SAFE_FREE(cipher->aes_key); } } #endif /* HAVE_OPENSSL_EVP_AES_CTR */ #ifdef HAVE_OPENSSL_EVP_AES_GCM static int evp_cipher_aead_get_length(struct ssh_cipher_struct *cipher, void *in, uint8_t *out, size_t len, uint64_t seq) { (void)cipher; (void)seq; /* The length is not encrypted: Copy it to the result buffer */ memcpy(out, in, len); return SSH_OK; } static void evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len, uint8_t *tag, uint64_t seq) { size_t authlen, aadlen; uint8_t lastiv[1]; int tmplen = 0; size_t outlen; int rc; (void) seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; /* increment IV */ rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_IV_GEN, 1, lastiv); if (rc == 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed"); return; } /* Pass over the authenticated data (not encrypted) */ rc = EVP_EncryptUpdate(cipher->ctx, NULL, &tmplen, (unsigned char *)in, (int)aadlen); outlen = tmplen; if (rc == 0 || outlen != aadlen) { SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data"); return; } memcpy(out, in, aadlen); /* Encrypt the rest of the data */ rc = EVP_EncryptUpdate(cipher->ctx, (unsigned char *)out + aadlen, &tmplen, (unsigned char *)in + aadlen, (int)len - aadlen); outlen = tmplen; if (rc != 1 || outlen != (int)len - aadlen) { SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed"); return; } /* compute tag */ rc = EVP_EncryptFinal(cipher->ctx, NULL, &tmplen); if (rc < 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptFinal failed: Failed to create a tag"); return; } rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_GET_TAG, authlen, (unsigned char *)tag); if (rc != 1) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_GET_TAG failed"); return; } } static int evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out, size_t encrypted_size, uint64_t seq) { size_t authlen, aadlen; uint8_t lastiv[1]; int outlen = 0; int rc = 0; (void)seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; /* increment IV */ rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_IV_GEN, 1, lastiv); if (rc == 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_IV_GEN failed"); return SSH_ERROR; } /* set tag for authentication */ rc = EVP_CIPHER_CTX_ctrl(cipher->ctx, EVP_CTRL_GCM_SET_TAG, authlen, (unsigned char *)complete_packet + aadlen + encrypted_size); if (rc == 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_CTRL_GCM_SET_TAG failed"); return SSH_ERROR; } /* Pass over the authenticated data (not encrypted) */ rc = EVP_DecryptUpdate(cipher->ctx, NULL, &outlen, (unsigned char *)complete_packet, (int)aadlen); if (rc == 0) { SSH_LOG(SSH_LOG_WARNING, "Failed to pass authenticated data"); return SSH_ERROR; } /* Do not copy the length to the target buffer, because it is already processed */ //memcpy(out, complete_packet, aadlen); /* Decrypt the rest of the data */ rc = EVP_DecryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)complete_packet + aadlen, encrypted_size /* already substracted aadlen*/); if (rc != 1) { SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed"); return SSH_ERROR; } if (outlen != (int)encrypted_size) { SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate: output size %d for %zd in", outlen, encrypted_size); return SSH_ERROR; } /* verify tag */ rc = EVP_DecryptFinal(cipher->ctx, NULL, &outlen); if (rc < 0) { SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptFinal failed: Failed authentication"); return SSH_ERROR; } return SSH_OK; } #endif /* HAVE_OPENSSL_EVP_AES_GCM */ /* * The table of supported ciphers */ static struct ssh_cipher_struct ssh_ciphertab[] = { #ifdef WITH_BLOWFISH_CIPHER { .name = "blowfish-cbc", .blocksize = 8, .ciphertype = SSH_BLOWFISH_CBC, .keysize = 128, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, #endif #ifdef HAS_AES #ifndef BROKEN_AES_CTR /* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which * increments the counter from 2^64 instead of 1. It's better not to use it */ #ifdef HAVE_OPENSSL_EVP_AES_CTR { .name = "aes128-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES128_CTR, .keysize = 128, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, { .name = "aes192-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES192_CTR, .keysize = 192, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, { .name = "aes256-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES256_CTR, .keysize = 256, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, #else /* HAVE_OPENSSL_EVP_AES_CTR */ { .name = "aes128-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES128_CTR, .keysize = 128, .set_encrypt_key = aes_ctr_set_key, .set_decrypt_key = aes_ctr_set_key, .encrypt = aes_ctr_encrypt, .decrypt = aes_ctr_encrypt, .cleanup = aes_ctr_cleanup }, { .name = "aes192-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES192_CTR, .keysize = 192, .set_encrypt_key = aes_ctr_set_key, .set_decrypt_key = aes_ctr_set_key, .encrypt = aes_ctr_encrypt, .decrypt = aes_ctr_encrypt, .cleanup = aes_ctr_cleanup }, { .name = "aes256-ctr", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES256_CTR, .keysize = 256, .set_encrypt_key = aes_ctr_set_key, .set_decrypt_key = aes_ctr_set_key, .encrypt = aes_ctr_encrypt, .decrypt = aes_ctr_encrypt, .cleanup = aes_ctr_cleanup }, #endif /* HAVE_OPENSSL_EVP_AES_CTR */ #endif /* BROKEN_AES_CTR */ { .name = "aes128-cbc", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES128_CBC, .keysize = 128, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, { .name = "aes192-cbc", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES192_CBC, .keysize = 192, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, { .name = "aes256-cbc", .blocksize = AES_BLOCK_SIZE, .ciphertype = SSH_AES256_CBC, .keysize = 256, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, #ifdef HAVE_OPENSSL_EVP_AES_GCM { .name = "aes128-gcm@openssh.com", .blocksize = AES_BLOCK_SIZE, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .ciphertype = SSH_AEAD_AES128_GCM, .keysize = 128, .tag_size = AES_GCM_TAGLEN, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .aead_encrypt = evp_cipher_aead_encrypt, .aead_decrypt_length = evp_cipher_aead_get_length, .aead_decrypt = evp_cipher_aead_decrypt, .cleanup = evp_cipher_cleanup }, { .name = "aes256-gcm@openssh.com", .blocksize = AES_BLOCK_SIZE, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .ciphertype = SSH_AEAD_AES256_GCM, .keysize = 256, .tag_size = AES_GCM_TAGLEN, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .aead_encrypt = evp_cipher_aead_encrypt, .aead_decrypt_length = evp_cipher_aead_get_length, .aead_decrypt = evp_cipher_aead_decrypt, .cleanup = evp_cipher_cleanup }, #endif /* HAVE_OPENSSL_EVP_AES_GCM */ #endif /* HAS_AES */ #ifdef HAS_DES { .name = "3des-cbc", .blocksize = 8, .ciphertype = SSH_3DES_CBC, .keysize = 192, .set_encrypt_key = evp_cipher_set_encrypt_key, .set_decrypt_key = evp_cipher_set_decrypt_key, .encrypt = evp_cipher_encrypt, .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, #endif /* HAS_DES */ { .name = "chacha20-poly1305@openssh.com" }, { .name = NULL } }; struct ssh_cipher_struct *ssh_get_ciphertab(void) { return ssh_ciphertab; } /** * @internal * @brief Initialize libcrypto's subsystem */ int ssh_crypto_init(void) { size_t i; if (libcrypto_initialized) { return SSH_OK; } if (OpenSSL_version_num() != OPENSSL_VERSION_NUMBER){ SSH_LOG(SSH_LOG_WARNING, "libssh compiled with %s " "headers, currently running with %s.", OPENSSL_VERSION_TEXT, OpenSSL_version(OpenSSL_version_num()) ); } #ifdef CAN_DISABLE_AESNI /* * disable AES-NI when running within Valgrind, because they generate * too many "uninitialized memory access" false positives */ if (RUNNING_ON_VALGRIND){ SSH_LOG(SSH_LOG_INFO, "Running within Valgrind, disabling AES-NI"); /* Bit #57 denotes AES-NI instruction set extension */ OPENSSL_ia32cap &= ~(1LL << 57); } #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif for (i = 0; ssh_ciphertab[i].name != NULL; i++) { int cmp; cmp = strcmp(ssh_ciphertab[i].name, "chacha20-poly1305@openssh.com"); if (cmp == 0) { memcpy(&ssh_ciphertab[i], ssh_get_chacha20poly1305_cipher(), sizeof(struct ssh_cipher_struct)); break; } } libcrypto_initialized = 1; return SSH_OK; } /** * @internal * @brief Finalize libcrypto's subsystem */ void ssh_crypto_finalize(void) { if (!libcrypto_initialized) { return; } #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); #endif libcrypto_initialized = 0; } #endif /* LIBCRYPTO */ ================================================ FILE: src/libssh/src/libgcrypt.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * Copyright (C) 2016 g10 Code GmbH * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/wrapper.h" #include "libssh/string.h" #include "libssh/misc.h" #ifdef HAVE_LIBGCRYPT #include static int libgcrypt_initialized = 0; static int alloc_key(struct ssh_cipher_struct *cipher) { cipher->key = malloc(cipher->keylen); if (cipher->key == NULL) { return -1; } return 0; } void ssh_reseed(void){ } int ssh_get_random(void *where, int len, int strong) { /* variable not used in gcrypt */ (void) strong; /* not using GCRY_VERY_STRONG_RANDOM which is a bit overkill */ gcry_randomize(where,len,GCRY_STRONG_RANDOM); return 1; } SHACTX sha1_init(void) { SHACTX ctx = NULL; gcry_md_open(&ctx, GCRY_MD_SHA1, 0); return ctx; } void sha1_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); } void sha1_final(unsigned char *md, SHACTX c) { gcry_md_final(c); memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN); gcry_md_close(c); } void sha1(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len); } #ifdef HAVE_GCRYPT_ECC static int nid_to_md_algo(int nid) { switch (nid) { case NID_gcrypt_nistp256: return GCRY_MD_SHA256; case NID_gcrypt_nistp384: return GCRY_MD_SHA384; case NID_gcrypt_nistp521: return GCRY_MD_SHA512; } return GCRY_MD_NONE; } void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) { int algo = nid_to_md_algo(nid); /* Note: What gcrypt calls 'hash' is called 'digest' here and vice-versa. */ gcry_md_hash_buffer(algo, hash, digest, len); *hlen = gcry_md_get_algo_dlen(algo); } EVPCTX evp_init(int nid) { gcry_error_t err; int algo = nid_to_md_algo(nid); EVPCTX ctx; err = gcry_md_open(&ctx, algo, 0); if (err) { return NULL; } return ctx; } void evp_update(EVPCTX ctx, const void *data, unsigned long len) { gcry_md_write(ctx, data, len); } void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) { int algo = gcry_md_get_algo(ctx); *mdlen = gcry_md_get_algo_dlen(algo); memcpy(md, gcry_md_read(ctx, algo), *mdlen); gcry_md_close(ctx); } #endif SHA256CTX sha256_init(void) { SHA256CTX ctx = NULL; gcry_md_open(&ctx, GCRY_MD_SHA256, 0); return ctx; } void sha256_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); } void sha256_final(unsigned char *md, SHACTX c) { gcry_md_final(c); memcpy(md, gcry_md_read(c, 0), SHA256_DIGEST_LEN); gcry_md_close(c); } void sha256(const unsigned char *digest, int len, unsigned char *hash){ gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len); } SHA384CTX sha384_init(void) { SHA384CTX ctx = NULL; gcry_md_open(&ctx, GCRY_MD_SHA384, 0); return ctx; } void sha384_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); } void sha384_final(unsigned char *md, SHACTX c) { gcry_md_final(c); memcpy(md, gcry_md_read(c, 0), SHA384_DIGEST_LEN); gcry_md_close(c); } void sha384(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA384, hash, digest, len); } SHA512CTX sha512_init(void) { SHA512CTX ctx = NULL; gcry_md_open(&ctx, GCRY_MD_SHA512, 0); return ctx; } void sha512_update(SHACTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); } void sha512_final(unsigned char *md, SHACTX c) { gcry_md_final(c); memcpy(md, gcry_md_read(c, 0), SHA512_DIGEST_LEN); gcry_md_close(c); } void sha512(const unsigned char *digest, int len, unsigned char *hash) { gcry_md_hash_buffer(GCRY_MD_SHA512, hash, digest, len); } MD5CTX md5_init(void) { MD5CTX c = NULL; gcry_md_open(&c, GCRY_MD_MD5, 0); return c; } void md5_update(MD5CTX c, const void *data, unsigned long len) { gcry_md_write(c,data,len); } void md5_final(unsigned char *md, MD5CTX c) { gcry_md_final(c); memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN); gcry_md_close(c); } int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { return sshkdf_derive_key(crypto, key, key_len, key_type, output, requested_len); } HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { HMACCTX c = NULL; switch(type) { case SSH_HMAC_SHA1: gcry_md_open(&c, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); break; case SSH_HMAC_SHA256: gcry_md_open(&c, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); break; case SSH_HMAC_SHA512: gcry_md_open(&c, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); break; case SSH_HMAC_MD5: gcry_md_open(&c, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC); break; default: c = NULL; } gcry_md_setkey(c, key, len); return c; } void hmac_update(HMACCTX c, const void *data, unsigned long len) { gcry_md_write(c, data, len); } void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) { *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c)); memcpy(hashmacbuf, gcry_md_read(c, 0), *len); gcry_md_close(c); } #ifdef WITH_BLOWFISH_CIPHER /* the wrapper functions for blowfish */ static int blowfish_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV){ if (cipher->key == NULL) { if (alloc_key(cipher) < 0) { return -1; } if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0)) { SAFE_FREE(cipher->key); return -1; } if (gcry_cipher_setkey(cipher->key[0], key, 16)) { SAFE_FREE(cipher->key); return -1; } if (gcry_cipher_setiv(cipher->key[0], IV, 8)) { SAFE_FREE(cipher->key); return -1; } } return 0; } static void blowfish_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { gcry_cipher_encrypt(cipher->key[0], out, len, in, len); } static void blowfish_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { gcry_cipher_decrypt(cipher->key[0], out, len, in, len); } #endif /* WITH_BLOWFISH_CIPHER */ static int aes_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int mode=GCRY_CIPHER_MODE_CBC; if (cipher->key == NULL) { if (alloc_key(cipher) < 0) { return -1; } if(strstr(cipher->name,"-ctr")) mode=GCRY_CIPHER_MODE_CTR; if (strstr(cipher->name, "-gcm")) mode = GCRY_CIPHER_MODE_GCM; switch (cipher->keysize) { case 128: if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES128, mode, 0)) { SAFE_FREE(cipher->key); return -1; } break; case 192: if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES192, mode, 0)) { SAFE_FREE(cipher->key); return -1; } break; case 256: if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_AES256, mode, 0)) { SAFE_FREE(cipher->key); return -1; } break; default: SSH_LOG(SSH_LOG_WARNING, "Unksupported key length %u.", cipher->keysize); SAFE_FREE(cipher->key); return -1; } if (gcry_cipher_setkey(cipher->key[0], key, cipher->keysize / 8)) { SAFE_FREE(cipher->key); return -1; } if(mode == GCRY_CIPHER_MODE_CBC){ if (gcry_cipher_setiv(cipher->key[0], IV, 16)) { SAFE_FREE(cipher->key); return -1; } } else if (mode == GCRY_CIPHER_MODE_GCM) { /* Store the IV so we can handle the packet counter increments later * The IV is passed to the cipher context later. */ memcpy(cipher->last_iv, IV, AES_GCM_IVLEN); } else { if(gcry_cipher_setctr(cipher->key[0],IV,16)){ SAFE_FREE(cipher->key); return -1; } } } return 0; } static void aes_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { gcry_cipher_encrypt(cipher->key[0], out, len, in, len); } static void aes_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { gcry_cipher_decrypt(cipher->key[0], out, len, in, len); } static int aes_aead_get_length(struct ssh_cipher_struct *cipher, void *in, uint8_t *out, size_t len, uint64_t seq) { (void)cipher; (void)seq; /* The length is not encrypted: Copy it to the result buffer */ memcpy(out, in, len); return SSH_OK; } static void aes_gcm_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len, uint8_t *tag, uint64_t seq) { gpg_error_t err; size_t aadlen, authlen; (void)seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; /* increment IV */ err = gcry_cipher_setiv(cipher->key[0], cipher->last_iv, AES_GCM_IVLEN); /* This actualy does not increment the packet counter for the * current encryption operation, but for the next one. The first * operation needs to be completed with the derived IV. * * The IV buffer has the following structure: * [ 4B static IV ][ 8B packet counter ][ 4B block counter ] */ uint64_inc(cipher->last_iv + 4); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s", gpg_strerror(err)); return; } /* Pass the authenticated data (packet_length) */ err = gcry_cipher_authenticate(cipher->key[0], in, aadlen); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s", gpg_strerror(err)); return; } memcpy(out, in, aadlen); /* Encrypt the rest of the data */ err = gcry_cipher_encrypt(cipher->key[0], (unsigned char *)out + aadlen, len - aadlen, (unsigned char *)in + aadlen, len - aadlen); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_encrypt failed: %s", gpg_strerror(err)); return; } /* Calculate the tag */ err = gcry_cipher_gettag(cipher->key[0], (void *)tag, authlen); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_gettag failed: %s", gpg_strerror(err)); return; } } static int aes_gcm_decrypt(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out, size_t encrypted_size, uint64_t seq) { gpg_error_t err; size_t aadlen, authlen; (void)seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; /* increment IV */ err = gcry_cipher_setiv(cipher->key[0], cipher->last_iv, AES_GCM_IVLEN); /* This actualy does not increment the packet counter for the * current encryption operation, but for the next one. The first * operation needs to be completed with the derived IV. * * The IV buffer has the following structure: * [ 4B static IV ][ 8B packet counter ][ 4B block counter ] */ uint64_inc(cipher->last_iv + 4); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_setiv failed: %s", gpg_strerror(err)); return SSH_ERROR; } /* Pass the authenticated data (packet_length) */ err = gcry_cipher_authenticate(cipher->key[0], complete_packet, aadlen); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_authenticate failed: %s", gpg_strerror(err)); return SSH_ERROR; } /* Do not copy the length to the target buffer, because it is already processed */ //memcpy(out, complete_packet, aadlen); /* Encrypt the rest of the data */ err = gcry_cipher_decrypt(cipher->key[0], out, encrypted_size, (unsigned char *)complete_packet + aadlen, encrypted_size); if (err) { SSH_LOG(SSH_LOG_WARNING, "gcry_cipher_decrypt failed: %s", gpg_strerror(err)); return SSH_ERROR; } /* Check the tag */ err = gcry_cipher_checktag(cipher->key[0], (unsigned char *)complete_packet + aadlen + encrypted_size, authlen); if (gpg_err_code(err) == GPG_ERR_CHECKSUM) { SSH_LOG(SSH_LOG_WARNING, "The authentication tag does not match"); return SSH_ERROR; } else if (err != GPG_ERR_NO_ERROR) { SSH_LOG(SSH_LOG_WARNING, "General error while decryption: %s", gpg_strerror(err)); return SSH_ERROR; } return SSH_OK; } static int des3_set_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { if (cipher->key == NULL) { if (alloc_key(cipher) < 0) { return -1; } if (gcry_cipher_open(&cipher->key[0], GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0)) { SAFE_FREE(cipher->key); return -1; } if (gcry_cipher_setkey(cipher->key[0], key, 24)) { SAFE_FREE(cipher->key); return -1; } if (gcry_cipher_setiv(cipher->key[0], IV, 8)) { SAFE_FREE(cipher->key); return -1; } } return 0; } static void des3_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { gcry_cipher_encrypt(cipher->key[0], out, len, in, len); } static void des3_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { gcry_cipher_decrypt(cipher->key[0], out, len, in, len); } /* the table of supported ciphers */ static struct ssh_cipher_struct ssh_ciphertab[] = { #ifdef WITH_BLOWFISH_CIPHER { .name = "blowfish-cbc", .blocksize = 8, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 128, .set_encrypt_key = blowfish_set_key, .set_decrypt_key = blowfish_set_key, .encrypt = blowfish_encrypt, .decrypt = blowfish_decrypt }, #endif /* WITH_BLOWFISH_CIPHER */ { .name = "aes128-ctr", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 128, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_encrypt }, { .name = "aes192-ctr", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 192, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_encrypt }, { .name = "aes256-ctr", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 256, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_encrypt }, { .name = "aes128-cbc", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 128, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_decrypt }, { .name = "aes192-cbc", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 192, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_decrypt }, { .name = "aes256-cbc", .blocksize = 16, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 256, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .encrypt = aes_encrypt, .decrypt = aes_decrypt }, { .name = "aes128-gcm@openssh.com", .blocksize = 16, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 128, .tag_size = AES_GCM_TAGLEN, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .aead_encrypt = aes_gcm_encrypt, .aead_decrypt_length = aes_aead_get_length, .aead_decrypt = aes_gcm_decrypt, }, { .name = "aes256-gcm@openssh.com", .blocksize = 16, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 256, .tag_size = AES_GCM_TAGLEN, .set_encrypt_key = aes_set_key, .set_decrypt_key = aes_set_key, .aead_encrypt = aes_gcm_encrypt, .aead_decrypt_length = aes_aead_get_length, .aead_decrypt = aes_gcm_decrypt, }, { .name = "3des-cbc", .blocksize = 8, .keylen = sizeof(gcry_cipher_hd_t), .key = NULL, .keysize = 192, .set_encrypt_key = des3_set_key, .set_decrypt_key = des3_set_key, .encrypt = des3_encrypt, .decrypt = des3_decrypt }, { .name = "chacha20-poly1305@openssh.com" }, { .name = NULL, .blocksize = 0, .keylen = 0, .key = NULL, .keysize = 0, .set_encrypt_key = NULL, .set_decrypt_key = NULL, .encrypt = NULL, .decrypt = NULL } }; struct ssh_cipher_struct *ssh_get_ciphertab(void) { return ssh_ciphertab; } /* * Extract an MPI from the given s-expression SEXP named NAME which is * encoded using INFORMAT and store it in a newly allocated ssh_string * encoded using OUTFORMAT. */ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp, const char *name, enum gcry_mpi_format informat, enum gcry_mpi_format outformat) { gpg_error_t err; ssh_string result = NULL; gcry_sexp_t fragment = NULL; gcry_mpi_t mpi = NULL; size_t size; fragment = gcry_sexp_find_token(sexp, name, 0); if (fragment == NULL) { goto fail; } mpi = gcry_sexp_nth_mpi(fragment, 1, informat); if (mpi == NULL) { goto fail; } err = gcry_mpi_print(outformat, NULL, 0, &size, mpi); if (err != 0) { goto fail; } result = ssh_string_new(size); if (result == NULL) { goto fail; } err = gcry_mpi_print(outformat, ssh_string_data(result), size, NULL, mpi); if (err != 0) { ssh_string_burn(result); SSH_STRING_FREE(result); result = NULL; goto fail; } fail: gcry_sexp_release(fragment); gcry_mpi_release(mpi); return result; } /** * @internal * * @brief Initialize libgcrypt's subsystem */ int ssh_crypto_init(void) { size_t i; if (libgcrypt_initialized) { return SSH_OK; } gcry_check_version(NULL); /* While the secure memory is not set up */ gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P, 0)) { gcry_control(GCRYCTL_INIT_SECMEM, 4096); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); } /* Re-enable warning */ gcry_control (GCRYCTL_RESUME_SECMEM_WARN); for (i = 0; ssh_ciphertab[i].name != NULL; i++) { int cmp; cmp = strcmp(ssh_ciphertab[i].name, "chacha20-poly1305@openssh.com"); if (cmp == 0) { memcpy(&ssh_ciphertab[i], ssh_get_chacha20poly1305_cipher(), sizeof(struct ssh_cipher_struct)); break; } } libgcrypt_initialized = 1; return SSH_OK; } /** * @internal * * @brief Finalize libgcrypt's subsystem */ void ssh_crypto_finalize(void) { if (!libgcrypt_initialized) { return; } gcry_control(GCRYCTL_TERM_SECMEM); libgcrypt_initialized = 0; } #endif ================================================ FILE: src/libssh/src/libmbedcrypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2017 Sartura d.o.o. * * Author: Juraj Vijtiuk * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/wrapper.h" #include "libssh/crypto.h" #include "libssh/priv.h" #include "libssh/misc.h" #ifdef HAVE_LIBMBEDCRYPTO #include #ifdef MBEDTLS_GCM_C #include #endif /* MBEDTLS_GCM_C */ static mbedtls_entropy_context ssh_mbedtls_entropy; static mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg; static int libmbedcrypto_initialized = 0; void ssh_reseed(void) { mbedtls_ctr_drbg_reseed(&ssh_mbedtls_ctr_drbg, NULL, 0); } int ssh_get_random(void *where, int len, int strong) { return ssh_mbedtls_random(where, len, strong); } SHACTX sha1_init(void) { SHACTX ctx = NULL; int rc; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void sha1_update(SHACTX c, const void *data, unsigned long len) { mbedtls_md_update(c, data, len); } void sha1_final(unsigned char *md, SHACTX c) { mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } void sha1(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); if (md_info != NULL) { mbedtls_md(md_info, digest, len, hash); } } static mbedtls_md_type_t nid_to_md_algo(int nid) { switch (nid) { case NID_mbedtls_nistp256: return MBEDTLS_MD_SHA256; case NID_mbedtls_nistp384: return MBEDTLS_MD_SHA384; case NID_mbedtls_nistp521: return MBEDTLS_MD_SHA512; } return MBEDTLS_MD_NONE; } void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen) { mbedtls_md_type_t algo = nid_to_md_algo(nid); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(algo); if (md_info != NULL) { *hlen = mbedtls_md_get_size(md_info); mbedtls_md(md_info, digest, len, hash); } } EVPCTX evp_init(int nid) { EVPCTX ctx = NULL; int rc; mbedtls_md_type_t algo = nid_to_md_algo(nid); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(algo); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void evp_update(EVPCTX ctx, const void *data, unsigned long len) { mbedtls_md_update(ctx, data, len); } void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen) { *mdlen = mbedtls_md_get_size(ctx->md_info); mbedtls_md_finish(ctx, md); mbedtls_md_free(ctx); SAFE_FREE(ctx); } SHA256CTX sha256_init(void) { SHA256CTX ctx = NULL; int rc; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if(ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void sha256_update(SHA256CTX c, const void *data, unsigned long len) { mbedtls_md_update(c, data, len); } void sha256_final(unsigned char *md, SHA256CTX c) { mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } void sha256(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); if (md_info != NULL) { mbedtls_md(md_info, digest, len, hash); } } SHA384CTX sha384_init(void) { SHA384CTX ctx = NULL; int rc; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void sha384_update(SHA384CTX c, const void *data, unsigned long len) { mbedtls_md_update(c, data, len); } void sha384_final(unsigned char *md, SHA384CTX c) { mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } void sha384(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); if (md_info != NULL) { mbedtls_md(md_info, digest, len, hash); } } SHA512CTX sha512_init(void) { SHA512CTX ctx = NULL; int rc; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void sha512_update(SHA512CTX c, const void *data, unsigned long len) { mbedtls_md_update(c, data, len); } void sha512_final(unsigned char *md, SHA512CTX c) { mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } void sha512(const unsigned char *digest, int len, unsigned char *hash) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); if (md_info != NULL) { mbedtls_md(md_info, digest, len, hash); } } MD5CTX md5_init(void) { MD5CTX ctx = NULL; int rc; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); if (md_info == NULL) { return NULL; } ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } mbedtls_md_init(ctx); rc = mbedtls_md_setup(ctx, md_info, 0); if (rc != 0) { SAFE_FREE(ctx); return NULL; } rc = mbedtls_md_starts(ctx); if (rc != 0) { SAFE_FREE(ctx); return NULL; } return ctx; } void md5_update(MD5CTX c, const void *data, unsigned long len) { mbedtls_md_update(c, data, len); } void md5_final(unsigned char *md, MD5CTX c) { mbedtls_md_finish(c, md); mbedtls_md_free(c); SAFE_FREE(c); } int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { return sshkdf_derive_key(crypto, key, key_len, key_type, output, requested_len); } HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) { HMACCTX ctx = NULL; const mbedtls_md_info_t *md_info = NULL; int rc; ctx = malloc(sizeof(mbedtls_md_context_t)); if (ctx == NULL) { return NULL; } switch (type) { case SSH_HMAC_SHA1: md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); break; case SSH_HMAC_SHA256: md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); break; case SSH_HMAC_SHA512: md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); break; default: goto error; } mbedtls_md_init(ctx); if (md_info == NULL) { goto error; } rc = mbedtls_md_setup(ctx, md_info, 1); if (rc != 0) { goto error; } rc = mbedtls_md_hmac_starts(ctx, key, len); if (rc != 0) { goto error; } return ctx; error: mbedtls_md_free(ctx); SAFE_FREE(ctx); return NULL; } void hmac_update(HMACCTX c, const void *data, unsigned long len) { mbedtls_md_hmac_update(c, data, len); } void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) { *len = mbedtls_md_get_size(c->md_info); mbedtls_md_hmac_finish(c, hashmacbuf); mbedtls_md_free(c); SAFE_FREE(c); } static int cipher_init(struct ssh_cipher_struct *cipher, mbedtls_operation_t operation, void *key, void *IV) { const mbedtls_cipher_info_t *cipher_info = NULL; mbedtls_cipher_context_t *ctx; int rc; if (operation == MBEDTLS_ENCRYPT) { ctx = &cipher->encrypt_ctx; } else if (operation == MBEDTLS_DECRYPT) { ctx = &cipher->decrypt_ctx; } else { SSH_LOG(SSH_LOG_WARNING, "unknown operation"); return 1; } mbedtls_cipher_init(ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); rc = mbedtls_cipher_setup(ctx, cipher_info); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed"); goto error; } rc = mbedtls_cipher_setkey(ctx, key, cipher_info->key_bitlen, operation); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } rc = mbedtls_cipher_set_iv(ctx, IV, cipher_info->iv_size); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); goto error; } return 0; error: mbedtls_cipher_free(ctx); return 1; } static int cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); goto error; } rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: return SSH_ERROR; } static int cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; rc = cipher_init(cipher, MBEDTLS_ENCRYPT, key, IV); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); goto error; } /* libssh only encypts and decrypts packets that are multiples of a block * size, and no padding is used */ rc = mbedtls_cipher_set_padding_mode(&cipher->encrypt_ctx, MBEDTLS_PADDING_NONE); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); goto error; } rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->encrypt_ctx); return SSH_ERROR; } #ifdef MBEDTLS_GCM_C static int cipher_set_key_gcm(struct ssh_cipher_struct *cipher, void *key, void *IV) { const mbedtls_cipher_info_t *cipher_info = NULL; int rc; mbedtls_gcm_init(&cipher->gcm_ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); rc = mbedtls_gcm_setkey(&cipher->gcm_ctx, MBEDTLS_CIPHER_ID_AES, key, cipher_info->key_bitlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_setkey failed"); goto error; } /* Store the IV so we can increment the packet counter later */ memcpy(cipher->last_iv, IV, AES_GCM_IVLEN); return 0; error: mbedtls_gcm_free(&cipher->gcm_ctx); return 1; } #endif /* MBEDTLS_GCM_C */ static int cipher_set_decrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); goto error; } mbedtls_cipher_reset(&cipher->decrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->decrypt_ctx); return SSH_ERROR; } static int cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key, void *IV) { int rc; rc = cipher_init(cipher, MBEDTLS_DECRYPT, key, IV); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "cipher_init failed"); goto error; } rc = mbedtls_cipher_set_padding_mode(&cipher->decrypt_ctx, MBEDTLS_PADDING_NONE); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); goto error; } mbedtls_cipher_reset(&cipher->decrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->decrypt_ctx); return SSH_ERROR; } static void cipher_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { size_t outlen = 0; size_t total_len = 0; int rc = 0; rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption"); return; } total_len += outlen; if (total_len == len) { return; } rc = mbedtls_cipher_finish(&cipher->encrypt_ctx, (unsigned char *) out + outlen, &outlen); total_len += outlen; if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during encryption"); return; } if (total_len != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } } static void cipher_encrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { size_t outlen = 0; int rc = 0; rc = mbedtls_cipher_update(&cipher->encrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during encryption"); return; } if (outlen != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } } static void cipher_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len) { size_t outlen = 0; int rc = 0; size_t total_len = 0; rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption"); return; } total_len += outlen; if (total_len == len) { return; } rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, (unsigned char *) out + outlen, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption"); return; } total_len += outlen; if (total_len != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } } static void cipher_decrypt_cbc(struct ssh_cipher_struct *cipher, void *in, void *out, unsigned long len) { size_t outlen = 0; int rc = 0; rc = mbedtls_cipher_update(&cipher->decrypt_ctx, in, len, out, &outlen); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update failed during decryption"); return; } /* MbedTLS caches the last block when decrypting with cbc. * By calling finish the block is flushed to out, however the unprocessed * data counter is not reset. * Calling mbedtls_cipher_reset resets the unprocessed data counter. */ if (outlen == 0) { rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, out, &outlen); } else if (outlen == len) { return; } else { rc = mbedtls_cipher_finish(&cipher->decrypt_ctx, (unsigned char *) out + outlen , &outlen); } if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_finish failed during decryption"); return; } rc = mbedtls_cipher_reset(&cipher->decrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed during decryption"); return; } if (outlen != len) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_update: output size %zu for %zu", outlen, len); return; } } #ifdef MBEDTLS_GCM_C static int cipher_gcm_get_length(struct ssh_cipher_struct *cipher, void *in, uint8_t *out, size_t len, uint64_t seq) { (void)cipher; (void)seq; /* The length is not encrypted: Copy it to the result buffer */ memcpy(out, in, len); return SSH_OK; } static void cipher_encrypt_gcm(struct ssh_cipher_struct *cipher, void *in, void *out, size_t len, uint8_t *tag, uint64_t seq) { size_t authlen, aadlen; int rc; (void) seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; /* The length is not encrypted */ memcpy(out, in, aadlen); rc = mbedtls_gcm_crypt_and_tag(&cipher->gcm_ctx, MBEDTLS_GCM_ENCRYPT, len - aadlen, /* encrypted data len */ cipher->last_iv, /* IV */ AES_GCM_IVLEN, in, /* aad */ aadlen, (const unsigned char *)in + aadlen, /* input */ (unsigned char *)out + aadlen, /* output */ authlen, tag); /* tag */ if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_crypt_and_tag failed"); return; } /* Increment the IV for the next invocation */ uint64_inc(cipher->last_iv + 4); } static int cipher_decrypt_gcm(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out, size_t encrypted_size, uint64_t seq) { size_t authlen, aadlen; int rc; (void) seq; aadlen = cipher->lenfield_blocksize; authlen = cipher->tag_size; rc = mbedtls_gcm_auth_decrypt(&cipher->gcm_ctx, encrypted_size, /* encrypted data len */ cipher->last_iv, /* IV */ AES_GCM_IVLEN, complete_packet, /* aad */ aadlen, (const uint8_t *)complete_packet + aadlen + encrypted_size, /* tag */ authlen, (const uint8_t *)complete_packet + aadlen, /* input */ (unsigned char *)out); /* output */ if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_gcm_auth_decrypt failed"); return SSH_ERROR; } /* Increment the IV for the next invocation */ uint64_inc(cipher->last_iv + 4); return SSH_OK; } #endif /* MBEDTLS_GCM_C */ static void cipher_cleanup(struct ssh_cipher_struct *cipher) { mbedtls_cipher_free(&cipher->encrypt_ctx); mbedtls_cipher_free(&cipher->decrypt_ctx); #ifdef MBEDTLS_GCM_C mbedtls_gcm_free(&cipher->gcm_ctx); #endif /* MBEDTLS_GCM_C */ } static struct ssh_cipher_struct ssh_ciphertab[] = { #ifdef WITH_BLOWFISH_CIPHER { .name = "blowfish-cbc", .blocksize = 8, .keysize = 128, .type = MBEDTLS_CIPHER_BLOWFISH_CBC, .set_encrypt_key = cipher_set_encrypt_key_cbc, .set_decrypt_key = cipher_set_decrypt_key_cbc, .encrypt = cipher_encrypt_cbc, .decrypt = cipher_decrypt_cbc, .cleanup = cipher_cleanup }, #endif /* WITH_BLOWFISH_CIPHER */ { .name = "aes128-ctr", .blocksize = 16, .keysize = 128, .type = MBEDTLS_CIPHER_AES_128_CTR, .set_encrypt_key = cipher_set_encrypt_key, .set_decrypt_key = cipher_set_decrypt_key, .encrypt = cipher_encrypt, .decrypt = cipher_decrypt, .cleanup = cipher_cleanup }, { .name = "aes192-ctr", .blocksize = 16, .keysize = 192, .type = MBEDTLS_CIPHER_AES_192_CTR, .set_encrypt_key = cipher_set_encrypt_key, .set_decrypt_key = cipher_set_decrypt_key, .encrypt = cipher_encrypt, .decrypt = cipher_decrypt, .cleanup = cipher_cleanup }, { .name = "aes256-ctr", .blocksize = 16, .keysize = 256, .type = MBEDTLS_CIPHER_AES_256_CTR, .set_encrypt_key = cipher_set_encrypt_key, .set_decrypt_key = cipher_set_decrypt_key, .encrypt = cipher_encrypt, .decrypt = cipher_decrypt, .cleanup = cipher_cleanup }, { .name = "aes128-cbc", .blocksize = 16, .keysize = 128, .type = MBEDTLS_CIPHER_AES_128_CBC, .set_encrypt_key = cipher_set_encrypt_key_cbc, .set_decrypt_key = cipher_set_decrypt_key_cbc, .encrypt = cipher_encrypt_cbc, .decrypt = cipher_decrypt_cbc, .cleanup = cipher_cleanup }, { .name = "aes192-cbc", .blocksize = 16, .keysize = 192, .type = MBEDTLS_CIPHER_AES_192_CBC, .set_encrypt_key = cipher_set_encrypt_key_cbc, .set_decrypt_key = cipher_set_decrypt_key_cbc, .encrypt = cipher_encrypt_cbc, .decrypt = cipher_decrypt_cbc, .cleanup = cipher_cleanup }, { .name = "aes256-cbc", .blocksize = 16, .keysize = 256, .type = MBEDTLS_CIPHER_AES_256_CBC, .set_encrypt_key = cipher_set_encrypt_key_cbc, .set_decrypt_key = cipher_set_decrypt_key_cbc, .encrypt = cipher_encrypt_cbc, .decrypt = cipher_decrypt_cbc, .cleanup = cipher_cleanup }, #ifdef MBEDTLS_GCM_C { .name = "aes128-gcm@openssh.com", .blocksize = 16, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .keysize = 128, .tag_size = AES_GCM_TAGLEN, .type = MBEDTLS_CIPHER_AES_128_GCM, .set_encrypt_key = cipher_set_key_gcm, .set_decrypt_key = cipher_set_key_gcm, .aead_encrypt = cipher_encrypt_gcm, .aead_decrypt_length = cipher_gcm_get_length, .aead_decrypt = cipher_decrypt_gcm, .cleanup = cipher_cleanup }, { .name = "aes256-gcm@openssh.com", .blocksize = 16, .lenfield_blocksize = 4, /* not encrypted, but authenticated */ .keysize = 256, .tag_size = AES_GCM_TAGLEN, .type = MBEDTLS_CIPHER_AES_256_GCM, .set_encrypt_key = cipher_set_key_gcm, .set_decrypt_key = cipher_set_key_gcm, .aead_encrypt = cipher_encrypt_gcm, .aead_decrypt_length = cipher_gcm_get_length, .aead_decrypt = cipher_decrypt_gcm, .cleanup = cipher_cleanup }, #endif /* MBEDTLS_GCM_C */ { .name = "3des-cbc", .blocksize = 8, .keysize = 192, .type = MBEDTLS_CIPHER_DES_EDE3_CBC, .set_encrypt_key = cipher_set_encrypt_key_cbc, .set_decrypt_key = cipher_set_decrypt_key_cbc, .encrypt = cipher_encrypt_cbc, .decrypt = cipher_decrypt_cbc, .cleanup = cipher_cleanup }, { .name = "chacha20-poly1305@openssh.com" }, { .name = NULL, .blocksize = 0, .keysize = 0, .set_encrypt_key = NULL, .set_decrypt_key = NULL, .encrypt = NULL, .decrypt = NULL, .cleanup = NULL } }; struct ssh_cipher_struct *ssh_get_ciphertab(void) { return ssh_ciphertab; } int ssh_crypto_init(void) { size_t i; int rc; if (libmbedcrypto_initialized) { return SSH_OK; } mbedtls_entropy_init(&ssh_mbedtls_entropy); mbedtls_ctr_drbg_init(&ssh_mbedtls_ctr_drbg); rc = mbedtls_ctr_drbg_seed(&ssh_mbedtls_ctr_drbg, mbedtls_entropy_func, &ssh_mbedtls_entropy, NULL, 0); if (rc != 0) { mbedtls_ctr_drbg_free(&ssh_mbedtls_ctr_drbg); } for (i = 0; ssh_ciphertab[i].name != NULL; i++) { int cmp; cmp = strcmp(ssh_ciphertab[i].name, "chacha20-poly1305@openssh.com"); if (cmp == 0) { memcpy(&ssh_ciphertab[i], ssh_get_chacha20poly1305_cipher(), sizeof(struct ssh_cipher_struct)); break; } } libmbedcrypto_initialized = 1; return SSH_OK; } int ssh_mbedtls_random(void *where, int len, int strong) { int rc = 0; if (strong) { mbedtls_ctr_drbg_set_prediction_resistance(&ssh_mbedtls_ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON); rc = mbedtls_ctr_drbg_random(&ssh_mbedtls_ctr_drbg, where, len); mbedtls_ctr_drbg_set_prediction_resistance(&ssh_mbedtls_ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF); } else { rc = mbedtls_ctr_drbg_random(&ssh_mbedtls_ctr_drbg, where, len); } return !rc; } mbedtls_ctr_drbg_context *ssh_get_mbedtls_ctr_drbg_context(void) { return &ssh_mbedtls_ctr_drbg; } void ssh_crypto_finalize(void) { if (!libmbedcrypto_initialized) { return; } mbedtls_ctr_drbg_free(&ssh_mbedtls_ctr_drbg); mbedtls_entropy_free(&ssh_mbedtls_entropy); libmbedcrypto_initialized = 0; } #endif /* HAVE_LIBMBEDCRYPTO */ ================================================ FILE: src/libssh/src/log.c ================================================ /* * log.c - logging and debugging functions * * This file is part of the SSH Library * * Copyright (c) 2008-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #ifdef HAVE_SYS_UTIME_H #include #endif /* HAVE_SYS_UTIME_H */ #include #include "libssh/priv.h" #include "libssh/misc.h" #include "libssh/session.h" static LIBSSH_THREAD int ssh_log_level; static LIBSSH_THREAD ssh_logging_callback ssh_log_cb; static LIBSSH_THREAD void *ssh_log_userdata; /** * @defgroup libssh_log The SSH logging functions. * @ingroup libssh * * Logging functions for debugging and problem resolving. * * @{ */ static int current_timestring(int hires, char *buf, size_t len) { char tbuf[64]; struct timeval tv; struct tm *tm; time_t t; gettimeofday(&tv, NULL); t = (time_t) tv.tv_sec; tm = localtime(&t); if (tm == NULL) { return -1; } if (hires) { strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm); snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec); } else { strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm); snprintf(buf, len, "%s", tbuf); } return 0; } static void ssh_log_stderr(int verbosity, const char *function, const char *buffer) { char date[128] = {0}; int rc; rc = current_timestring(1, date, sizeof(date)); if (rc == 0) { fprintf(stderr, "[%s, %d] %s:", date, verbosity, function); } else { fprintf(stderr, "[%d] %s", verbosity, function); } fprintf(stderr, " %s\n", buffer); } void ssh_log_function(int verbosity, const char *function, const char *buffer) { ssh_logging_callback log_fn = ssh_get_log_callback(); if (log_fn) { char buf[1024]; snprintf(buf, sizeof(buf), "%s: %s", function, buffer); log_fn(verbosity, function, buf, ssh_get_log_userdata()); return; } ssh_log_stderr(verbosity, function, buffer); } void _ssh_log(int verbosity, const char *function, const char *format, ...) { char buffer[1024]; va_list va; if (verbosity <= ssh_get_log_level()) { va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); ssh_log_function(verbosity, function, buffer); } } /* LEGACY */ void ssh_log(ssh_session session, int verbosity, const char *format, ...) { char buffer[1024]; va_list va; if (verbosity <= session->common.log_verbosity) { va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); ssh_log_function(verbosity, "", buffer); } } /** @internal * @brief log a SSH event with a common pointer * @param common The SSH/bind session. * @param verbosity The verbosity of the event. * @param format The format string of the log entry. */ void ssh_log_common(struct ssh_common_struct *common, int verbosity, const char *function, const char *format, ...) { char buffer[1024]; va_list va; if (verbosity <= common->log_verbosity) { va_start(va, format); vsnprintf(buffer, sizeof(buffer), format, va); va_end(va); ssh_log_function(verbosity, function, buffer); } } /* PUBLIC */ /** * @brief Set the log level of the library. * * @param[in] level The level to set. * * @return SSH_OK on success, SSH_ERROR on error. */ int ssh_set_log_level(int level) { if (level < 0) { return SSH_ERROR; } ssh_log_level = level; return SSH_OK; } /** * @brief Get the log level of the library. * * @return The value of the log level. */ int ssh_get_log_level(void) { return ssh_log_level; } int ssh_set_log_callback(ssh_logging_callback cb) { if (cb == NULL) { return SSH_ERROR; } ssh_log_cb = cb; return SSH_OK; } ssh_logging_callback ssh_get_log_callback(void) { return ssh_log_cb; } /** * @brief Get the userdata of the logging function. * * @return The userdata if set or NULL. */ void *ssh_get_log_userdata(void) { if (ssh_log_userdata == NULL) { return NULL; } return ssh_log_userdata; } /** * @brief Set the userdata for the logging function. * * @param[in] data The userdata to set. * * @return SSH_OK on success. */ int ssh_set_log_userdata(void *data) { ssh_log_userdata = data; return 0; } /** @} */ ================================================ FILE: src/libssh/src/match.c ================================================ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Simple pattern matching, with '*' and '?' as wildcards. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 2000 Markus Friedl. 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 ``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 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. */ #include "config.h" #include #include #include #include "libssh/priv.h" #define MAX_MATCH_RECURSION 32 /* * Returns true if the given string matches the pattern (which may contain ? * and * as wildcards), and zero if it does not match. */ static int match_pattern(const char *s, const char *pattern, size_t limit) { bool had_asterisk = false; if (s == NULL || pattern == NULL || limit <= 0) { return 0; } for (;;) { /* If at end of pattern, accept if also at end of string. */ if (*pattern == '\0') { return (*s == '\0'); } while (*pattern == '*') { /* Skip the asterisk. */ had_asterisk = true; pattern++; } if (had_asterisk) { /* If at end of pattern, accept immediately. */ if (!*pattern) return 1; /* If next character in pattern is known, optimize. */ if (*pattern != '?') { /* * Look instances of the next character in * pattern, and try to match starting from * those. */ for (; *s; s++) if (*s == *pattern && match_pattern(s + 1, pattern + 1, limit - 1)) { return 1; } /* Failed. */ return 0; } /* * Move ahead one character at a time and try to * match at each position. */ for (; *s; s++) { if (match_pattern(s, pattern, limit - 1)) { return 1; } } /* Failed. */ return 0; } /* * There must be at least one more character in the string. * If we are at the end, fail. */ if (!*s) { return 0; } /* Check if the next character of the string is acceptable. */ if (*pattern != '?' && *pattern != *s) { return 0; } /* Move to the next character, both in string and in pattern. */ s++; pattern++; } /* NOTREACHED */ return 0; } /* * Tries to match the string against the comma-separated sequence of subpatterns * (each possibly preceded by ! to indicate negation). * Returns -1 if negation matches, 1 if there is a positive match, 0 if there is * no match at all. */ int match_pattern_list(const char *string, const char *pattern, unsigned int len, int dolower) { char sub[1024]; int negated; int got_positive; unsigned int i, subi; got_positive = 0; for (i = 0; i < len;) { /* Check if the subpattern is negated. */ if (pattern[i] == '!') { negated = 1; i++; } else { negated = 0; } /* * Extract the subpattern up to a comma or end. Convert the * subpattern to lowercase. */ for (subi = 0; i < len && subi < sizeof(sub) - 1 && pattern[i] != ','; subi++, i++) { sub[subi] = dolower && isupper(pattern[i]) ? (char)tolower(pattern[i]) : pattern[i]; } /* If subpattern too long, return failure (no match). */ if (subi >= sizeof(sub) - 1) { return 0; } /* If the subpattern was terminated by a comma, skip the comma. */ if (i < len && pattern[i] == ',') { i++; } /* Null-terminate the subpattern. */ sub[subi] = '\0'; /* Try to match the subpattern against the string. */ if (match_pattern(string, sub, MAX_MATCH_RECURSION)) { if (negated) { return -1; /* Negative */ } else { got_positive = 1; /* Positive */ } } } /* * Return success if got a positive match. If there was a negative * match, we have already returned -1 and never get here. */ return got_positive; } /* * Tries to match the host name (which must be in all lowercase) against the * comma-separated sequence of subpatterns (each possibly preceded by ! to * indicate negation). * Returns -1 if negation matches, 1 if there is a positive match, 0 if there * is no match at all. */ int match_hostname(const char *host, const char *pattern, unsigned int len) { return match_pattern_list(host, pattern, len, 1); } ================================================ FILE: src/libssh/src/mbedcrypto_missing.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2017 Sartura d.o.o. * * Author: Juraj Vijtiuk * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/priv.h" #include "libssh/libmbedcrypto.h" #ifdef HAVE_LIBMBEDCRYPTO bignum ssh_mbedcry_bn_new(void) { bignum bn; bn = malloc(sizeof(mbedtls_mpi)); if (bn) { mbedtls_mpi_init(bn); } return bn; } void ssh_mbedcry_bn_free(bignum bn) { mbedtls_mpi_free(bn); SAFE_FREE(bn); } unsigned char *ssh_mbedcry_bn2num(const_bignum num, int radix) { char *buf = NULL; size_t olen; int rc; rc = mbedtls_mpi_write_string(num, radix, buf, 0, &olen); if (rc != 0 && rc != MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) { return NULL; } buf = malloc(olen); if (buf == NULL) { return NULL; } rc = mbedtls_mpi_write_string(num, radix, buf, olen, &olen); if (rc != 0) { SAFE_FREE(buf); return NULL; } return (unsigned char *) buf; } int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom) { size_t len; int rc; int i; if (bits <= 0) { return 0; } len = bits / 8 + 1; /* FIXME weird bug: over 1024, fill_random function returns an error code * MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 */ if (len > 1024){ len = 1024; } rc = mbedtls_mpi_fill_random(rnd, len, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (rc != 0) { return 0; } for (i = len * 8 - 1; i >= bits; i--) { rc = mbedtls_mpi_set_bit(rnd, i, 0); if (rc != 0) { return 0; } } if (top == 0) { rc = mbedtls_mpi_set_bit(rnd, bits - 1, 0); if (rc != 0) { return 0; } } if (top == 1) { if (bits < 2) { return 0; } rc = mbedtls_mpi_set_bit(rnd, bits - 2, 0); if (rc != 0) { return 0; } } if (bottom) { rc = mbedtls_mpi_set_bit(rnd, 0, 1); if (rc != 0) { return 0; } } return 1; } int ssh_mbedcry_is_bit_set(bignum num, size_t pos) { int bit; bit = mbedtls_mpi_get_bit(num, pos); return bit; } /** @brief generates a random integer between 0 and max * @returns 1 in case of success, 0 otherwise */ int ssh_mbedcry_rand_range(bignum dest, bignum max) { size_t bits; bignum rnd; int rc; bits = bignum_num_bits(max) + 64; rnd = bignum_new(); if (rnd == NULL){ return 0; } rc = bignum_rand(rnd, bits); if (rc != 1) { bignum_safe_free(rnd); return rc; } mbedtls_mpi_mod_mpi(dest, rnd, max); bignum_safe_free(rnd); return 1; } int ssh_mbedcry_hex2bn(bignum *dest, char *data) { int rc; *dest = bignum_new(); if (*dest == NULL){ return 0; } rc = mbedtls_mpi_read_string(*dest, 16, data); if (rc == 0) { return 1; } return 0; } #endif ================================================ FILE: src/libssh/src/messages.c ================================================ /* * messages.c - message parsing for client and server * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #ifndef _WIN32 #include #include #endif #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/packet.h" #include "libssh/channels.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/dh.h" #include "libssh/messages.h" #ifdef WITH_SERVER #include "libssh/server.h" #include "libssh/gssapi.h" #endif /** * @defgroup libssh_messages The SSH message functions * @ingroup libssh * * This file contains the message parsing utilities for client and server * programs using libssh. * * On the server the the main loop of the program will call * ssh_message_get(session) to get messages as they come. They are not 1-1 with * the protocol messages. Then, the user will know what kind of a message it is * and use the appropriate functions to handle it (or use the default handlers * if you don't know what to do). * * @{ */ static ssh_message ssh_message_new(ssh_session session) { ssh_message msg = calloc(1, sizeof(struct ssh_message_struct)); if (msg == NULL) { return NULL; } msg->session = session; /* Set states explicitly */ msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE; return msg; } #ifndef WITH_SERVER /* Reduced version of the reply default that only reply with * SSH_MSG_UNIMPLEMENTED */ static int ssh_message_reply_default(ssh_message msg) { SSH_LOG(SSH_LOG_FUNCTIONS, "Reporting unknown packet"); if (ssh_buffer_add_u8(msg->session->out_buffer, SSH2_MSG_UNIMPLEMENTED) < 0) goto error; if (ssh_buffer_add_u32(msg->session->out_buffer, htonl(msg->session->recv_seq-1)) < 0) goto error; return ssh_packet_send(msg->session); error: return SSH_ERROR; } #endif #ifdef WITH_SERVER static int ssh_execute_server_request(ssh_session session, ssh_message msg) { ssh_channel channel = NULL; int rc; switch(msg->type) { case SSH_REQUEST_AUTH: if (msg->auth_request.method == SSH_AUTH_METHOD_PASSWORD && ssh_callbacks_exists(session->server_callbacks, auth_password_function)) { rc = session->server_callbacks->auth_password_function(session, msg->auth_request.username, msg->auth_request.password, session->server_callbacks->userdata); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) { ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); } else { ssh_message_reply_default(msg); } return SSH_OK; } else if(msg->auth_request.method == SSH_AUTH_METHOD_PUBLICKEY && ssh_callbacks_exists(session->server_callbacks, auth_pubkey_function)) { rc = session->server_callbacks->auth_pubkey_function(session, msg->auth_request.username, msg->auth_request.pubkey, msg->auth_request.signature_state, session->server_callbacks->userdata); if (msg->auth_request.signature_state != SSH_PUBLICKEY_STATE_NONE) { if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL) { ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); } else { ssh_message_reply_default(msg); } } else { if (rc == SSH_AUTH_SUCCESS) { ssh_message_auth_reply_pk_ok_simple(msg); } else { ssh_message_reply_default(msg); } } return SSH_OK; } else if (msg->auth_request.method == SSH_AUTH_METHOD_NONE && ssh_callbacks_exists(session->server_callbacks, auth_none_function)) { rc = session->server_callbacks->auth_none_function(session, msg->auth_request.username, session->server_callbacks->userdata); if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_PARTIAL){ ssh_message_auth_reply_success(msg, rc == SSH_AUTH_PARTIAL); } else { ssh_message_reply_default(msg); } return SSH_OK; } break; case SSH_REQUEST_CHANNEL_OPEN: if (msg->channel_request_open.type == SSH_CHANNEL_SESSION && ssh_callbacks_exists(session->server_callbacks, channel_open_request_session_function)) { channel = session->server_callbacks->channel_open_request_session_function(session, session->server_callbacks->userdata); if (channel != NULL) { rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARNING, "Failed to send reply for accepting a channel " "open"); } return SSH_OK; } else { ssh_message_reply_default(msg); } return SSH_OK; } break; case SSH_REQUEST_CHANNEL: channel = msg->channel_request.channel; if (msg->channel_request.type == SSH_CHANNEL_REQUEST_PTY){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_pty_request_function) { rc = ssh_callbacks_iterate_exec(channel_pty_request_function, session, channel, msg->channel_request.TERM, msg->channel_request.width, msg->channel_request.height, msg->channel_request.pxwidth, msg->channel_request.pxheight); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SHELL){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_shell_request_function) { rc = ssh_callbacks_iterate_exec(channel_shell_request_function, session, channel); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_X11){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_x11_req_function) { ssh_callbacks_iterate_exec(channel_x11_req_function, session, channel, msg->channel_request.x11_single_connection, msg->channel_request.x11_auth_protocol, msg->channel_request.x11_auth_cookie, msg->channel_request.x11_screen_number); ssh_message_channel_request_reply_success(msg); return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_WINDOW_CHANGE){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_pty_window_change_function) { rc = ssh_callbacks_iterate_exec(channel_pty_window_change_function, session, channel, msg->channel_request.width, msg->channel_request.height, msg->channel_request.pxwidth, msg->channel_request.pxheight); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARNING, "Failed to iterate callbacks for window change"); } return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_EXEC){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_exec_request_function) { rc = ssh_callbacks_iterate_exec(channel_exec_request_function, session, channel, msg->channel_request.command); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_ENV){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_env_request_function) { rc = ssh_callbacks_iterate_exec(channel_env_request_function, session, channel, msg->channel_request.var_name, msg->channel_request.var_value); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } ssh_callbacks_iterate_end(); } else if (msg->channel_request.type == SSH_CHANNEL_REQUEST_SUBSYSTEM){ ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks, channel_subsystem_request_function) { rc = ssh_callbacks_iterate_exec(channel_subsystem_request_function, session, channel, msg->channel_request.subsystem); if (rc == 0) { ssh_message_channel_request_reply_success(msg); } else { ssh_message_reply_default(msg); } return SSH_OK; } ssh_callbacks_iterate_end(); } break; case SSH_REQUEST_SERVICE: if (ssh_callbacks_exists(session->server_callbacks, service_request_function)) { rc = session->server_callbacks->service_request_function(session, msg->service_request.service, session->server_callbacks->userdata); if (rc == 0) { ssh_message_reply_default(msg); } else { ssh_disconnect(session); } return SSH_OK; } return SSH_AGAIN; case SSH_REQUEST_GLOBAL: break; } return SSH_AGAIN; } static int ssh_execute_client_request(ssh_session session, ssh_message msg) { ssh_channel channel = NULL; int rc = SSH_AGAIN; if (msg->type == SSH_REQUEST_CHANNEL_OPEN && msg->channel_request_open.type == SSH_CHANNEL_X11 && ssh_callbacks_exists(session->common.callbacks, channel_open_request_x11_function)) { channel = session->common.callbacks->channel_open_request_x11_function (session, msg->channel_request_open.originator, msg->channel_request_open.originator_port, session->common.callbacks->userdata); if (channel != NULL) { rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); return rc; } else { ssh_message_reply_default(msg); } return SSH_OK; } else if (msg->type == SSH_REQUEST_CHANNEL_OPEN && msg->channel_request_open.type == SSH_CHANNEL_AUTH_AGENT && ssh_callbacks_exists(session->common.callbacks, channel_open_request_auth_agent_function)) { channel = session->common.callbacks->channel_open_request_auth_agent_function (session, session->common.callbacks->userdata); if (channel != NULL) { rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel); return rc; } else { ssh_message_reply_default(msg); } return SSH_OK; } return rc; } /** @internal * Executes the callbacks defined in session->server_callbacks, out of an ssh_message * I don't like ssh_message interface but it works. * @returns SSH_OK if the message has been handled, or SSH_AGAIN otherwise. */ static int ssh_execute_server_callbacks(ssh_session session, ssh_message msg){ int rc = SSH_AGAIN; if (session->server_callbacks != NULL){ rc = ssh_execute_server_request(session, msg); } else if (session->common.callbacks != NULL) { /* This one is in fact a client callback... */ rc = ssh_execute_client_request(session, msg); } return rc; } #endif /* WITH_SERVER */ static int ssh_execute_message_callback(ssh_session session, ssh_message msg) { int ret; if(session->ssh_message_callback != NULL) { ret = session->ssh_message_callback(session, msg, session->ssh_message_callback_data); if(ret == 1) { ret = ssh_message_reply_default(msg); SSH_MESSAGE_FREE(msg); if(ret != SSH_OK) { return ret; } } else { SSH_MESSAGE_FREE(msg); } } else { ret = ssh_message_reply_default(msg); SSH_MESSAGE_FREE(msg); if(ret != SSH_OK) { return ret; } } return SSH_OK; } /** * @internal * * @brief Add a message to the current queue of messages to be parsed and/or call * the various callback functions. * * @param[in] session The SSH session to add the message. * * @param[in] message The message to add to the queue. */ static void ssh_message_queue(ssh_session session, ssh_message message) { #ifdef WITH_SERVER int ret; #endif if (message == NULL) { return; } #ifdef WITH_SERVER /* probably not the best place to execute server callbacks, but still better * than nothing. */ ret = ssh_execute_server_callbacks(session, message); if (ret == SSH_OK) { SSH_MESSAGE_FREE(message); return; } #endif /* WITH_SERVER */ if (session->ssh_message_callback != NULL) { /* This will transfer the message, do not free. */ ssh_execute_message_callback(session, message); return; } if (session->server_callbacks != NULL) { /* if we have server callbacks, but nothing was executed, it means we are * in non-synchronous mode, and we just don't care about the message we * received. Just send a default response. Do not queue it. */ ssh_message_reply_default(message); SSH_MESSAGE_FREE(message); return; } if (session->ssh_message_list == NULL) { session->ssh_message_list = ssh_list_new(); if (session->ssh_message_list == NULL) { /* * If the message list couldn't be allocated, the message can't be * enqueued */ ssh_message_reply_default(message); ssh_set_error_oom(session); SSH_MESSAGE_FREE(message); return; } } /* This will transfer the message, do not free. */ ssh_list_append(session->ssh_message_list, message); return; } /** * @internal * * @brief Pop a message from the message list and dequeue it. * * @param[in] session The SSH session to pop the message. * * @returns The head message or NULL if it doesn't exist. */ ssh_message ssh_message_pop_head(ssh_session session){ ssh_message msg=NULL; struct ssh_iterator *i; if(session->ssh_message_list == NULL) return NULL; i=ssh_list_get_iterator(session->ssh_message_list); if(i != NULL){ msg=ssh_iterator_value(ssh_message,i); ssh_list_remove(session->ssh_message_list,i); } return msg; } /* Returns 1 if there is a message available */ static int ssh_message_termination(void *s){ ssh_session session = s; struct ssh_iterator *it; if(session->session_state == SSH_SESSION_STATE_ERROR) return 1; it = ssh_list_get_iterator(session->ssh_message_list); if(!it) return 0; else return 1; } /** * @brief Retrieve a SSH message from a SSH session. * * @param[in] session The SSH session to get the message. * * @returns The SSH message received, NULL in case of error, or timeout * elapsed. * * @warning This function blocks until a message has been received. Betterset up * a callback if this behavior is unwanted. */ ssh_message ssh_message_get(ssh_session session) { ssh_message msg = NULL; int rc; msg=ssh_message_pop_head(session); if(msg) { return msg; } if(session->ssh_message_list == NULL) { session->ssh_message_list = ssh_list_new(); } rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, ssh_message_termination, session); if(rc || session->session_state == SSH_SESSION_STATE_ERROR) return NULL; msg=ssh_list_pop_head(ssh_message, session->ssh_message_list); return msg; } /** * @brief Get the type of the message. * * @param[in] msg The message to get the type from. * * @return The message type or -1 on error. */ int ssh_message_type(ssh_message msg) { if (msg == NULL) { return -1; } return msg->type; } /** * @brief Get the subtype of the message. * * @param[in] msg The message to get the subtype from. * * @return The message type or -1 on error. */ int ssh_message_subtype(ssh_message msg) { if (msg == NULL) { return -1; } switch(msg->type) { case SSH_REQUEST_AUTH: return msg->auth_request.method; case SSH_REQUEST_CHANNEL_OPEN: return msg->channel_request_open.type; case SSH_REQUEST_CHANNEL: return msg->channel_request.type; case SSH_REQUEST_GLOBAL: return msg->global_request.type; } return -1; } /** * @brief Free a SSH message. * * @param[in] msg The message to release the memory. */ void ssh_message_free(ssh_message msg){ if (msg == NULL) { return; } switch(msg->type) { case SSH_REQUEST_AUTH: SAFE_FREE(msg->auth_request.username); if (msg->auth_request.password) { explicit_bzero(msg->auth_request.password, strlen(msg->auth_request.password)); SAFE_FREE(msg->auth_request.password); } ssh_key_free(msg->auth_request.pubkey); break; case SSH_REQUEST_CHANNEL_OPEN: SAFE_FREE(msg->channel_request_open.originator); SAFE_FREE(msg->channel_request_open.destination); break; case SSH_REQUEST_CHANNEL: SAFE_FREE(msg->channel_request.TERM); SAFE_FREE(msg->channel_request.modes); SAFE_FREE(msg->channel_request.var_name); SAFE_FREE(msg->channel_request.var_value); SAFE_FREE(msg->channel_request.command); SAFE_FREE(msg->channel_request.subsystem); switch (msg->channel_request.type) { case SSH_CHANNEL_REQUEST_EXEC: SAFE_FREE(msg->channel_request.command); break; case SSH_CHANNEL_REQUEST_ENV: SAFE_FREE(msg->channel_request.var_name); SAFE_FREE(msg->channel_request.var_value); break; case SSH_CHANNEL_REQUEST_PTY: SAFE_FREE(msg->channel_request.TERM); break; case SSH_CHANNEL_REQUEST_SUBSYSTEM: SAFE_FREE(msg->channel_request.subsystem); break; case SSH_CHANNEL_REQUEST_X11: SAFE_FREE(msg->channel_request.x11_auth_protocol); SAFE_FREE(msg->channel_request.x11_auth_cookie); break; } break; case SSH_REQUEST_SERVICE: SAFE_FREE(msg->service_request.service); break; case SSH_REQUEST_GLOBAL: SAFE_FREE(msg->global_request.bind_address); break; } ZERO_STRUCTP(msg); SAFE_FREE(msg); } #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_service_request) { char *service_c = NULL; ssh_message msg = NULL; int rc; (void)type; (void)user; rc = ssh_buffer_unpack(packet, "s", &service_c); if (rc != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST packet"); goto error; } SSH_LOG(SSH_LOG_PACKET, "Received a SERVICE_REQUEST for service %s", service_c); msg = ssh_message_new(session); if (msg == NULL) { SAFE_FREE(service_c); goto error; } msg->type = SSH_REQUEST_SERVICE; msg->service_request.service = service_c; ssh_message_queue(session, msg); error: return SSH_PACKET_USED; } /* * This function concats in a buffer the values needed to do a signature * verification. */ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session, ssh_message msg, const char *service, ssh_string algo) { struct ssh_crypto_struct *crypto = NULL; ssh_buffer buffer; ssh_string str=NULL; int rc; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto == NULL) { return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; } rc = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &str); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_pack(buffer, "dPbsssbsS", crypto->digest_len, /* session ID string */ (size_t)crypto->digest_len, crypto->session_id, SSH2_MSG_USERAUTH_REQUEST, /* type */ msg->auth_request.username, service, "publickey", /* method */ 1, /* has to be signed (true) */ ssh_string_get_char(algo), /* pubkey algorithm */ str); /* public key as a blob */ SSH_STRING_FREE(str); if (rc != SSH_OK) { ssh_set_error_oom(session); SSH_BUFFER_FREE(buffer); return NULL; } return buffer; } /** * @internal * * @brief Handle a SSH_MSG_MSG_USERAUTH_REQUEST packet and queue a * SSH Message */ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){ ssh_message msg = NULL; ssh_signature sig = NULL; char *service = NULL; char *method = NULL; int cmp; int rc; (void)user; (void)type; msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } msg->type = SSH_REQUEST_AUTH; rc = ssh_buffer_unpack(packet, "sss", &msg->auth_request.username, &service, &method); if (rc != SSH_OK) { goto error; } SSH_LOG(SSH_LOG_PACKET, "Auth request for service %s, method %s for user '%s'", service, method, msg->auth_request.username); cmp = strcmp(service, "ssh-connection"); if (cmp != 0) { SSH_LOG(SSH_LOG_WARNING, "Invalid service request: %s", service); goto end; } if (strcmp(method, "none") == 0) { msg->auth_request.method = SSH_AUTH_METHOD_NONE; goto end; } if (strcmp(method, "password") == 0) { uint8_t tmp; msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD; rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password); if (rc != SSH_OK) { goto error; } goto end; } if (strcmp(method, "keyboard-interactive") == 0) { ssh_string lang = NULL; ssh_string submethods = NULL; msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE; lang = ssh_buffer_get_ssh_string(packet); if (lang == NULL) { goto error; } /* from the RFC 4256 * 3.1. Initial Exchange * "The language tag is deprecated and SHOULD be the empty string." */ SSH_STRING_FREE(lang); submethods = ssh_buffer_get_ssh_string(packet); if (submethods == NULL) { goto error; } /* from the RFC 4256 * 3.1. Initial Exchange * "One possible implementation strategy of the submethods field on the * server is that, unless the user may use multiple different * submethods, the server ignores this field." */ SSH_STRING_FREE(submethods); goto end; } if (strcmp(method, "publickey") == 0) { ssh_string algo = NULL; ssh_string pubkey_blob = NULL; uint8_t has_sign; msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY; SAFE_FREE(method); rc = ssh_buffer_unpack(packet, "bSS", &has_sign, &algo, &pubkey_blob ); if (rc != SSH_OK) { goto error; } rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey); SSH_STRING_FREE(pubkey_blob); pubkey_blob = NULL; if (rc < 0) { SSH_STRING_FREE(algo); algo = NULL; goto error; } msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE; // has a valid signature ? if(has_sign) { ssh_string sig_blob = NULL; ssh_buffer digest = NULL; sig_blob = ssh_buffer_get_ssh_string(packet); if(sig_blob == NULL) { SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer"); msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR; SSH_STRING_FREE(algo); algo = NULL; goto error; } digest = ssh_msg_userauth_build_digest(session, msg, service, algo); SSH_STRING_FREE(algo); algo = NULL; if (digest == NULL) { SSH_STRING_FREE(sig_blob); SSH_LOG(SSH_LOG_PACKET, "Failed to get digest"); msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG; goto error; } rc = ssh_pki_import_signature_blob(sig_blob, msg->auth_request.pubkey, &sig); if (rc == SSH_OK) { /* Check if the signature from client matches server preferences */ if (session->opts.pubkey_accepted_types) { if (!ssh_match_group(session->opts.pubkey_accepted_types, sig->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from client (%s) doesn't match server " "preference (%s)", sig->type_c, session->opts.pubkey_accepted_types); rc = SSH_ERROR; } } if (rc == SSH_OK) { rc = ssh_pki_signature_verify(session, sig, msg->auth_request.pubkey, ssh_buffer_get(digest), ssh_buffer_get_len(digest)); } } SSH_STRING_FREE(sig_blob); SSH_BUFFER_FREE(digest); ssh_signature_free(sig); if (rc < 0) { SSH_LOG( SSH_LOG_PACKET, "Received an invalid signature from peer"); msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG; goto error; } SSH_LOG(SSH_LOG_PACKET, "Valid signature received"); msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID; } SSH_STRING_FREE(algo); goto end; } #ifdef WITH_GSSAPI if (strcmp(method, "gssapi-with-mic") == 0) { uint32_t n_oid; ssh_string *oids; ssh_string oid; char *hexa; int i; ssh_buffer_get_u32(packet, &n_oid); n_oid=ntohl(n_oid); if(n_oid > 100){ ssh_set_error(session, SSH_FATAL, "USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",n_oid); goto error; } SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid); oids = calloc(n_oid, sizeof(ssh_string)); if (oids == NULL){ ssh_set_error_oom(session); goto error; } for (i=0;i<(int) n_oid;++i){ oid=ssh_buffer_get_ssh_string(packet); if(oid == NULL){ for(i=i-1;i>=0;--i){ SAFE_FREE(oids[i]); } SAFE_FREE(oids); ssh_set_error(session, SSH_LOG_PACKET, "USERAUTH_REQUEST: gssapi-with-mic missing OID"); goto error; } oids[i] = oid; if(session->common.log_verbosity >= SSH_LOG_PACKET){ hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid)); SSH_LOG(SSH_LOG_PACKET,"gssapi: OID %d: %s",i, hexa); SAFE_FREE(hexa); } } ssh_gssapi_handle_userauth(session, msg->auth_request.username, n_oid, oids); for(i=0;i<(int)n_oid;++i){ SAFE_FREE(oids[i]); } SAFE_FREE(oids); /* bypass the message queue thing */ SAFE_FREE(service); SAFE_FREE(method); SSH_MESSAGE_FREE(msg); return SSH_PACKET_USED; } #endif msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN; SAFE_FREE(method); goto end; error: SAFE_FREE(service); SAFE_FREE(method); SSH_MESSAGE_FREE(msg); return SSH_PACKET_USED; end: SAFE_FREE(service); SAFE_FREE(method); ssh_message_queue(session,msg); return SSH_PACKET_USED; } #endif /* WITH_SERVER */ /** * @internal * * @brief Handle a SSH_MSG_MSG_USERAUTH_INFO_RESPONSE packet and queue a * SSH Message */ #ifndef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){ (void)session; (void)type; (void)packet; (void)user; return SSH_PACKET_USED; } #else /* WITH_SERVER */ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){ uint32_t nanswers; uint32_t i; ssh_string tmp; int rc; ssh_message msg = NULL; /* GSSAPI_TOKEN has same packed number. XXX fix this */ #ifdef WITH_GSSAPI if (session->gssapi != NULL) { return ssh_packet_userauth_gssapi_token(session, type, packet, user); } #endif (void)user; (void)type; msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } /* HACK: we forge a message to be able to handle it in the * same switch() as other auth methods */ msg->type = SSH_REQUEST_AUTH; msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE; msg->auth_request.kbdint_response = 1; #if 0 // should we wipe the username ? msg->auth_request.username = NULL; #endif rc = ssh_buffer_unpack(packet, "d", &nanswers); if (rc != SSH_OK) { ssh_set_error_invalid(session); goto error; } if (session->kbdint == NULL) { SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a keyboard-interactive " "response but it seems we didn't send the request."); session->kbdint = ssh_kbdint_new(); if (session->kbdint == NULL) { ssh_set_error_oom(session); goto error; } } else if (session->kbdint->answers != NULL) { uint32_t n; for (n = 0; n < session->kbdint->nanswers; n++) { explicit_bzero(session->kbdint->answers[n], strlen(session->kbdint->answers[n])); SAFE_FREE(session->kbdint->answers[n]); } SAFE_FREE(session->kbdint->answers); session->kbdint->nanswers = 0; } SSH_LOG(SSH_LOG_PACKET,"kbdint: %d answers",nanswers); if (nanswers > KBDINT_MAX_PROMPT) { ssh_set_error(session, SSH_FATAL, "Too much answers received from client: %u (0x%.4x)", nanswers, nanswers); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; goto error; } if(nanswers != session->kbdint->nprompts) { /* warn but let the application handle this case */ SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Number of prompts and answers" " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers); } session->kbdint->nanswers = nanswers; session->kbdint->answers = calloc(nanswers, sizeof(char *)); if (session->kbdint->answers == NULL) { session->kbdint->nanswers = 0; ssh_set_error_oom(session); ssh_kbdint_free(session->kbdint); session->kbdint = NULL; goto error; } for (i = 0; i < nanswers; i++) { tmp = ssh_buffer_get_ssh_string(packet); if (tmp == NULL) { ssh_set_error(session, SSH_FATAL, "Short INFO_RESPONSE packet"); session->kbdint->nanswers = i; ssh_kbdint_free(session->kbdint); session->kbdint = NULL; goto error; } session->kbdint->answers[i] = ssh_string_to_char(tmp); SSH_STRING_FREE(tmp); if (session->kbdint->answers[i] == NULL) { ssh_set_error_oom(session); session->kbdint->nanswers = i; ssh_kbdint_free(session->kbdint); session->kbdint = NULL; goto error; } } ssh_message_queue(session,msg); return SSH_PACKET_USED; error: SSH_MESSAGE_FREE(msg); return SSH_PACKET_USED; } #endif /* WITH_SERVER */ SSH_PACKET_CALLBACK(ssh_packet_channel_open){ ssh_message msg = NULL; char *type_c = NULL; uint32_t originator_port, destination_port; int rc; (void)type; (void)user; msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } msg->type = SSH_REQUEST_CHANNEL_OPEN; rc = ssh_buffer_unpack(packet, "s", &type_c); if (rc != SSH_OK){ goto error; } SSH_LOG(SSH_LOG_PACKET, "Clients wants to open a %s channel", type_c); ssh_buffer_unpack(packet,"ddd", &msg->channel_request_open.sender, &msg->channel_request_open.window, &msg->channel_request_open.packet_size); if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED){ ssh_set_error(session,SSH_FATAL, "Invalid state when receiving channel open request (must be authenticated)"); goto error; } if (strcmp(type_c,"session") == 0) { msg->channel_request_open.type = SSH_CHANNEL_SESSION; SAFE_FREE(type_c); goto end; } if (strcmp(type_c,"direct-tcpip") == 0) { rc = ssh_buffer_unpack(packet, "sdsd", &msg->channel_request_open.destination, &destination_port, &msg->channel_request_open.originator, &originator_port); if (rc != SSH_OK) { goto error; } msg->channel_request_open.destination_port = (uint16_t) destination_port; msg->channel_request_open.originator_port = (uint16_t) originator_port; msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP; goto end; } if (strcmp(type_c,"forwarded-tcpip") == 0) { rc = ssh_buffer_unpack(packet, "sdsd", &msg->channel_request_open.destination, &destination_port, &msg->channel_request_open.originator, &originator_port ); if (rc != SSH_OK){ goto error; } msg->channel_request_open.destination_port = (uint16_t) destination_port; msg->channel_request_open.originator_port = (uint16_t) originator_port; msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP; goto end; } if (strcmp(type_c,"x11") == 0) { rc = ssh_buffer_unpack(packet, "sd", &msg->channel_request_open.originator, &originator_port); if (rc != SSH_OK){ goto error; } msg->channel_request_open.originator_port = (uint16_t) originator_port; msg->channel_request_open.type = SSH_CHANNEL_X11; goto end; } if (strcmp(type_c,"auth-agent@openssh.com") == 0) { msg->channel_request_open.type = SSH_CHANNEL_AUTH_AGENT; goto end; } msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN; goto end; error: SSH_MESSAGE_FREE(msg); end: SAFE_FREE(type_c); if(msg != NULL) ssh_message_queue(session,msg); return SSH_PACKET_USED; } /** * @internal * * @brief This function accepts a channel open request for the specified channel. * * @param[in] msg The message. * * @param[in] chan The channel the request is made on. * * @returns SSH_OK on success, SSH_ERROR if an error occured. */ int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan) { ssh_session session; int rc; if (msg == NULL) { return SSH_ERROR; } session = msg->session; chan->local_channel = ssh_channel_new_id(session); chan->local_maxpacket = 35000; chan->local_window = 32000; chan->remote_channel = msg->channel_request_open.sender; chan->remote_maxpacket = msg->channel_request_open.packet_size; chan->remote_window = msg->channel_request_open.window; chan->state = SSH_CHANNEL_STATE_OPEN; chan->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND; rc = ssh_buffer_pack(session->out_buffer, "bdddd", SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, chan->remote_channel, chan->local_channel, chan->local_window, chan->local_maxpacket); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Accepting a channel request_open for chan %d", chan->remote_channel); rc = ssh_packet_send(session); return rc; } /** * @internal * * @brief This function accepts a channel open request. * * @param[in] msg The message. * * @returns a valid ssh_channel handle if the request is to be allowed * * @returns NULL in case of error */ ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) { ssh_channel chan; int rc; if (msg == NULL) { return NULL; } chan = ssh_channel_new(msg->session); if (chan == NULL) { return NULL; } rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan); if (rc < 0) { ssh_channel_free(chan); chan = NULL; } return chan; } /** * @internal * * @brief This function parses the last end of a channel request packet. * * This is normally converted to a SSH message and placed in the queue. * * @param[in] session The SSH session. * * @param[in] channel The channel the request is made on. * * @param[in] packet The rest of the packet to be parsed. * * @param[in] request The type of request. * * @param[in] want_reply The want_reply field from the request. * * @returns SSH_OK on success, SSH_ERROR if an error occured. */ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet, const char *request, uint8_t want_reply) { ssh_message msg = NULL; int rc; msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } SSH_LOG(SSH_LOG_PACKET, "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)", request, channel->local_channel, channel->remote_channel, want_reply); msg->type = SSH_REQUEST_CHANNEL; msg->channel_request.channel = channel; msg->channel_request.want_reply = want_reply; if (strcmp(request, "pty-req") == 0) { rc = ssh_buffer_unpack(packet, "sddddS", &msg->channel_request.TERM, &msg->channel_request.width, &msg->channel_request.height, &msg->channel_request.pxwidth, &msg->channel_request.pxheight, &msg->channel_request.modes ); msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY; if (rc != SSH_OK) { goto error; } goto end; } if (strcmp(request, "window-change") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE; rc = ssh_buffer_unpack(packet, "dddd", &msg->channel_request.width, &msg->channel_request.height, &msg->channel_request.pxwidth, &msg->channel_request.pxheight); if (rc != SSH_OK){ goto error; } goto end; } if (strcmp(request, "subsystem") == 0) { rc = ssh_buffer_unpack(packet, "s", &msg->channel_request.subsystem); msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM; if (rc != SSH_OK){ goto error; } goto end; } if (strcmp(request, "shell") == 0) { msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL; goto end; } if (strcmp(request, "exec") == 0) { rc = ssh_buffer_unpack(packet, "s", &msg->channel_request.command); msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC; if (rc != SSH_OK) { goto error; } goto end; } if (strcmp(request, "env") == 0) { rc = ssh_buffer_unpack(packet, "ss", &msg->channel_request.var_name, &msg->channel_request.var_value); msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV; if (rc != SSH_OK) { goto error; } goto end; } if (strcmp(request, "x11-req") == 0) { rc = ssh_buffer_unpack(packet, "bssd", &msg->channel_request.x11_single_connection, &msg->channel_request.x11_auth_protocol, &msg->channel_request.x11_auth_cookie, &msg->channel_request.x11_screen_number); msg->channel_request.type = SSH_CHANNEL_REQUEST_X11; if (rc != SSH_OK) { goto error; } goto end; } msg->channel_request.type = SSH_CHANNEL_REQUEST_UNKNOWN; end: ssh_message_queue(session,msg); return SSH_OK; error: SSH_MESSAGE_FREE(msg); return SSH_ERROR; } int ssh_message_channel_request_reply_success(ssh_message msg) { uint32_t channel; int rc; if (msg == NULL) { return SSH_ERROR; } if (msg->channel_request.want_reply) { channel = msg->channel_request.channel->remote_channel; SSH_LOG(SSH_LOG_PACKET, "Sending a channel_request success to channel %d", channel); rc = ssh_buffer_pack(msg->session->out_buffer, "bd", SSH2_MSG_CHANNEL_SUCCESS, channel); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } return ssh_packet_send(msg->session); } SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the request succeeded"); return SSH_OK; } #ifdef WITH_SERVER SSH_PACKET_CALLBACK(ssh_packet_global_request){ ssh_message msg = NULL; char *request=NULL; uint8_t want_reply; int rc = SSH_PACKET_USED; int r; (void)user; (void)type; (void)packet; SSH_LOG(SSH_LOG_PROTOCOL,"Received SSH_MSG_GLOBAL_REQUEST packet"); r = ssh_buffer_unpack(packet, "sb", &request, &want_reply); if (r != SSH_OK){ goto error; } msg = ssh_message_new(session); if (msg == NULL) { ssh_set_error_oom(session); goto error; } msg->type = SSH_REQUEST_GLOBAL; if (strcmp(request, "tcpip-forward") == 0) { /* According to RFC4254, the client SHOULD reject this message */ if (session->client) { goto reply_with_failure; } r = ssh_buffer_unpack(packet, "sd", &msg->global_request.bind_address, &msg->global_request.bind_port ); if (r != SSH_OK){ goto reply_with_failure; } msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD; msg->global_request.want_reply = want_reply; SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, msg->global_request.bind_address, msg->global_request.bind_port); if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { SSH_LOG(SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, msg->global_request.bind_address, msg->global_request.bind_port); session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); } else { SAFE_FREE(request); ssh_message_queue(session, msg); return rc; } } else if (strcmp(request, "cancel-tcpip-forward") == 0) { /* According to RFC4254, the client SHOULD reject this message */ if (session->client) { goto reply_with_failure; } r = ssh_buffer_unpack(packet, "sd", &msg->global_request.bind_address, &msg->global_request.bind_port); if (r != SSH_OK){ goto reply_with_failure; } msg->global_request.type = SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD; msg->global_request.want_reply = want_reply; SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply, msg->global_request.bind_address, msg->global_request.bind_port); if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); } else { SAFE_FREE(request); ssh_message_queue(session, msg); return rc; } } else if(strcmp(request, "keepalive@openssh.com") == 0) { msg->global_request.type = SSH_GLOBAL_REQUEST_KEEPALIVE; msg->global_request.want_reply = want_reply; SSH_LOG(SSH_LOG_PROTOCOL, "Received keepalive@openssh.com %d", want_reply); if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) { session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata); } else { ssh_message_global_request_reply_success(msg, 0); } } else { SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, " "want_reply = %d", request, want_reply); goto reply_with_failure; } SAFE_FREE(msg); SAFE_FREE(request); return rc; reply_with_failure: /* Only report the failure if requested */ if (want_reply) { r = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_REQUEST_FAILURE); if (r < 0) { ssh_set_error_oom(session); goto error; } r = ssh_packet_send(session); if (r != SSH_OK) { goto error; } } else { SSH_LOG(SSH_LOG_PACKET, "The requester doesn't want to know the request failed!"); } /* Consume the message to avoid sending UNIMPLEMENTED later */ rc = SSH_PACKET_USED; error: SAFE_FREE(msg); SAFE_FREE(request); SSH_LOG(SSH_LOG_WARNING, "Invalid SSH_MSG_GLOBAL_REQUEST packet"); return rc; } #endif /* WITH_SERVER */ /** @} */ ================================================ FILE: src/libssh/src/misc.c ================================================ /* * misc.c - useful client functions * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * Copyright (c) 2008-2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #ifndef _WIN32 /* This is needed for a standard getpwuid_r on opensolaris */ #define _POSIX_PTHREAD_SEMANTICS #include #include #include #include #include #endif /* _WIN32 */ #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #ifdef _WIN32 #ifndef _WIN32_IE # define _WIN32_IE 0x0501 // SHGetSpecialFolderPath #endif #include // Must be the first to include #include #include #include #ifdef HAVE_IO_H #include #endif /* HAVE_IO_H */ #endif /* _WIN32 */ #include "libssh/priv.h" #include "libssh/misc.h" #include "libssh/session.h" #ifdef HAVE_LIBGCRYPT #define GCRYPT_STRING "/gnutls" #else #define GCRYPT_STRING "" #endif #ifdef HAVE_LIBCRYPTO #define CRYPTO_STRING "/openssl" #else #define CRYPTO_STRING "" #endif #ifdef HAVE_LIBMBEDCRYPTO #define MBED_STRING "/mbedtls" #else #define MBED_STRING "" #endif #ifdef WITH_ZLIB #define ZLIB_STRING "/zlib" #else #define ZLIB_STRING "" #endif /** * @defgroup libssh_misc The SSH helper functions. * @ingroup libssh * * Different helper functions used in the SSH Library. * * @{ */ #ifdef _WIN32 char *ssh_get_user_home_dir(void) { char tmp[MAX_PATH] = {0}; char *szPath = NULL; if (SHGetSpecialFolderPathA(NULL, tmp, CSIDL_PROFILE, TRUE)) { szPath = malloc(strlen(tmp) + 1); if (szPath == NULL) { return NULL; } strcpy(szPath, tmp); return szPath; } return NULL; } /* we have read access on file */ int ssh_file_readaccess_ok(const char *file) { if (_access(file, 4) < 0) { return 0; } return 1; } /** * @brief Check if the given path is an existing directory and that is * accessible for writing. * * @param[in] path Path to the directory to be checked * * @return Return 1 if the directory exists and is accessible; 0 otherwise * */ int ssh_dir_writeable(const char *path) { struct _stat buffer; int rc; rc = _stat(path, &buffer); if (rc < 0) { return 0; } if ((buffer.st_mode & _S_IFDIR) && (buffer.st_mode & _S_IWRITE)) { return 1; } return 0; } #define SSH_USEC_IN_SEC 1000000LL #define SSH_SECONDS_SINCE_1601 11644473600LL int gettimeofday(struct timeval *__p, void *__t) { union { unsigned long long ns100; /* time since 1 Jan 1601 in 100ns units */ FILETIME ft; } now; GetSystemTimeAsFileTime (&now.ft); __p->tv_usec = (long) ((now.ns100 / 10LL) % SSH_USEC_IN_SEC); __p->tv_sec = (long)(((now.ns100 / 10LL ) / SSH_USEC_IN_SEC) - SSH_SECONDS_SINCE_1601); return (0); } char *ssh_get_local_username(void) { DWORD size = 0; char *user; /* get the size */ GetUserName(NULL, &size); user = (char *) malloc(size); if (user == NULL) { return NULL; } if (GetUserName(user, &size)) { return user; } return NULL; } int ssh_is_ipaddr_v4(const char *str) { struct sockaddr_storage ss; int sslen = sizeof(ss); int rc = SOCKET_ERROR; /* WSAStringToAddressA thinks that 0.0.0 is a valid IP */ if (strlen(str) < 7) { return 0; } rc = WSAStringToAddressA((LPSTR) str, AF_INET, NULL, (struct sockaddr*)&ss, &sslen); if (rc == 0) { return 1; } return 0; } int ssh_is_ipaddr(const char *str) { int rc = SOCKET_ERROR; if (strchr(str, ':')) { struct sockaddr_storage ss; int sslen = sizeof(ss); /* TODO link-local (IP:v6:addr%ifname). */ rc = WSAStringToAddressA((LPSTR) str, AF_INET6, NULL, (struct sockaddr*)&ss, &sslen); if (rc == 0) { return 1; } } return ssh_is_ipaddr_v4(str); } #else /* _WIN32 */ #ifndef NSS_BUFLEN_PASSWD #define NSS_BUFLEN_PASSWD 4096 #endif /* NSS_BUFLEN_PASSWD */ char *ssh_get_user_home_dir(void) { char *szPath = NULL; struct passwd pwd; struct passwd *pwdbuf = NULL; char buf[NSS_BUFLEN_PASSWD] = {0}; int rc; rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); if (rc != 0 || pwdbuf == NULL ) { szPath = getenv("HOME"); if (szPath == NULL) { return NULL; } snprintf(buf, sizeof(buf), "%s", szPath); return strdup(buf); } szPath = strdup(pwd.pw_dir); return szPath; } /* we have read access on file */ int ssh_file_readaccess_ok(const char *file) { if (access(file, R_OK) < 0) { return 0; } return 1; } /** * @brief Check if the given path is an existing directory and that is * accessible for writing. * * @param[in] path Path to the directory to be checked * * @return Return 1 if the directory exists and is accessible; 0 otherwise * */ int ssh_dir_writeable(const char *path) { struct stat buffer; int rc; rc = stat(path, &buffer); if (rc < 0) { return 0; } if (S_ISDIR(buffer.st_mode) && (buffer.st_mode & S_IWRITE)) { return 1; } return 0; } char *ssh_get_local_username(void) { struct passwd pwd; struct passwd *pwdbuf = NULL; char buf[NSS_BUFLEN_PASSWD]; char *name; int rc; rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); if (rc != 0 || pwdbuf == NULL) { return NULL; } name = strdup(pwd.pw_name); if (name == NULL) { return NULL; } return name; } int ssh_is_ipaddr_v4(const char *str) { int rc = -1; struct in_addr dest; rc = inet_pton(AF_INET, str, &dest); if (rc > 0) { return 1; } return 0; } int ssh_is_ipaddr(const char *str) { int rc = -1; if (strchr(str, ':')) { struct in6_addr dest6; /* TODO link-local (IP:v6:addr%ifname). */ rc = inet_pton(AF_INET6, str, &dest6); if (rc > 0) { return 1; } } return ssh_is_ipaddr_v4(str); } #endif /* _WIN32 */ char *ssh_lowercase(const char* str) { char *new, *p; if (str == NULL) { return NULL; } new = strdup(str); if (new == NULL) { return NULL; } for (p = new; *p; p++) { *p = tolower(*p); } return new; } char *ssh_hostport(const char *host, int port) { char *dest = NULL; size_t len; if (host == NULL) { return NULL; } /* 3 for []:, 5 for 65536 and 1 for nul */ len = strlen(host) + 3 + 5 + 1; dest = malloc(len); if (dest == NULL) { return NULL; } snprintf(dest, len, "[%s]:%d", host, port); return dest; } /** * @brief Convert a buffer into a colon separated hex string. * The caller has to free the memory. * * @param what What should be converted to a hex string. * * @param len Length of the buffer to convert. * * @return The hex string or NULL on error. * * @see ssh_string_free_char() */ char *ssh_get_hexa(const unsigned char *what, size_t len) { const char h[] = "0123456789abcdef"; char *hexa; size_t i; size_t hlen = len * 3; if (len > (UINT_MAX - 1) / 3) { return NULL; } hexa = malloc(hlen + 1); if (hexa == NULL) { return NULL; } for (i = 0; i < len; i++) { hexa[i * 3] = h[(what[i] >> 4) & 0xF]; hexa[i * 3 + 1] = h[what[i] & 0xF]; hexa[i * 3 + 2] = ':'; } hexa[hlen - 1] = '\0'; return hexa; } /** * @deprecated Please use ssh_print_hash() instead */ void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len) { char *hexa = ssh_get_hexa(what, len); if (hexa == NULL) { return; } fprintf(stderr, "%s: %s\n", descr, hexa); free(hexa); } /** * @brief Log the content of a buffer in hexadecimal format, similar to the * output of 'hexdump -C' command. * * The first logged line is the given description followed by the length. * Then the content of the buffer is logged 16 bytes per line in the following * format: * * (offset) (first 8 bytes) (last 8 bytes) (the 16 bytes as ASCII char values) * * The output for a 16 bytes array containing values from 0x00 to 0x0f would be: * * "Example (16 bytes):" * " 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f ................" * * The value for each byte as corresponding ASCII character is printed at the * end if the value is printable. Otherwise it is replace with '.'. * * @param[in] descr A description for the content to be logged * @param[in] what The buffer to be logged * @param[in] len The length of the buffer given in what * * @note If a too long description is provided (which would result in a first * line longer than 80 bytes), the function will fail. */ void ssh_log_hexdump(const char *descr, const unsigned char *what, size_t len) { size_t i; char ascii[17]; const unsigned char *pc = NULL; size_t count = 0; ssize_t printed = 0; /* The required buffer size is calculated from: * * 2 bytes for spaces at the beginning * 8 bytes for the offset * 2 bytes for spaces * 24 bytes to print the first 8 bytes + spaces * 1 byte for an extra space * 24 bytes to print next 8 bytes + spaces * 2 bytes for extra spaces * 16 bytes for the content as ASCII characters at the end * 1 byte for the ending '\0' * * Resulting in 80 bytes. * * Except for the first line (description + size), all lines have fixed * length. If a too long description is used, the function will fail. * */ char buffer[80]; /* Print description */ if (descr != NULL) { printed = snprintf(buffer, sizeof(buffer), "%s ", descr); if (printed < 0) { goto error; } count += printed; } else { printed = snprintf(buffer, sizeof(buffer), "(NULL description) "); if (printed < 0) { goto error; } count += printed; } if (len == 0) { printed = snprintf(buffer + count, sizeof(buffer) - count, "(zero length):"); if (printed < 0) { goto error; } SSH_LOG(SSH_LOG_DEBUG, "%s", buffer); return; } else { printed = snprintf(buffer + count, sizeof(buffer) - count, "(%zu bytes):", len); if (printed < 0) { goto error; } count += printed; } if (what == NULL) { printed = snprintf(buffer + count, sizeof(buffer) - count, "(NULL)"); if (printed < 0) { goto error; } SSH_LOG(SSH_LOG_DEBUG, "%s", buffer); return; } SSH_LOG(SSH_LOG_DEBUG, "%s", buffer); /* Reset state */ count = 0; pc = what; for (i = 0; i < len; i++) { /* Add one space after printing 8 bytes */ if ((i % 8) == 0) { if (i != 0) { printed = snprintf(buffer + count, sizeof(buffer) - count, " "); if (printed < 0) { goto error; } count += printed; } } /* Log previous line and reset state for new line */ if ((i % 16) == 0) { if (i != 0) { printed = snprintf(buffer + count, sizeof(buffer) - count, " %s", ascii); if (printed < 0) { goto error; } SSH_LOG(SSH_LOG_DEBUG, "%s", buffer); count = 0; } /* Start a new line with the offset */ printed = snprintf(buffer, sizeof(buffer), " %08zx ", i); if (printed < 0) { goto error; } count += printed; } /* Print the current byte hexadecimal representation */ printed = snprintf(buffer + count, sizeof(buffer) - count, " %02x", pc[i]); if (printed < 0) { goto error; } count += printed; /* If printable, store the ASCII character */ if (isprint(pc[i])) { ascii[i % 16] = pc[i]; } else { ascii[i % 16] = '.'; } ascii[(i % 16) + 1] = '\0'; } /* Add padding if not exactly 16 characters */ while ((i % 16) != 0) { /* Add one space after printing 8 bytes */ if ((i % 8) == 0) { if (i != 0) { printed = snprintf(buffer + count, sizeof(buffer) - count, " "); if (printed < 0) { goto error; } count += printed; } } printed = snprintf(buffer + count, sizeof(buffer) - count, " "); if (printed < 0) { goto error; } count += printed; i++; } /* Print the last printable part */ printed = snprintf(buffer + count, sizeof(buffer) - count, " %s", ascii); if (printed < 0) { goto error; } SSH_LOG(SSH_LOG_DEBUG, "%s", buffer); return; error: SSH_LOG(SSH_LOG_WARN, "Could not print to buffer"); return; } /** * @brief Check if libssh is the required version or get the version * string. * * @param[in] req_version The version required. * * @return If the version of libssh is newer than the version * required it will return a version string. * NULL if the version is older. * * Example: * * @code * if (ssh_version(SSH_VERSION_INT(0,2,1)) == NULL) { * fprintf(stderr, "libssh version is too old!\n"); * exit(1); * } * * if (debug) { * printf("libssh %s\n", ssh_version(0)); * } * @endcode */ const char *ssh_version(int req_version) { if (req_version <= LIBSSH_VERSION_INT) { return SSH_STRINGIFY(LIBSSH_VERSION) GCRYPT_STRING CRYPTO_STRING MBED_STRING ZLIB_STRING; } return NULL; } struct ssh_list *ssh_list_new(void) { struct ssh_list *ret=malloc(sizeof(struct ssh_list)); if(!ret) return NULL; ret->root=ret->end=NULL; return ret; } void ssh_list_free(struct ssh_list *list){ struct ssh_iterator *ptr,*next; if(!list) return; ptr=list->root; while(ptr){ next=ptr->next; SAFE_FREE(ptr); ptr=next; } SAFE_FREE(list); } struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list){ if(!list) return NULL; return list->root; } struct ssh_iterator *ssh_list_find(const struct ssh_list *list, void *value){ struct ssh_iterator *it; for(it = ssh_list_get_iterator(list); it != NULL ;it=it->next) if(it->data==value) return it; return NULL; } /** * @brief Get the number of elements in the list * * @param[in] list The list to count. * * @return The number of elements in the list. */ size_t ssh_list_count(const struct ssh_list *list) { struct ssh_iterator *it = NULL; int count = 0; for (it = ssh_list_get_iterator(list); it != NULL ; it = it->next) { count++; } return count; } static struct ssh_iterator *ssh_iterator_new(const void *data){ struct ssh_iterator *iterator=malloc(sizeof(struct ssh_iterator)); if(!iterator) return NULL; iterator->next=NULL; iterator->data=data; return iterator; } int ssh_list_append(struct ssh_list *list,const void *data){ struct ssh_iterator *iterator = NULL; if (list == NULL) { return SSH_ERROR; } iterator = ssh_iterator_new(data); if (iterator == NULL) { return SSH_ERROR; } if(!list->end){ /* list is empty */ list->root=list->end=iterator; } else { /* put it on end of list */ list->end->next=iterator; list->end=iterator; } return SSH_OK; } int ssh_list_prepend(struct ssh_list *list, const void *data){ struct ssh_iterator *it = NULL; if (list == NULL) { return SSH_ERROR; } it = ssh_iterator_new(data); if (it == NULL) { return SSH_ERROR; } if (list->end == NULL) { /* list is empty */ list->root = list->end = it; } else { /* set as new root */ it->next = list->root; list->root = it; } return SSH_OK; } void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){ struct ssh_iterator *ptr,*prev; if (list == NULL) { return; } prev=NULL; ptr=list->root; while(ptr && ptr != iterator){ prev=ptr; ptr=ptr->next; } if(!ptr){ /* we did not find the element */ return; } /* unlink it */ if(prev) prev->next=ptr->next; /* if iterator was the head */ if(list->root == iterator) list->root=iterator->next; /* if iterator was the tail */ if(list->end == iterator) list->end = prev; SAFE_FREE(iterator); } /** * @internal * * @brief Removes the top element of the list and returns the data value * attached to it. * * @param[in[ list The ssh_list to remove the element. * * @returns A pointer to the element being stored in head, or NULL * if the list is empty. */ const void *_ssh_list_pop_head(struct ssh_list *list){ struct ssh_iterator *iterator = NULL; const void *data = NULL; if (list == NULL) { return NULL; } iterator = list->root; if (iterator == NULL) { return NULL; } data=iterator->data; list->root=iterator->next; if(list->end==iterator) list->end=NULL; SAFE_FREE(iterator); return data; } /** * @brief Parse directory component. * * dirname breaks a null-terminated pathname string into a directory component. * In the usual case, ssh_dirname() returns the string up to, but not including, * the final '/'. Trailing '/' characters are not counted as part of the * pathname. The caller must free the memory. * * @param[in] path The path to parse. * * @return The dirname of path or NULL if we can't allocate memory. * If path does not contain a slash, c_dirname() returns * the string ".". If path is the string "/", it returns * the string "/". If path is NULL or an empty string, * "." is returned. */ char *ssh_dirname (const char *path) { char *new = NULL; size_t len; if (path == NULL || *path == '\0') { return strdup("."); } len = strlen(path); /* Remove trailing slashes */ while(len > 0 && path[len - 1] == '/') --len; /* We have only slashes */ if (len == 0) { return strdup("/"); } /* goto next slash */ while(len > 0 && path[len - 1] != '/') --len; if (len == 0) { return strdup("."); } else if (len == 1) { return strdup("/"); } /* Remove slashes again */ while(len > 0 && path[len - 1] == '/') --len; new = malloc(len + 1); if (new == NULL) { return NULL; } strncpy(new, path, len); new[len] = '\0'; return new; } /** * @brief basename - parse filename component. * * basename breaks a null-terminated pathname string into a filename component. * ssh_basename() returns the component following the final '/'. Trailing '/' * characters are not counted as part of the pathname. * * @param[in] path The path to parse. * * @return The filename of path or NULL if we can't allocate * memory. If path is a the string "/", basename returns * the string "/". If path is NULL or an empty string, * "." is returned. */ char *ssh_basename (const char *path) { char *new = NULL; const char *s; size_t len; if (path == NULL || *path == '\0') { return strdup("."); } len = strlen(path); /* Remove trailing slashes */ while(len > 0 && path[len - 1] == '/') --len; /* We have only slashes */ if (len == 0) { return strdup("/"); } while(len > 0 && path[len - 1] != '/') --len; if (len > 0) { s = path + len; len = strlen(s); while(len > 0 && s[len - 1] == '/') --len; } else { return strdup(path); } new = malloc(len + 1); if (new == NULL) { return NULL; } strncpy(new, s, len); new[len] = '\0'; return new; } /** * @brief Attempts to create a directory with the given pathname. * * This is the portable version of mkdir, mode is ignored on Windows systems. * * @param[in] pathname The path name to create the directory. * * @param[in] mode The permissions to use. * * @return 0 on success, < 0 on error with errno set. */ int ssh_mkdir(const char *pathname, mode_t mode) { int r; #ifdef _WIN32 r = _mkdir(pathname); #else r = mkdir(pathname, mode); #endif return r; } /** * @brief Attempts to create a directory with the given pathname. The missing * directories in the given pathname are created recursively. * * @param[in] pathname The path name to create the directory. * * @param[in] mode The permissions to use. * * @return 0 on success, < 0 on error with errno set. * * @note mode is ignored on Windows systems. */ int ssh_mkdirs(const char *pathname, mode_t mode) { int rc = 0; char *parent = NULL; if (pathname == NULL || pathname[0] == '\0' || !strcmp(pathname, "/") || !strcmp(pathname, ".")) { errno = EINVAL; return -1; } errno = 0; #ifdef _WIN32 rc = _mkdir(pathname); #else rc = mkdir(pathname, mode); #endif if (rc < 0) { /* If a directory was missing, try to create the parent */ if (errno == ENOENT) { parent = ssh_dirname(pathname); if (parent == NULL) { errno = ENOMEM; return -1; } rc = ssh_mkdirs(parent, mode); if (rc < 0) { /* We could not create the parent */ SAFE_FREE(parent); return -1; } SAFE_FREE(parent); /* Try again */ errno = 0; #ifdef _WIN32 rc = _mkdir(pathname); #else rc = mkdir(pathname, mode); #endif } } return rc; } /** * @brief Expand a directory starting with a tilde '~' * * @param[in] d The directory to expand. * * @return The expanded directory, NULL on error. */ char *ssh_path_expand_tilde(const char *d) { char *h = NULL, *r; const char *p; size_t ld; size_t lh = 0; if (d[0] != '~') { return strdup(d); } d++; /* handle ~user/path */ p = strchr(d, '/'); if (p != NULL && p > d) { #ifdef _WIN32 return strdup(d); #else struct passwd *pw; size_t s = p - d; char u[128]; if (s >= sizeof(u)) { return NULL; } memcpy(u, d, s); u[s] = '\0'; pw = getpwnam(u); if (pw == NULL) { return NULL; } ld = strlen(p); h = strdup(pw->pw_dir); #endif } else { ld = strlen(d); p = (char *) d; h = ssh_get_user_home_dir(); } if (h == NULL) { return NULL; } lh = strlen(h); r = malloc(ld + lh + 1); if (r == NULL) { SAFE_FREE(h); return NULL; } if (lh > 0) { memcpy(r, h, lh); } SAFE_FREE(h); memcpy(r + lh, p, ld + 1); return r; } /** @internal * @brief expands a string in function of session options * @param[in] s Format string to expand. Known parameters: * %d SSH configuration directory (~/.ssh) * %h target host name * %u local username * %l local hostname * %r remote username * %p remote port * @returns Expanded string. */ char *ssh_path_expand_escape(ssh_session session, const char *s) { char host[NI_MAXHOST]; char buf[MAX_BUF_SIZE]; char *r, *x = NULL; const char *p; size_t i, l; r = ssh_path_expand_tilde(s); if (r == NULL) { ssh_set_error_oom(session); return NULL; } if (strlen(r) > MAX_BUF_SIZE) { ssh_set_error(session, SSH_FATAL, "string to expand too long"); free(r); return NULL; } p = r; buf[0] = '\0'; for (i = 0; *p != '\0'; p++) { if (*p != '%') { escape: buf[i] = *p; i++; if (i >= MAX_BUF_SIZE) { free(r); return NULL; } buf[i] = '\0'; continue; } p++; if (*p == '\0') { break; } switch (*p) { case '%': goto escape; case 'd': x = strdup(session->opts.sshdir); break; case 'u': x = ssh_get_local_username(); break; case 'l': if (gethostname(host, sizeof(host) == 0)) { x = strdup(host); } break; case 'h': x = strdup(session->opts.host); break; case 'r': x = strdup(session->opts.username); break; case 'p': if (session->opts.port < 65536) { char tmp[6]; snprintf(tmp, sizeof(tmp), "%u", session->opts.port > 0 ? session->opts.port : 22); x = strdup(tmp); } break; default: ssh_set_error(session, SSH_FATAL, "Wrong escape sequence detected"); free(r); return NULL; } if (x == NULL) { ssh_set_error_oom(session); free(r); return NULL; } i += strlen(x); if (i >= MAX_BUF_SIZE) { ssh_set_error(session, SSH_FATAL, "String too long"); free(x); free(r); return NULL; } l = strlen(buf); strncpy(buf + l, x, sizeof(buf) - l - 1); buf[i] = '\0'; SAFE_FREE(x); } free(r); return strdup(buf); #undef MAX_BUF_SIZE } /** * @internal * * @brief Analyze the SSH banner to extract version information. * * @param session The session to analyze the banner from. * @param server 0 means we are a client, 1 a server. * * @return 0 on success, < 0 on error. * * @see ssh_get_issue_banner() */ int ssh_analyze_banner(ssh_session session, int server) { const char *banner; const char *openssh; if (server) { banner = session->clientbanner; } else { banner = session->serverbanner; } if (banner == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid banner"); return -1; } /* * Typical banners e.g. are: * * SSH-1.5-openSSH_5.4 * SSH-1.99-openSSH_3.0 * * SSH-2.0-something * 012345678901234567890 */ if (strlen(banner) < 6 || strncmp(banner, "SSH-", 4) != 0) { ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner); return -1; } SSH_LOG(SSH_LOG_PROTOCOL, "Analyzing banner: %s", banner); switch (banner[4]) { case '2': break; case '1': if (strlen(banner) > 6) { if (banner[6] == '9') { break; } } FALL_THROUGH; default: ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner); return -1; } /* Make a best-effort to extract OpenSSH version numbers. */ openssh = strstr(banner, "OpenSSH"); if (openssh != NULL) { char *tmp = NULL; unsigned long int major = 0UL; unsigned long int minor = 0UL; /* * The banner is typical: * OpenSSH_5.4 * 012345678901234567890 */ if (strlen(openssh) > 9) { major = strtoul(openssh + 8, &tmp, 10); if ((tmp == (openssh + 8)) || ((errno == ERANGE) && (major == ULONG_MAX)) || ((errno != 0) && (major == 0)) || ((major < 1) || (major > 100))) { /* invalid major */ goto done; } minor = strtoul(openssh + 10, &tmp, 10); if ((tmp == (openssh + 10)) || ((errno == ERANGE) && (major == ULONG_MAX)) || ((errno != 0) && (major == 0)) || (minor > 100)) { /* invalid minor */ goto done; } session->openssh = SSH_VERSION_INT(((int) major), ((int) minor), 0); SSH_LOG(SSH_LOG_PROTOCOL, "We are talking to an OpenSSH client version: %lu.%lu (%x)", major, minor, session->openssh); } } done: return 0; } /* try the Monotonic clock if possible for perfs reasons */ #ifdef _POSIX_MONOTONIC_CLOCK #define CLOCK CLOCK_MONOTONIC #else #define CLOCK CLOCK_REALTIME #endif /** * @internal * @brief initializes a timestamp to the current time * @param[out] ts pointer to an allocated ssh_timestamp structure */ void ssh_timestamp_init(struct ssh_timestamp *ts){ #ifdef HAVE_CLOCK_GETTIME struct timespec tp; clock_gettime(CLOCK, &tp); ts->useconds = tp.tv_nsec / 1000; #else struct timeval tp; gettimeofday(&tp, NULL); ts->useconds = tp.tv_usec; #endif ts->seconds = tp.tv_sec; } #undef CLOCK /** * @internal * @brief gets the time difference between two timestamps in ms * @param[in] old older value * @param[in] new newer value * @returns difference in milliseconds */ static int ssh_timestamp_difference(struct ssh_timestamp *old, struct ssh_timestamp *new){ long seconds, usecs, msecs; seconds = new->seconds - old->seconds; usecs = new->useconds - old->useconds; if (usecs < 0){ seconds--; usecs += 1000000; } msecs = seconds * 1000 + usecs/1000; return msecs; } /** * @internal * @brief turn seconds and microseconds pair (as provided by user-set options) * into millisecond value * @param[in] sec number of seconds * @param[in] usec number of microseconds * @returns milliseconds, or 10000 if user supplied values are equal to zero */ int ssh_make_milliseconds(long sec, long usec) { int res = usec ? (usec / 1000) : 0; res += (sec * 1000); if (res == 0) { res = 10 * 1000; /* use a reasonable default value in case * SSH_OPTIONS_TIMEOUT is not set in options. */ } return res; } /** * @internal * @brief Checks if a timeout is elapsed, in function of a previous * timestamp and an assigned timeout * @param[in] ts pointer to an existing timestamp * @param[in] timeout timeout in milliseconds. Negative values mean infinite * timeout * @returns 1 if timeout is elapsed * 0 otherwise */ int ssh_timeout_elapsed(struct ssh_timestamp *ts, int timeout) { struct ssh_timestamp now; switch(timeout) { case -2: /* * -2 means user-defined timeout as available in * session->timeout, session->timeout_usec. */ SSH_LOG(SSH_LOG_WARN, "ssh_timeout_elapsed called with -2. this needs to " "be fixed. please set a breakpoint on misc.c:%d and " "fix the caller\n", __LINE__); return 0; case -1: /* -1 means infinite timeout */ return 0; case 0: /* 0 means no timeout */ return 1; default: break; } ssh_timestamp_init(&now); return (ssh_timestamp_difference(ts,&now) >= timeout); } /** * @brief updates a timeout value so it reflects the remaining time * @param[in] ts pointer to an existing timestamp * @param[in] timeout timeout in milliseconds. Negative values mean infinite * timeout * @returns remaining time in milliseconds, 0 if elapsed, -1 if never. */ int ssh_timeout_update(struct ssh_timestamp *ts, int timeout){ struct ssh_timestamp now; int ms, ret; if (timeout <= 0) { return timeout; } ssh_timestamp_init(&now); ms = ssh_timestamp_difference(ts,&now); if(ms < 0) ms = 0; ret = timeout - ms; return ret >= 0 ? ret: 0; } int ssh_match_group(const char *group, const char *object) { const char *a; const char *z; z = group; do { a = strchr(z, ','); if (a == NULL) { if (strcmp(z, object) == 0) { return 1; } return 0; } else { if (strncmp(z, object, a - z) == 0) { return 1; } } z = a + 1; } while(1); /* not reached */ return 0; } #if !defined(HAVE_EXPLICIT_BZERO) void explicit_bzero(void *s, size_t n) { #if defined(HAVE_MEMSET_S) memset_s(s, n, '\0', n); #elif defined(HAVE_SECURE_ZERO_MEMORY) SecureZeroMemory(s, n); #else memset(s, '\0', n); #if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION) /* See http://llvm.org/bugs/show_bug.cgi?id=15495 */ __asm__ volatile("" : : "g"(s) : "memory"); #endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */ #endif } #endif /* !HAVE_EXPLICIT_BZERO */ #if !defined(HAVE_STRNDUP) char *strndup(const char *s, size_t n) { char *x = NULL; if (n + 1 < n) { return NULL; } x = malloc(n + 1); if (x == NULL) { return NULL; } memcpy(x, s, n); x[n] = '\0'; return x; } #endif /* ! HAVE_STRNDUP */ /* Increment 64b integer in network byte order */ void uint64_inc(unsigned char *counter) { int i; for (i = 7; i >= 0; i--) { counter[i]++; if (counter[i]) return; } } /** * @internal * * @brief Quote file name to be used on shell. * * Try to put the given file name between single quotes. There are special * cases: * * - When the '\'' char is found in the file name, it is double quoted * - example: * input: a'b * output: 'a'"'"'b' * - When the '!' char is found in the file name, it is replaced by an unquoted * verbatim char "\!" * - example: * input: a!b * output 'a'\!'b' * * @param[in] file_name File name string to be quoted before used on shell * @param[out] buf Buffer to receive the final quoted file name. Must * have room for the final quoted string. The maximum * output length would be (3 * strlen(file_name) + 1) * since in the worst case each character would be * replaced by 3 characters, plus the terminating '\0'. * @param[in] buf_len The size of the provided output buffer * * @returns SSH_ERROR on error; length of the resulting string not counting the * string terminator '\0' * */ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len) { const char *src = NULL; char *dst = NULL; size_t required_buf_len; enum ssh_quote_state_e state = NO_QUOTE; if (file_name == NULL || buf == NULL || buf_len == 0) { SSH_LOG(SSH_LOG_WARNING, "Invalid parameter"); return SSH_ERROR; } /* Only allow file names smaller than 32kb. */ if (strlen(file_name) > 32 * 1024) { SSH_LOG(SSH_LOG_WARNING, "File name too long"); return SSH_ERROR; } /* Paranoia check */ required_buf_len = (size_t)3 * strlen(file_name) + 1; if (required_buf_len > buf_len) { SSH_LOG(SSH_LOG_WARNING, "Buffer too small"); return SSH_ERROR; } src = file_name; dst = buf; while ((*src != '\0')) { switch (*src) { /* The '\'' char is double quoted */ case '\'': switch (state) { case NO_QUOTE: /* Start a new double quoted string. The '\'' char will be * copied to the beginning of it at the end of the loop. */ *dst++ = '"'; break; case SINGLE_QUOTE: /* Close the current single quoted string and start a new double * quoted string. The '\'' char will be copied to the beginning * of it at the end of the loop. */ *dst++ = '\''; *dst++ = '"'; break; case DOUBLE_QUOTE: /* If already in the double quoted string, keep copying the * sequence of chars. */ break; default: /* Should never be reached */ goto error; } /* When the '\'' char is found, the resulting state will be * DOUBLE_QUOTE in any case*/ state = DOUBLE_QUOTE; break; /* The '!' char is replaced by unquoted "\!" */ case '!': switch (state) { case NO_QUOTE: /* The '!' char is interpreted in some shells (e.g. CSH) even * when is quoted with single quotes. Replace it with unquoted * "\!" which is correctly interpreted as the '!' character. */ *dst++ = '\\'; break; case SINGLE_QUOTE: /* Close the current quoted string and replace '!' for unquoted * "\!" */ *dst++ = '\''; *dst++ = '\\'; break; case DOUBLE_QUOTE: /* Close current quoted string and replace "!" for unquoted * "\!" */ *dst++ = '"'; *dst++ = '\\'; break; default: /* Should never be reached */ goto error; } /* When the '!' char is found, the resulting state will be NO_QUOTE * in any case*/ state = NO_QUOTE; break; /* Ordinary chars are single quoted */ default: switch (state) { case NO_QUOTE: /* Start a new single quoted string */ *dst++ = '\''; break; case SINGLE_QUOTE: /* If already in the single quoted string, keep copying the * sequence of chars. */ break; case DOUBLE_QUOTE: /* Close current double quoted string and start a new single * quoted string. */ *dst++ = '"'; *dst++ = '\''; break; default: /* Should never be reached */ goto error; } /* When an ordinary char is found, the resulting state will be * SINGLE_QUOTE in any case*/ state = SINGLE_QUOTE; break; } /* Copy the current char to output */ *dst++ = *src++; } /* Close the quoted string when necessary */ switch (state) { case NO_QUOTE: /* No open string */ break; case SINGLE_QUOTE: /* Close current single quoted string */ *dst++ = '\''; break; case DOUBLE_QUOTE: /* Close current double quoted string */ *dst++ = '"'; break; default: /* Should never be reached */ goto error; } /* Put the string terminator */ *dst = '\0'; return dst - buf; error: return SSH_ERROR; } /** * @internal * * @brief Given a string, encode existing newlines as the string "\\n" * * @param[in] string Input string * @param[out] buf Output buffer. This buffer must be at least (2 * * strlen(string)) + 1 long. In the worst case, * each character can be encoded as 2 characters plus the * terminating '\0'. * @param[in] buf_len Size of the provided output buffer * * @returns SSH_ERROR on error; length of the resulting string not counting the * terminating '\0' otherwise */ int ssh_newline_vis(const char *string, char *buf, size_t buf_len) { const char *in = NULL; char *out = NULL; if (string == NULL || buf == NULL || buf_len == 0) { return SSH_ERROR; } if ((2 * strlen(string) + 1) > buf_len) { SSH_LOG(SSH_LOG_WARNING, "Buffer too small"); return SSH_ERROR; } out = buf; for (in = string; *in != '\0'; in++) { if (*in == '\n') { *out++ = '\\'; *out++ = 'n'; } else { *out++ = *in; } } *out = '\0'; return out - buf; } /** @} */ ================================================ FILE: src/libssh/src/options.c ================================================ /* * options.c - handle pre-connection options * * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #ifndef _WIN32 #include #else #include #endif #include #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/options.h" #ifdef WITH_SERVER #include "libssh/server.h" #include "libssh/bind.h" #include "libssh/bind_config.h" #endif /** * @addtogroup libssh_session * @{ */ /** * @brief Duplicate the options of a session structure. * * If you make several sessions with the same options this is useful. You * cannot use twice the same option structure in ssh_session_connect. * * @param src The session to use to copy the options. * * @param dest A pointer to store the allocated session with duplicated * options. You have to free the memory. * * @returns 0 on sucess, -1 on error with errno set. * * @see ssh_session_connect() */ int ssh_options_copy(ssh_session src, ssh_session *dest) { ssh_session new; struct ssh_iterator *it = NULL; char *id = NULL; int i; if (src == NULL || dest == NULL) { return -1; } new = ssh_new(); if (new == NULL) { return -1; } if (src->opts.username != NULL) { new->opts.username = strdup(src->opts.username); if (new->opts.username == NULL) { ssh_free(new); return -1; } } if (src->opts.host != NULL) { new->opts.host = strdup(src->opts.host); if (new->opts.host == NULL) { ssh_free(new); return -1; } } if (src->opts.bindaddr != NULL) { new->opts.bindaddr = strdup(src->opts.bindaddr); if (new->opts.bindaddr == NULL) { ssh_free(new); return -1; } } /* Remove the default identities */ for (id = ssh_list_pop_head(char *, new->opts.identity); id != NULL; id = ssh_list_pop_head(char *, new->opts.identity)) { SAFE_FREE(id); } /* Copy the new identities from the source list */ if (src->opts.identity != NULL) { it = ssh_list_get_iterator(src->opts.identity); while (it) { int rc; id = strdup((char *) it->data); if (id == NULL) { ssh_free(new); return -1; } rc = ssh_list_append(new->opts.identity, id); if (rc < 0) { free(id); ssh_free(new); return -1; } it = it->next; } } if (src->opts.sshdir != NULL) { new->opts.sshdir = strdup(src->opts.sshdir); if (new->opts.sshdir == NULL) { ssh_free(new); return -1; } } if (src->opts.knownhosts != NULL) { new->opts.knownhosts = strdup(src->opts.knownhosts); if (new->opts.knownhosts == NULL) { ssh_free(new); return -1; } } if (src->opts.global_knownhosts != NULL) { new->opts.global_knownhosts = strdup(src->opts.global_knownhosts); if (new->opts.global_knownhosts == NULL) { ssh_free(new); return -1; } } for (i = 0; i < SSH_KEX_METHODS; i++) { if (src->opts.wanted_methods[i] != NULL) { new->opts.wanted_methods[i] = strdup(src->opts.wanted_methods[i]); if (new->opts.wanted_methods[i] == NULL) { ssh_free(new); return -1; } } } if (src->opts.ProxyCommand != NULL) { new->opts.ProxyCommand = strdup(src->opts.ProxyCommand); if (new->opts.ProxyCommand == NULL) { ssh_free(new); return -1; } } if (src->opts.pubkey_accepted_types != NULL) { new->opts.pubkey_accepted_types = strdup(src->opts.pubkey_accepted_types); if (new->opts.pubkey_accepted_types == NULL) { ssh_free(new); return -1; } } if (src->opts.gss_server_identity != NULL) { new->opts.gss_server_identity = strdup(src->opts.gss_server_identity); if (new->opts.gss_server_identity == NULL) { ssh_free(new); return -1; } } if (src->opts.gss_client_identity != NULL) { new->opts.gss_client_identity = strdup(src->opts.gss_client_identity); if (new->opts.gss_client_identity == NULL) { ssh_free(new); return -1; } } memcpy(new->opts.options_seen, src->opts.options_seen, sizeof(new->opts.options_seen)); new->opts.fd = src->opts.fd; new->opts.port = src->opts.port; new->opts.timeout = src->opts.timeout; new->opts.timeout_usec = src->opts.timeout_usec; new->opts.compressionlevel = src->opts.compressionlevel; new->opts.StrictHostKeyChecking = src->opts.StrictHostKeyChecking; new->opts.gss_delegate_creds = src->opts.gss_delegate_creds; new->opts.flags = src->opts.flags; new->opts.nodelay = src->opts.nodelay; new->opts.config_processed = src->opts.config_processed; new->common.log_verbosity = src->common.log_verbosity; new->common.callbacks = src->common.callbacks; *dest = new; return 0; } int ssh_options_set_algo(ssh_session session, enum ssh_kex_types_e algo, const char *list) { char *p = NULL; if (ssh_fips_mode()) { p = ssh_keep_fips_algos(algo, list); } else { p = ssh_keep_known_algos(algo, list); } if (p == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Setting method: no allowed algorithm for method \"%s\" (%s)", ssh_kex_get_description(algo), list); return -1; } SAFE_FREE(session->opts.wanted_methods[algo]); session->opts.wanted_methods[algo] = p; return 0; } /** * @brief This function can set all possible ssh options. * * @param session An allocated SSH session structure. * * @param type The option type to set. This could be one of the * following: * * - SSH_OPTIONS_HOST: * The hostname or ip address to connect to (const char *). * * - SSH_OPTIONS_PORT: * The port to connect to (unsigned int *). * * - SSH_OPTIONS_PORT_STR: * The port to connect to (const char *). * * - SSH_OPTIONS_FD: * The file descriptor to use (socket_t).\n * \n * If you wish to open the socket yourself for a reason * or another, set the file descriptor. Don't forget to * set the hostname as the hostname is used as a key in * the known_host mechanism. * * - SSH_OPTIONS_BINDADDR: * The address to bind the client to (const char *). * * - SSH_OPTIONS_USER: * The username for authentication (const char *).\n * \n * If the value is NULL, the username is set to the * default username. * * - SSH_OPTIONS_SSH_DIR: * Set the ssh directory (const char *,format string).\n * \n * If the value is NULL, the directory is set to the * default ssh directory.\n * \n * The ssh directory is used for files like known_hosts * and identity (private and public key). It may include * "%s" which will be replaced by the user home * directory. * * - SSH_OPTIONS_KNOWNHOSTS: * Set the known hosts file name (const char *,format string).\n * \n * If the value is NULL, the directory is set to the * default known hosts file, normally * ~/.ssh/known_hosts.\n * \n * The known hosts file is used to certify remote hosts * are genuine. It may include "%d" which will be * replaced by the user home directory. * * - SSH_OPTIONS_GLOBAL_KNOWNHOSTS: * Set the global known hosts file name (const char *,format string).\n * \n * If the value is NULL, the directory is set to the * default global known hosts file, normally * /etc/ssh/ssh_known_hosts.\n * \n * The known hosts file is used to certify remote hosts * are genuine. * * - SSH_OPTIONS_ADD_IDENTITY (or SSH_OPTIONS_IDENTITY): * Add a new identity file (const char *, format string) to * the identity list.\n * \n * By default identity, id_dsa and id_rsa are checked.\n * \n * The identity used to authenticate with public key will be * prepended to the list. * It may include "%s" which will be replaced by the * user home directory. * * - SSH_OPTIONS_TIMEOUT: * Set a timeout for the connection in seconds (long). * * - SSH_OPTIONS_TIMEOUT_USEC: * Set a timeout for the connection in micro seconds * (long). * * - SSH_OPTIONS_SSH1: * Deprecated * * - SSH_OPTIONS_SSH2: * Unused * * - SSH_OPTIONS_LOG_VERBOSITY: * Set the session logging verbosity (int).\n * \n * The verbosity of the messages. Every log smaller or * equal to verbosity will be shown. * - SSH_LOG_NOLOG: No logging * - SSH_LOG_WARNING: Only warnings * - SSH_LOG_PROTOCOL: High level protocol information * - SSH_LOG_PACKET: Lower level protocol infomations, packet level * - SSH_LOG_FUNCTIONS: Every function path * * - SSH_OPTIONS_LOG_VERBOSITY_STR: * Set the session logging verbosity via a * string that will be converted to a numerical * value (e.g. "3") and interpreted according * to the values of * SSH_OPTIONS_LOG_VERBOSITY above (const * char *). * * - SSH_OPTIONS_CIPHERS_C_S: * Set the symmetric cipher client to server (const char *, * comma-separated list). * * - SSH_OPTIONS_CIPHERS_S_C: * Set the symmetric cipher server to client (const char *, * comma-separated list). * * - SSH_OPTIONS_KEY_EXCHANGE: * Set the key exchange method to be used (const char *, * comma-separated list). ex: * "ecdh-sha2-nistp256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" * * - SSH_OPTIONS_HMAC_C_S: * Set the Message Authentication Code algorithm client to server * (const char *, comma-separated list). * * - SSH_OPTIONS_HMAC_S_C: * Set the Message Authentication Code algorithm server to client * (const char *, comma-separated list). * * - SSH_OPTIONS_HOSTKEYS: * Set the preferred server host key types (const char *, * comma-separated list). ex: * "ssh-rsa,ssh-dss,ecdh-sha2-nistp256" * * - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES: * Set the preferred public key algorithms to be used for * authentication (const char *, comma-separated list). ex: * "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256" * * - SSH_OPTIONS_COMPRESSION_C_S: * Set the compression to use for client to server * communication (const char *, "yes", "no" or a specific * algorithm name if needed ("zlib","zlib@openssh.com","none"). * * - SSH_OPTIONS_COMPRESSION_S_C: * Set the compression to use for server to client * communication (const char *, "yes", "no" or a specific * algorithm name if needed ("zlib","zlib@openssh.com","none"). * * - SSH_OPTIONS_COMPRESSION: * Set the compression to use for both directions * communication (const char *, "yes", "no" or a specific * algorithm name if needed ("zlib","zlib@openssh.com","none"). * * - SSH_OPTIONS_COMPRESSION_LEVEL: * Set the compression level to use for zlib functions. (int, * value from 1 to 9, 9 being the most efficient but slower). * * - SSH_OPTIONS_STRICTHOSTKEYCHECK: * Set the parameter StrictHostKeyChecking to avoid * asking about a fingerprint (int, 0 = false). * * - SSH_OPTIONS_PROXYCOMMAND: * Set the command to be executed in order to connect to * server (const char *). * * - SSH_OPTIONS_GSSAPI_SERVER_IDENTITY * Set it to specify the GSSAPI server identity that libssh * should expect when connecting to the server (const char *). * * - SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY * Set it to specify the GSSAPI client identity that libssh * should expect when connecting to the server (const char *). * * - SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS * Set it to specify that GSSAPI should delegate credentials * to the server (int, 0 = false). * * - SSH_OPTIONS_PASSWORD_AUTH * Set it if password authentication should be used * in ssh_userauth_auto_pubkey(). (int, 0=false). * Currently without effect (ssh_userauth_auto_pubkey doesn't use * password authentication). * * - SSH_OPTIONS_PUBKEY_AUTH * Set it if pubkey authentication should be used * in ssh_userauth_auto_pubkey(). (int, 0=false). * * - SSH_OPTIONS_KBDINT_AUTH * Set it if keyboard-interactive authentication should be used * in ssh_userauth_auto_pubkey(). (int, 0=false). * Currently without effect (ssh_userauth_auto_pubkey doesn't use * keyboard-interactive authentication). * * - SSH_OPTIONS_GSSAPI_AUTH * Set it if gssapi authentication should be used * in ssh_userauth_auto_pubkey(). (int, 0=false). * Currently without effect (ssh_userauth_auto_pubkey doesn't use * gssapi authentication). * * - SSH_OPTIONS_NODELAY * Set it to disable Nagle's Algorithm (TCP_NODELAY) on the * session socket. (int, 0=false) * * - SSH_OPTIONS_PROCESS_CONFIG * Set it to false to disable automatic processing of per-user * and system-wide OpenSSH configuration files. LibSSH * automatically uses these configuration files unless * you provide it with this option or with different file (bool). * * - SSH_OPTIONS_REKEY_DATA * Set the data limit that can be transferred with a single * key in bytes. RFC 4253 Section 9 recommends 1GB of data, while * RFC 4344 provides more specific restrictions, that are applied * automatically. When specified, the lower value will be used. * (uint64_t, 0=default) * * - SSH_OPTIONS_REKEY_TIME * Set the time limit for a session before intializing a rekey * in seconds. RFC 4253 Section 9 recommends one hour. * (uint32_t, 0=off) * * @param value The value to set. This is a generic pointer and the * datatype which is used should be set according to the * type set. * * @return 0 on success, < 0 on error. */ int ssh_options_set(ssh_session session, enum ssh_options_e type, const void *value) { const char *v; char *p, *q; long int i; unsigned int u; int rc; if (session == NULL) { return -1; } switch (type) { case SSH_OPTIONS_HOST: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { q = strdup(value); if (q == NULL) { ssh_set_error_oom(session); return -1; } p = strchr(q, '@'); SAFE_FREE(session->opts.host); if (p) { *p = '\0'; session->opts.host = strdup(p + 1); if (session->opts.host == NULL) { SAFE_FREE(q); ssh_set_error_oom(session); return -1; } SAFE_FREE(session->opts.username); session->opts.username = strdup(q); SAFE_FREE(q); if (session->opts.username == NULL) { ssh_set_error_oom(session); return -1; } } else { session->opts.host = q; } } break; case SSH_OPTIONS_PROXY_HOST: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { q = strdup(value); if (q == NULL) { ssh_set_error_oom(session); return -1; } p = strchr(q, '@'); SAFE_FREE(session->opts.proxy_host); if (p) { *p = '\0'; session->opts.proxy_host = strdup(p + 1); if (session->opts.proxy_host == NULL) { SAFE_FREE(q); ssh_set_error_oom(session); return -1; } SAFE_FREE(session->opts.username); session->opts.username = strdup(q); SAFE_FREE(q); if (session->opts.username == NULL) { ssh_set_error_oom(session); return -1; } } else { session->opts.proxy_host = q; } } break; case SSH_OPTIONS_PORT: case SSH_OPTIONS_PROXY_PORT: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int *x = (int *) value; if (*x <= 0) { ssh_set_error_invalid(session); return -1; } if (type == SSH_OPTIONS_PORT) { session->opts.port = *x & 0xffffU; } else if (type == SSH_OPTIONS_PROXY_PORT) { session->opts.proxy_port = *x & 0xffffU; } } break; case SSH_OPTIONS_PORT_STR: case SSH_OPTIONS_PROXY_PORT_STR: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { q = strdup(v); if (q == NULL) { ssh_set_error_oom(session); return -1; } i = strtol(q, &p, 10); if (q == p) { SAFE_FREE(q); } SAFE_FREE(q); if (i <= 0) { ssh_set_error_invalid(session); return -1; } if (type == SSH_OPTIONS_PORT_STR) { session->opts.port = i & 0xffffU; } else if (type == SSH_OPTIONS_PROXY_PORT_STR) { session->opts.proxy_port = i & 0xffffU; } } break; case SSH_OPTIONS_FD: if (value == NULL) { session->opts.fd = SSH_INVALID_SOCKET; ssh_set_error_invalid(session); return -1; } else { socket_t *x = (socket_t *) value; if (*x < 0) { session->opts.fd = SSH_INVALID_SOCKET; ssh_set_error_invalid(session); return -1; } session->opts.fd = *x & 0xffff; } break; case SSH_OPTIONS_BINDADDR: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } q = strdup(v); if (q == NULL) { return -1; } SAFE_FREE(session->opts.bindaddr); session->opts.bindaddr = q; break; case SSH_OPTIONS_USER: v = value; SAFE_FREE(session->opts.username); if (v == NULL) { q = ssh_get_local_username(); if (q == NULL) { ssh_set_error_oom(session); return -1; } session->opts.username = q; } else if (v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { /* username provided */ session->opts.username = strdup(value); if (session->opts.username == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_SSH_DIR: v = value; SAFE_FREE(session->opts.sshdir); if (v == NULL) { session->opts.sshdir = ssh_path_expand_tilde("~/.ssh"); if (session->opts.sshdir == NULL) { return -1; } } else if (v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { session->opts.sshdir = ssh_path_expand_tilde(v); if (session->opts.sshdir == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_IDENTITY: case SSH_OPTIONS_ADD_IDENTITY: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } q = strdup(v); if (q == NULL) { return -1; } rc = ssh_list_prepend(session->opts.identity, q); if (rc < 0) { free(q); return -1; } break; case SSH_OPTIONS_KNOWNHOSTS: v = value; SAFE_FREE(session->opts.knownhosts); if (v == NULL) { /* The default value will be set by the ssh_options_apply() */ } else if (v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { session->opts.knownhosts = strdup(v); if (session->opts.knownhosts == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: v = value; SAFE_FREE(session->opts.global_knownhosts); if (v == NULL) { session->opts.global_knownhosts = strdup("/etc/ssh/ssh_known_hosts"); if (session->opts.global_knownhosts == NULL) { ssh_set_error_oom(session); return -1; } } else if (v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { session->opts.global_knownhosts = strdup(v); if (session->opts.global_knownhosts == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_TIMEOUT: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { long *x = (long *) value; if (*x < 0) { ssh_set_error_invalid(session); return -1; } session->opts.timeout = *x & 0xffffffffU; } break; case SSH_OPTIONS_TIMEOUT_USEC: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { long *x = (long *) value; if (*x < 0) { ssh_set_error_invalid(session); return -1; } session->opts.timeout_usec = *x & 0xffffffffU; } break; case SSH_OPTIONS_SSH1: break; case SSH_OPTIONS_SSH2: break; case SSH_OPTIONS_LOG_VERBOSITY: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int *x = (int *) value; if (*x < 0) { ssh_set_error_invalid(session); return -1; } session->common.log_verbosity = *x & 0xffffU; ssh_set_log_level(*x & 0xffffU); } break; case SSH_OPTIONS_LOG_VERBOSITY_STR: v = value; if (v == NULL || v[0] == '\0') { session->common.log_verbosity = 0; ssh_set_error_invalid(session); return -1; } else { q = strdup(v); if (q == NULL) { ssh_set_error_oom(session); return -1; } i = strtol(q, &p, 10); if (q == p) { SAFE_FREE(q); } SAFE_FREE(q); if (i < 0) { ssh_set_error_invalid(session); return -1; } session->common.log_verbosity = i & 0xffffU; ssh_set_log_level(i & 0xffffU); } break; case SSH_OPTIONS_CIPHERS_C_S: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_CRYPT_C_S, v) < 0) return -1; } break; case SSH_OPTIONS_CIPHERS_S_C: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_CRYPT_S_C, v) < 0) return -1; } break; case SSH_OPTIONS_KEY_EXCHANGE: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_KEX, v) < 0) return -1; } break; case SSH_OPTIONS_HOSTKEYS: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_HOSTKEYS, v) < 0) return -1; } break; case SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_fips_mode()) { p = ssh_keep_fips_algos(SSH_HOSTKEYS, v); } else { p = ssh_keep_known_algos(SSH_HOSTKEYS, v); } if (p == NULL) { ssh_set_error(session, SSH_REQUEST_DENIED, "Setting method: no known public key algorithm (%s)", v); return -1; } SAFE_FREE(session->opts.pubkey_accepted_types); session->opts.pubkey_accepted_types = p; } break; case SSH_OPTIONS_HMAC_C_S: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_MAC_C_S, v) < 0) return -1; } break; case SSH_OPTIONS_HMAC_S_C: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (ssh_options_set_algo(session, SSH_MAC_S_C, v) < 0) return -1; } break; case SSH_OPTIONS_COMPRESSION_C_S: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (strcasecmp(value,"yes")==0){ if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,zlib") < 0) return -1; } else if (strcasecmp(value,"no")==0){ if(ssh_options_set_algo(session,SSH_COMP_C_S,"none") < 0) return -1; } else { if (ssh_options_set_algo(session, SSH_COMP_C_S, v) < 0) return -1; } } break; case SSH_OPTIONS_COMPRESSION_S_C: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { if (strcasecmp(value,"yes")==0){ if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,zlib") < 0) return -1; } else if (strcasecmp(value,"no")==0){ if(ssh_options_set_algo(session,SSH_COMP_S_C,"none") < 0) return -1; } else { if (ssh_options_set_algo(session, SSH_COMP_S_C, v) < 0) return -1; } } break; case SSH_OPTIONS_COMPRESSION: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_C_S, v) < 0) return -1; if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_S_C, v) < 0) return -1; break; case SSH_OPTIONS_COMPRESSION_LEVEL: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int *x = (int *)value; if (*x < 1 || *x > 9) { ssh_set_error_invalid(session); return -1; } session->opts.compressionlevel = *x & 0xff; } break; case SSH_OPTIONS_STRICTHOSTKEYCHECK: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int *x = (int *) value; session->opts.StrictHostKeyChecking = (*x & 0xff) > 0 ? 1 : 0; } session->opts.StrictHostKeyChecking = *(int*)value; break; case SSH_OPTIONS_PROXYCOMMAND: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { SAFE_FREE(session->opts.ProxyCommand); /* Setting the command to 'none' disables this option. */ rc = strcasecmp(v, "none"); if (rc != 0) { q = strdup(v); if (q == NULL) { return -1; } session->opts.ProxyCommand = q; } } break; case SSH_OPTIONS_GSSAPI_SERVER_IDENTITY: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { SAFE_FREE(session->opts.gss_server_identity); session->opts.gss_server_identity = strdup(v); if (session->opts.gss_server_identity == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(session); return -1; } else { SAFE_FREE(session->opts.gss_client_identity); session->opts.gss_client_identity = strdup(v); if (session->opts.gss_client_identity == NULL) { ssh_set_error_oom(session); return -1; } } break; case SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int x = *(int *)value; session->opts.gss_delegate_creds = (x & 0xff); } break; case SSH_OPTIONS_PASSWORD_AUTH: case SSH_OPTIONS_PUBKEY_AUTH: case SSH_OPTIONS_KBDINT_AUTH: case SSH_OPTIONS_GSSAPI_AUTH: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int x = *(int *)value; u = type == SSH_OPTIONS_PASSWORD_AUTH ? SSH_OPT_FLAG_PASSWORD_AUTH: type == SSH_OPTIONS_PUBKEY_AUTH ? SSH_OPT_FLAG_PUBKEY_AUTH: type == SSH_OPTIONS_KBDINT_AUTH ? SSH_OPT_FLAG_KBDINT_AUTH: SSH_OPT_FLAG_GSSAPI_AUTH; if (x != 0){ session->opts.flags |= u; } else { session->opts.flags &= ~u; } } break; case SSH_OPTIONS_NODELAY: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { int *x = (int *) value; session->opts.nodelay = (*x & 0xff) > 0 ? 1 : 0; } break; case SSH_OPTIONS_PROCESS_CONFIG: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { bool *x = (bool *)value; session->opts.config_processed = !(*x); } break; case SSH_OPTIONS_REKEY_DATA: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { uint64_t *x = (uint64_t *)value; session->opts.rekey_data = *x; } break; case SSH_OPTIONS_REKEY_TIME: if (value == NULL) { ssh_set_error_invalid(session); return -1; } else { uint32_t *x = (uint32_t *)value; if ((*x * 1000) < *x) { ssh_set_error(session, SSH_REQUEST_DENIED, "The provided value (%" PRIu32 ") for rekey" " time is too large", *x); return -1; } session->opts.rekey_time = (*x) * 1000; } break; case SSH_OPTIONS_EXTERNAL_CALLBACKS: if (value == NULL) { session->socket_external_callbacks.send = NULL; session->socket_external_callbacks.userdata = NULL; } else { ssh_socket_external_callbacks external_callbacks = (ssh_socket_external_callbacks) value; session->socket_external_callbacks.send = external_callbacks->send; session->socket_external_callbacks.userdata = external_callbacks->userdata; } break; default: ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); return -1; break; } return 0; } /** * @brief This function can get ssh the ssh port. It must only be used on * a valid ssh session. This function is useful when the session * options have been automatically inferred from the environment * or configuration files and one * * @param session An allocated SSH session structure. * * @param port_target An unsigned integer into which the * port will be set from the ssh session. * * @return 0 on success, < 0 on error. * */ int ssh_options_get_port(ssh_session session, unsigned int* port_target) { if (session == NULL) { return -1; } if (session->opts.port == 0) { *port_target = 22; return 0; } *port_target = session->opts.port; return 0; } /** * @brief This function can get ssh options, it does not support all options provided for * ssh options set, but mostly those which a user-space program may care about having * trusted the ssh driver to infer these values from underlaying configuration files. * It operates only on those SSH_OPTIONS_* which return char*. If you wish to receive * the port then please use ssh_options_get_port() which returns an unsigned int. * * @param session An allocated SSH session structure. * * @param type The option type to get. This could be one of the * following: * * - SSH_OPTIONS_HOST: * The hostname or ip address to connect to (const char *). * * - SSH_OPTIONS_USER: * The username for authentication (const char *).\n * \n when not explicitly set this will be inferred from the * ~/.ssh/config file. * * - SSH_OPTIONS_IDENTITY: * Get the first identity file name (const char *).\n * \n * By default identity, id_dsa and id_rsa are checked. * * - SSH_OPTIONS_PROXYCOMMAND: * Get the proxycommand necessary to log into the * remote host. When not explicitly set, it will be read * from the ~/.ssh/config file. * * - SSH_OPTIONS_GLOBAL_KNOWNHOSTS: * Get the path to the global known_hosts file being used. * * - SSH_OPTIONS_KNOWNHOSTS: * Get the path to the known_hosts file being used. * * @param value The value to get into. As a char**, space will be * allocated by the function for the value, it is * your responsibility to free the memory using * ssh_string_free_char(). * * @return SSH_OK on success, SSH_ERROR on error. */ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value) { char* src = NULL; if (session == NULL) { return SSH_ERROR; } if (value == NULL) { ssh_set_error_invalid(session); return SSH_ERROR; } switch(type) { case SSH_OPTIONS_HOST: { src = session->opts.host; break; } case SSH_OPTIONS_USER: { src = session->opts.username; break; } case SSH_OPTIONS_IDENTITY: { struct ssh_iterator *it = ssh_list_get_iterator(session->opts.identity); if (it == NULL) { return SSH_ERROR; } src = ssh_iterator_value(char *, it); break; } case SSH_OPTIONS_PROXYCOMMAND: { src = session->opts.ProxyCommand; break; } case SSH_OPTIONS_KNOWNHOSTS: { src = session->opts.knownhosts; break; } case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: { src = session->opts.global_knownhosts; break; } default: ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); return SSH_ERROR; break; } if (src == NULL) { return SSH_ERROR; } *value = strdup(src); if (*value == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } return SSH_OK; } /** * @brief Parse command line arguments. * * This is a helper for your application to generate the appropriate * options from the command line arguments.\n * The argv array and argc value are changed so that the parsed * arguments wont appear anymore in them.\n * The single arguments (without switches) are not parsed. thus, * myssh -l user localhost\n * The command wont set the hostname value of options to localhost. * * @param session The session to configure. * * @param argcptr The pointer to the argument count. * * @param argv The arguments list pointer. * * @returns 0 on success, < 0 on error. * * @see ssh_session_new() */ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) { #ifdef _MSC_VER (void)session; (void)argcptr; (void)argv; /* Not supported with a Microsoft compiler */ return -1; #else char *user = NULL; char *cipher = NULL; char *identity = NULL; char *port = NULL; char **save = NULL; char **tmp = NULL; size_t i = 0; int argc = *argcptr; int debuglevel = 0; int usersa = 0; int usedss = 0; int compress = 0; int cont = 1; size_t current = 0; int saveoptind = optind; /* need to save 'em */ int saveopterr = opterr; int opt; opterr = 0; /* shut up getopt */ while((opt = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1) { switch(opt) { case 'l': user = optarg; break; case 'p': port = optarg; break; case 'v': debuglevel++; break; case 'r': usersa++; break; case 'd': usedss++; break; case 'c': cipher = optarg; break; case 'i': identity = optarg; break; case 'C': compress++; break; case '2': break; case '1': break; default: { char optv[3] = "- "; optv[1] = optopt; tmp = realloc(save, (current + 1) * sizeof(char*)); if (tmp == NULL) { SAFE_FREE(save); ssh_set_error_oom(session); return -1; } save = tmp; save[current] = strdup(optv); if (save[current] == NULL) { SAFE_FREE(save); ssh_set_error_oom(session); return -1; } current++; if (optarg) { save[current++] = argv[optind + 1]; } } } /* switch */ } /* while */ opterr = saveopterr; tmp = realloc(save, (current + (argc - optind)) * sizeof(char*)); if (tmp == NULL) { SAFE_FREE(save); ssh_set_error_oom(session); return -1; } save = tmp; while (optind < argc) { tmp = realloc(save, (current + 1) * sizeof(char*)); if (tmp == NULL) { SAFE_FREE(save); ssh_set_error_oom(session); return -1; } save = tmp; save[current] = argv[optind]; current++; optind++; } if (usersa && usedss) { ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen"); cont = 0; } ssh_set_log_level(debuglevel); optind = saveoptind; if(!cont) { SAFE_FREE(save); return -1; } /* first recopy the save vector into the original's */ for (i = 0; i < current; i++) { /* don't erase argv[0] */ argv[ i + 1] = save[i]; } argv[current + 1] = NULL; *argcptr = current + 1; SAFE_FREE(save); /* set a new option struct */ if (compress) { if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes") < 0) { cont = 0; } } if (cont && cipher) { if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) { cont = 0; } if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) { cont = 0; } } if (cont && user) { if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { cont = 0; } } if (cont && identity) { if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) { cont = 0; } } if (port != NULL) { ssh_options_set(session, SSH_OPTIONS_PORT_STR, port); } if (!cont) { return SSH_ERROR; } return SSH_OK; #endif } /** * @brief Parse the ssh config file. * * This should be the last call of all options, it may overwrite options which * are already set. It requires that the host name is already set with * ssh_options_set_host(). * * @param session SSH session handle * * @param filename The options file to use, if NULL the default * ~/.ssh/config will be used. * * @return 0 on success, < 0 on error. * * @see ssh_options_set_host() */ int ssh_options_parse_config(ssh_session session, const char *filename) { char *expanded_filename; int r; if (session == NULL) { return -1; } if (session->opts.host == NULL) { ssh_set_error_invalid(session); return -1; } if (session->opts.sshdir == NULL) { r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); if (r < 0) { ssh_set_error_oom(session); return -1; } } /* set default filename */ if (filename == NULL) { expanded_filename = ssh_path_expand_escape(session, "%d/config"); } else { expanded_filename = ssh_path_expand_escape(session, filename); } if (expanded_filename == NULL) { return -1; } r = ssh_config_parse_file(session, expanded_filename); if (r < 0) { goto out; } if (filename == NULL) { r = ssh_config_parse_file(session, GLOBAL_CLIENT_CONFIG); } /* Do not process the default configuration as part of connection again */ session->opts.config_processed = true; out: free(expanded_filename); return r; } int ssh_options_apply(ssh_session session) { struct ssh_iterator *it; char *tmp; int rc; if (session->opts.sshdir == NULL) { rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); if (rc < 0) { return -1; } } if (session->opts.username == NULL) { rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL); if (rc < 0) { return -1; } } if (session->opts.knownhosts == NULL) { tmp = ssh_path_expand_escape(session, "%d/known_hosts"); } else { tmp = ssh_path_expand_escape(session, session->opts.knownhosts); } if (tmp == NULL) { return -1; } free(session->opts.knownhosts); session->opts.knownhosts = tmp; if (session->opts.global_knownhosts == NULL) { tmp = strdup("/etc/ssh/ssh_known_hosts"); } else { tmp = ssh_path_expand_escape(session, session->opts.global_knownhosts); } if (tmp == NULL) { return -1; } free(session->opts.global_knownhosts); session->opts.global_knownhosts = tmp; if (session->opts.ProxyCommand != NULL) { tmp = ssh_path_expand_escape(session, session->opts.ProxyCommand); if (tmp == NULL) { return -1; } free(session->opts.ProxyCommand); session->opts.ProxyCommand = tmp; } for (it = ssh_list_get_iterator(session->opts.identity); it != NULL; it = it->next) { char *id = (char *) it->data; if (strncmp(id, "pkcs11:", 6) == 0) { /* PKCS#11 URIs are using percent-encoding so we can not mix * it with ssh expansion of ssh escape characters. * Skip these identities now, before we will have PKCS#11 support */ continue; } tmp = ssh_path_expand_escape(session, id); if (tmp == NULL) { return -1; } free(id); it->data = tmp; } return 0; } /** @} */ #ifdef WITH_SERVER /** * @addtogroup libssh_server * @{ */ static int ssh_bind_set_key(ssh_bind sshbind, char **key_loc, const void *value) { if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { SAFE_FREE(*key_loc); *key_loc = strdup(value); if (*key_loc == NULL) { ssh_set_error_oom(sshbind); return -1; } } return 0; } static int ssh_bind_set_algo(ssh_bind sshbind, enum ssh_kex_types_e algo, const char *list) { char *p = NULL; if (ssh_fips_mode()) { p = ssh_keep_fips_algos(algo, list); } else { p = ssh_keep_known_algos(algo, list); } if (p == NULL) { ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Setting method: no algorithm for method \"%s\" (%s)", ssh_kex_get_description(algo), list); return -1; } SAFE_FREE(sshbind->wanted_methods[algo]); sshbind->wanted_methods[algo] = p; return 0; } /** * @brief Set options for an SSH server bind. * * @param sshbind The ssh server bind to configure. * * @param type The option type to set. This should be one of the * following: * * - SSH_BIND_OPTIONS_HOSTKEY: * Set the path to an ssh host key, regardless * of type. Only one key from per key type * (RSA, DSA, ECDSA) is allowed in an ssh_bind * at a time, and later calls to this function * with this option for the same key type will * override prior calls (const char *). * * - SSH_BIND_OPTIONS_BINDADDR: * Set the IP address to bind (const char *). * * - SSH_BIND_OPTIONS_BINDPORT: * Set the port to bind (unsigned int *). * * - SSH_BIND_OPTIONS_BINDPORT_STR: * Set the port to bind (const char *). * * - SSH_BIND_OPTIONS_LOG_VERBOSITY: * Set the session logging verbosity (int *). * The logging verbosity should have one of the * following values, which are listed in order * of increasing verbosity. Every log message * with verbosity less than or equal to the * logging verbosity will be shown. * - SSH_LOG_NOLOG: No logging * - SSH_LOG_WARNING: Only warnings * - SSH_LOG_PROTOCOL: High level protocol information * - SSH_LOG_PACKET: Lower level protocol infomations, packet level * - SSH_LOG_FUNCTIONS: Every function path * * - SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: * Set the session logging verbosity via a * string that will be converted to a numerical * value (e.g. "3") and interpreted according * to the values of * SSH_BIND_OPTIONS_LOG_VERBOSITY above (const * char *). * * - SSH_BIND_OPTIONS_DSAKEY: * Set the path to the ssh host dsa key, SSHv2 * only (const char *). * * - SSH_BIND_OPTIONS_RSAKEY: * Set the path to the ssh host rsa key, SSHv2 * only (const char *). * * - SSH_BIND_OPTIONS_ECDSAKEY: * Set the path to the ssh host ecdsa key, * SSHv2 only (const char *). * * - SSH_BIND_OPTIONS_BANNER: * Set the server banner sent to clients (const char *). * * - SSH_BIND_OPTIONS_IMPORT_KEY: * Set the Private Key for the server directly (ssh_key) * * - SSH_BIND_OPTIONS_CIPHERS_C_S: * Set the symmetric cipher client to server (const char *, * comma-separated list). * * - SSH_BIND_OPTIONS_CIPHERS_S_C: * Set the symmetric cipher server to client (const char *, * comma-separated list). * * - SSH_BIND_OPTIONS_KEY_EXCHANGE: * Set the key exchange method to be used (const char *, * comma-separated list). ex: * "ecdh-sha2-nistp256,diffie-hellman-group14-sha1" * * - SSH_BIND_OPTIONS_HMAC_C_S: * Set the Message Authentication Code algorithm client * to server (const char *, comma-separated list). * * - SSH_BIND_OPTIONS_HMAC_S_C: * Set the Message Authentication Code algorithm server * to client (const char *, comma-separated list). * * - SSH_BIND_OPTIONS_CONFIG_DIR: * Set the directory (const char *, format string) * to be used when the "%d" scape is used when providing * paths of configuration files to * ssh_bind_options_parse_config(). * * - SSH_BIND_OPTIONS_PROCESS_CONFIG * Set it to false to disable automatic processing of * system-wide configuration files. LibSSH automatically * uses these configuration files otherwise. This * option will only have effect if set before any call * to ssh_bind_options_parse_config() (bool). * * - SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES: * Set the public key algorithm accepted by the server * (const char *, comma-separated list). * * - SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS: * Set the list of allowed hostkey signatures algorithms * to offer to the client, ordered by preference. This * list is used as a filter when creating the list of * algorithms to offer to the client: first the list of * possible algorithms is created from the list of keys * set and then filtered against this list. * (const char *, comma-separated list). * * @param value The value to set. This is a generic pointer and the * datatype which should be used is described at the * corresponding value of type above. * * @return 0 on success, < 0 on error, invalid option, or parameter. */ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type, const void *value) { char *p, *q; const char *v; int i, rc; if (sshbind == NULL) { return -1; } switch (type) { case SSH_BIND_OPTIONS_HOSTKEY: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { int key_type; ssh_key key; ssh_key *bind_key_loc = NULL; char **bind_key_path_loc; rc = ssh_pki_import_privkey_file(value, NULL, NULL, NULL, &key); if (rc != SSH_OK) { return -1; } key_type = ssh_key_type(key); switch (key_type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_DSA bind_key_loc = &sshbind->dsa; bind_key_path_loc = &sshbind->dsakey; #else ssh_set_error(sshbind, SSH_FATAL, "DSS key used and libssh compiled " "without DSA support"); #endif break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_ECC bind_key_loc = &sshbind->ecdsa; bind_key_path_loc = &sshbind->ecdsakey; #else ssh_set_error(sshbind, SSH_FATAL, "ECDSA key used and libssh compiled " "without ECDSA support"); #endif break; case SSH_KEYTYPE_RSA: bind_key_loc = &sshbind->rsa; bind_key_path_loc = &sshbind->rsakey; break; case SSH_KEYTYPE_ED25519: bind_key_loc = &sshbind->ed25519; bind_key_path_loc = &sshbind->ed25519key; break; default: ssh_set_error(sshbind, SSH_FATAL, "Unsupported key type %d", key_type); } if (bind_key_loc == NULL) { ssh_key_free(key); return -1; } /* Set the location of the key on disk even though we don't need it in case some other function wants it */ rc = ssh_bind_set_key(sshbind, bind_key_path_loc, value); if (rc < 0) { ssh_key_free(key); return -1; } ssh_key_free(*bind_key_loc); *bind_key_loc = key; } break; case SSH_BIND_OPTIONS_IMPORT_KEY: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { int key_type; ssh_key *bind_key_loc = NULL; ssh_key key = (ssh_key)value; key_type = ssh_key_type(key); switch (key_type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_DSA bind_key_loc = &sshbind->dsa; #else ssh_set_error(sshbind, SSH_FATAL, "DSA key used and libssh compiled " "without DSA support"); #endif break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_ECC bind_key_loc = &sshbind->ecdsa; #else ssh_set_error(sshbind, SSH_FATAL, "ECDSA key used and libssh compiled " "without ECDSA support"); #endif break; case SSH_KEYTYPE_RSA: bind_key_loc = &sshbind->rsa; break; case SSH_KEYTYPE_ED25519: bind_key_loc = &sshbind->ed25519; break; default: ssh_set_error(sshbind, SSH_FATAL, "Unsupported key type %d", key_type); } if (bind_key_loc == NULL) return -1; ssh_key_free(*bind_key_loc); *bind_key_loc = key; } break; case SSH_BIND_OPTIONS_BINDADDR: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { SAFE_FREE(sshbind->bindaddr); sshbind->bindaddr = strdup(value); if (sshbind->bindaddr == NULL) { ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_BINDPORT: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { int *x = (int *) value; sshbind->bindport = *x & 0xffffU; } break; case SSH_BIND_OPTIONS_BINDPORT_STR: if (value == NULL) { sshbind->bindport = 22 & 0xffffU; } else { q = strdup(value); if (q == NULL) { ssh_set_error_oom(sshbind); return -1; } i = strtol(q, &p, 10); if (q == p) { SAFE_FREE(q); } SAFE_FREE(q); sshbind->bindport = i & 0xffffU; } break; case SSH_BIND_OPTIONS_LOG_VERBOSITY: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { int *x = (int *) value; ssh_set_log_level(*x & 0xffffU); } break; case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR: if (value == NULL) { ssh_set_log_level(0); } else { q = strdup(value); if (q == NULL) { ssh_set_error_oom(sshbind); return -1; } i = strtol(q, &p, 10); if (q == p) { SAFE_FREE(q); } SAFE_FREE(q); ssh_set_log_level(i & 0xffffU); } break; case SSH_BIND_OPTIONS_DSAKEY: rc = ssh_bind_set_key(sshbind, &sshbind->dsakey, value); if (rc < 0) { return -1; } break; case SSH_BIND_OPTIONS_RSAKEY: rc = ssh_bind_set_key(sshbind, &sshbind->rsakey, value); if (rc < 0) { return -1; } break; case SSH_BIND_OPTIONS_ECDSAKEY: rc = ssh_bind_set_key(sshbind, &sshbind->ecdsakey, value); if (rc < 0) { return -1; } break; case SSH_BIND_OPTIONS_BANNER: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { SAFE_FREE(sshbind->banner); sshbind->banner = strdup(value); if (sshbind->banner == NULL) { ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_CIPHERS_C_S: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { if (ssh_bind_set_algo(sshbind, SSH_CRYPT_C_S, v) < 0) return -1; } break; case SSH_BIND_OPTIONS_CIPHERS_S_C: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { if (ssh_bind_set_algo(sshbind, SSH_CRYPT_S_C, v) < 0) return -1; } break; case SSH_BIND_OPTIONS_KEY_EXCHANGE: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { rc = ssh_bind_set_algo(sshbind, SSH_KEX, v); if (rc < 0) { return -1; } } break; case SSH_BIND_OPTIONS_HMAC_C_S: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { if (ssh_bind_set_algo(sshbind, SSH_MAC_C_S, v) < 0) return -1; } break; case SSH_BIND_OPTIONS_HMAC_S_C: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { if (ssh_bind_set_algo(sshbind, SSH_MAC_S_C, v) < 0) return -1; } break; case SSH_BIND_OPTIONS_CONFIG_DIR: v = value; SAFE_FREE(sshbind->config_dir); if (v == NULL) { break; } else if (v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { sshbind->config_dir = ssh_path_expand_tilde(v); if (sshbind->config_dir == NULL) { ssh_set_error_oom(sshbind); return -1; } } break; case SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { if (ssh_fips_mode()) { p = ssh_keep_fips_algos(SSH_HOSTKEYS, v); } else { p = ssh_keep_known_algos(SSH_HOSTKEYS, v); } if (p == NULL) { ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Setting method: no known public key algorithm (%s)", v); return -1; } SAFE_FREE(sshbind->pubkey_accepted_key_types); sshbind->pubkey_accepted_key_types = p; } break; case SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS: v = value; if (v == NULL || v[0] == '\0') { ssh_set_error_invalid(sshbind); return -1; } else { rc = ssh_bind_set_algo(sshbind, SSH_HOSTKEYS, v); if (rc < 0) { return -1; } } break; case SSH_BIND_OPTIONS_PROCESS_CONFIG: if (value == NULL) { ssh_set_error_invalid(sshbind); return -1; } else { bool *x = (bool *)value; sshbind->config_processed = !(*x); } break; default: ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); return -1; break; } return 0; } static char *ssh_bind_options_expand_escape(ssh_bind sshbind, const char *s) { char buf[MAX_BUF_SIZE]; char *r, *x = NULL; const char *p; size_t i, l; r = ssh_path_expand_tilde(s); if (r == NULL) { ssh_set_error_oom(sshbind); return NULL; } if (strlen(r) > MAX_BUF_SIZE) { ssh_set_error(sshbind, SSH_FATAL, "string to expand too long"); free(r); return NULL; } p = r; buf[0] = '\0'; for (i = 0; *p != '\0'; p++) { if (*p != '%') { buf[i] = *p; i++; if (i >= MAX_BUF_SIZE) { free(r); return NULL; } buf[i] = '\0'; continue; } p++; if (*p == '\0') { break; } switch (*p) { case 'd': x = strdup(sshbind->config_dir); break; default: ssh_set_error(sshbind, SSH_FATAL, "Wrong escape sequence detected"); free(r); return NULL; } if (x == NULL) { ssh_set_error_oom(sshbind); free(r); return NULL; } i += strlen(x); if (i >= MAX_BUF_SIZE) { ssh_set_error(sshbind, SSH_FATAL, "String too long"); free(x); free(r); return NULL; } l = strlen(buf); strncpy(buf + l, x, sizeof(buf) - l - 1); buf[i] = '\0'; SAFE_FREE(x); } free(r); return strdup(buf); } /** * @brief Parse a ssh bind options configuration file. * * This parses the options file and set them to the ssh_bind handle provided. If * an option was previously set, it is overridden. If the global configuration * hasn't been processed yet, it is processed prior to the provided file. * * @param sshbind SSH bind handle * * @param filename The options file to use; if NULL only the global * configuration is parsed and applied (if it haven't been * processed before). * * @return 0 on success, < 0 on error. */ int ssh_bind_options_parse_config(ssh_bind sshbind, const char *filename) { int rc = 0; char *expanded_filename; if (sshbind == NULL) { return -1; } /* If the global default configuration hasn't been processed yet, process it * before the provided configuration. */ if (!(sshbind->config_processed)) { rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG); if (rc != 0) { return rc; } sshbind->config_processed = true; } if (filename != NULL) { expanded_filename = ssh_bind_options_expand_escape(sshbind, filename); if (expanded_filename == NULL) { return -1; } /* Apply the user provided configuration */ rc = ssh_bind_config_parse_file(sshbind, expanded_filename); free(expanded_filename); } return rc; } #endif /** @} */ ================================================ FILE: src/libssh/src/packet.c ================================================ /* * packet.c - packet building functions * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/packet.h" #include "libssh/socket.h" #include "libssh/channels.h" #include "libssh/misc.h" #include "libssh/session.h" #include "libssh/messages.h" #include "libssh/pcap.h" #include "libssh/kex.h" #include "libssh/auth.h" #include "libssh/gssapi.h" #include "libssh/bytearray.h" #include "libssh/dh.h" static ssh_packet_callback default_packet_handlers[]= { ssh_packet_disconnect_callback, // SSH2_MSG_DISCONNECT 1 ssh_packet_ignore_callback, // SSH2_MSG_IGNORE 2 ssh_packet_unimplemented, // SSH2_MSG_UNIMPLEMENTED 3 ssh_packet_ignore_callback, // SSH2_MSG_DEBUG 4 #if WITH_SERVER ssh_packet_service_request, // SSH2_MSG_SERVICE_REQUEST 5 #else NULL, #endif ssh_packet_service_accept, // SSH2_MSG_SERVICE_ACCEPT 6 ssh_packet_ext_info, // SSH2_MSG_EXT_INFO 7 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 8-19 ssh_packet_kexinit, // SSH2_MSG_KEXINIT 20 ssh_packet_newkeys, // SSH2_MSG_NEWKEYS 21 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 22-29 #if WITH_SERVER ssh_packet_kexdh_init, // SSH2_MSG_KEXDH_INIT 30 // SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 #else NULL, #endif NULL, // SSH2_MSG_KEXDH_REPLY 31 // SSH2_MSG_KEX_DH_GEX_GROUP 31 NULL, // SSH2_MSG_KEX_DH_GEX_INIT 32 NULL, // SSH2_MSG_KEX_DH_GEX_REPLY 33 NULL, // SSH2_MSG_KEX_DH_GEX_REQUEST 34 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 35-49 #if WITH_SERVER ssh_packet_userauth_request, // SSH2_MSG_USERAUTH_REQUEST 50 #else NULL, #endif ssh_packet_userauth_failure, // SSH2_MSG_USERAUTH_FAILURE 51 ssh_packet_userauth_success, // SSH2_MSG_USERAUTH_SUCCESS 52 ssh_packet_userauth_banner, // SSH2_MSG_USERAUTH_BANNER 53 NULL,NULL,NULL,NULL,NULL,NULL, // 54-59 ssh_packet_userauth_pk_ok, // SSH2_MSG_USERAUTH_PK_OK 60 // SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 // SSH2_MSG_USERAUTH_INFO_REQUEST 60 // SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 ssh_packet_userauth_info_response, // SSH2_MSG_USERAUTH_INFO_RESPONSE 61 // SSH2_MSG_USERAUTH_GSSAPI_TOKEN 61 NULL, // 62 NULL, // SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63 NULL, // SSH2_MSG_USERAUTH_GSSAPI_ERROR 64 NULL, // SSH2_MSG_USERAUTH_GSSAPI_ERRTOK 65 #if defined(WITH_GSSAPI) && defined(WITH_SERVER) ssh_packet_userauth_gssapi_mic, // SSH2_MSG_USERAUTH_GSSAPI_MIC 66 #else /* WITH_GSSAPI && WITH_SERVER */ NULL, #endif /* WITH_GSSAPI && WITH_SERVER */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 67-79 #ifdef WITH_SERVER ssh_packet_global_request, // SSH2_MSG_GLOBAL_REQUEST 80 #else /* WITH_SERVER */ NULL, #endif /* WITH_SERVER */ ssh_request_success, // SSH2_MSG_REQUEST_SUCCESS 81 ssh_request_denied, // SSH2_MSG_REQUEST_FAILURE 82 NULL, NULL, NULL, NULL, NULL, NULL, NULL,// 83-89 ssh_packet_channel_open, // SSH2_MSG_CHANNEL_OPEN 90 ssh_packet_channel_open_conf, // SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 ssh_packet_channel_open_fail, // SSH2_MSG_CHANNEL_OPEN_FAILURE 92 channel_rcv_change_window, // SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 channel_rcv_data, // SSH2_MSG_CHANNEL_DATA 94 channel_rcv_data, // SSH2_MSG_CHANNEL_EXTENDED_DATA 95 channel_rcv_eof, // SSH2_MSG_CHANNEL_EOF 96 channel_rcv_close, // SSH2_MSG_CHANNEL_CLOSE 97 channel_rcv_request, // SSH2_MSG_CHANNEL_REQUEST 98 ssh_packet_channel_success, // SSH2_MSG_CHANNEL_SUCCESS 99 ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100 }; /** @internal * @brief check if the received packet is allowed for the current session state * @param session current ssh_session * @returns SSH_PACKET_ALLOWED if the packet is allowed; SSH_PACKET_DENIED * if the packet arrived in wrong state; SSH_PACKET_UNKNOWN if the packet type * is unknown */ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session session) { enum ssh_packet_filter_result_e rc; #ifdef DEBUG_PACKET SSH_LOG(SSH_LOG_PACKET, "Filtering packet type %d", session->in_packet.type); #endif switch(session->in_packet.type) { case SSH2_MSG_DISCONNECT: // 1 /* * States required: * - None * * Transitions: * - session->socket->state = SSH_SOCKET_CLOSED * - session->session_state = SSH_SESSION_STATE_ERROR * */ /* Always allowed */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_IGNORE: // 2 /* * States required: * - None * * Transitions: * - None * */ /* Always allowed */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_UNIMPLEMENTED: // 3 /* * States required: * - None * * Transitions: * - None * */ /* Always allowed */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_DEBUG: // 4 /* * States required: * - None * * Transitions: * - None * */ /* Always allowed */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_SERVICE_REQUEST: // 5 /* Server only */ /* * States required: * - session->session_state == SSH_SESSION_STATE_AUTHENTICATING * or session->session_state == SSH_SESSION_STATE_AUTHENTICATED * - session->dh_handshake_state == DH_STATE_FINISHED * * Transitions: * - None * */ /* If this is a client, reject the message */ if (session->client) { rc = SSH_PACKET_DENIED; break; } if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) && (session->session_state != SSH_SESSION_STATE_AUTHENTICATED)) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_SERVICE_ACCEPT: // 6 /* * States required: * - session->session_state == SSH_SESSION_STATE_AUTHENTICATING * or session->session_state == SSH_SESSION_STATE_AUTHENTICATED * - session->dh_handshake_state == DH_STATE_FINISHED * - session->auth.service_state == SSH_AUTH_SERVICE_SENT * * Transitions: * - auth.service_state = SSH_AUTH_SERVICE_ACCEPTED * */ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) && (session->session_state != SSH_SESSION_STATE_AUTHENTICATED)) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } /* TODO check if only auth service can be requested */ if (session->auth.service_state != SSH_AUTH_SERVICE_SENT) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_EXT_INFO: // 7 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * or session->session_state == SSH_SESSION_STATE_AUTHENTICATED * (re-exchange) * - dh_handshake_state == DH_STATE_FINISHED * * Transitions: * - None * */ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) && (session->session_state != SSH_SESSION_STATE_AUTHENTICATED)) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEXINIT: // 20 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * or session_state == SSH_SESSION_STATE_INITIAL_KEX * - dh_handshake_state == DH_STATE_INIT * or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange) * or dh_handshake_state == DH_STATE_FINISHED (re-exchange) * * Transitions: * - session->dh_handshake_state = DH_STATE_INIT * - session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED * * On server: * - session->session_state = SSH_SESSION_STATE_DH * */ if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATED) && (session->session_state != SSH_SESSION_STATE_INITIAL_KEX)) { rc = SSH_PACKET_DENIED; break; } if ((session->dh_handshake_state != DH_STATE_INIT) && (session->dh_handshake_state != DH_STATE_INIT_SENT) && (session->dh_handshake_state != DH_STATE_FINISHED)) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_NEWKEYS: // 21 /* * States required: * - session_state == SSH_SESSION_STATE_DH * - dh_handshake_state == DH_STATE_NEWKEYS_SENT * * Transitions: * - session->dh_handshake_state = DH_STATE_FINISHED * - session->session_state = SSH_SESSION_STATE_AUTHENTICATING * if session->flags & SSH_SESSION_FLAG_AUTHENTICATED * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED * */ /* If DH has not been started, reject message */ if (session->session_state != SSH_SESSION_STATE_DH) { rc = SSH_PACKET_DENIED; break; } /* Only allowed if dh_handshake_state is in NEWKEYS_SENT state */ if (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEXDH_INIT: // 30 // SSH2_MSG_KEX_ECDH_INIT: // 30 // SSH2_MSG_ECMQV_INIT: // 30 // SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30 /* Server only */ /* * States required: * - session_state == SSH_SESSION_STATE_DH * - dh_handshake_state == DH_STATE_INIT * * Transitions: * - session->dh_handshake_state = DH_STATE_INIT_SENT * then calls dh_handshake_server which triggers: * - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT * */ if (session->session_state != SSH_SESSION_STATE_DH) { rc = SSH_PACKET_DENIED; break; } /* Only allowed if dh_handshake_state is in initial state */ if (session->dh_handshake_state != DH_STATE_INIT) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEXDH_REPLY: // 31 // SSH2_MSG_KEX_ECDH_REPLY: // 31 // SSH2_MSG_ECMQV_REPLY: // 31 // SSH2_MSG_KEX_DH_GEX_GROUP: // 31 /* * States required: * - session_state == SSH_SESSION_STATE_DH * - dh_handshake_state == DH_STATE_INIT_SENT * or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex) * * Transitions: * - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT * */ if (session->session_state != SSH_SESSION_STATE_DH) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_INIT_SENT && session->dh_handshake_state != DH_STATE_REQUEST_SENT) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEX_DH_GEX_INIT: // 32 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEX_DH_GEX_REPLY: // 33 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_KEX_DH_GEX_REQUEST: // 34 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_REQUEST: // 50 /* Server only */ /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - dh_hanshake_state == DH_STATE_FINISHED * * Transitions: * - if authentication was successful: * - session_state = SSH_SESSION_STATE_AUTHENTICATED * */ /* If this is a client, reject the message */ if (session->client) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_FAILURE: // 51 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - dh_hanshake_state == DH_STATE_FINISHED * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT * or session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT * or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT * or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT * or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT * * Transitions: * - if unpacking failed: * - session->auth.state = SSH_AUTH_ERROR * - if failure was partial: * - session->auth.state = SSH_AUTH_PARTIAL * - else: * - session->auth.state = SSH_AUTH_STATE_FAILED * */ /* If this is a server, reject the message */ if (session->server) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_SUCCESS: // 52 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - dh_hanshake_state == DH_STATE_FINISHED * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT * or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT * or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT * or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT * or session->auth.state == SSH_AUTH_STATE_AUTH_NONE_SENT * * Transitions: * - session->auth.state = SSH_AUTH_STATE_SUCCESS * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED * - session->flags |= SSH_SESSION_FLAG_AUTHENTICATED * - sessions->auth.current_method = SSH_AUTH_METHOD_UNKNOWN * */ /* If this is a server, reject the message */ if (session->server) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) && (session->auth.state != SSH_AUTH_STATE_PUBKEY_AUTH_SENT) && (session->auth.state != SSH_AUTH_STATE_PASSWORD_AUTH_SENT) && (session->auth.state != SSH_AUTH_STATE_GSSAPI_MIC_SENT) && (session->auth.state != SSH_AUTH_STATE_AUTH_NONE_SENT)) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_BANNER: // 53 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_PK_OK: // 60 // SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // 60 // SSH2_MSG_USERAUTH_INFO_REQUEST: // 60 // SSH2_MSG_USERAUTH_GSSAPI_RESPONSE: // 60 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT * or * session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT * or * session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT * * Transitions: * Depending on the current state, the message is treated * differently: * - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT * - session->auth.state = SSH_AUTH_STATE_INFO * - session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT * - session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN * - session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT * - session->auth.state = SSH_AUTH_STATE_PK_OK * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) && (session->auth.state != SSH_AUTH_STATE_PUBKEY_OFFER_SENT) && (session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT)) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_INFO_RESPONSE: // 61 // SSH2_MSG_USERAUTH_GSSAPI_TOKEN: // 61 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - session_state->auth.state == SSH_SESSION_STATE_GSSAPI_TOKEN * or * session_state->auth.state == SSH_SESSION_STATE_INFO * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } if ((session->auth.state != SSH_AUTH_STATE_INFO) && (session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN)) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE: // 63 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_GSSAPI_ERROR: // 64 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_GSSAPI_ERRTOK: // 65 /* TODO Not filtered */ rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_USERAUTH_GSSAPI_MIC: // 66 /* Server only */ /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATING * - session->gssapi->state == SSH_GSSAPI_STATE_RCV_MIC * * Transitions: * Depending on the result of the verification, the states are * changed: * - SSH_AUTH_SUCCESS: * - session->session_state = SSH_SESSION_STATE_AUTHENTICATED * - session->flags != SSH_SESSION_FLAG_AUTHENTICATED * - SSH_AUTH_PARTIAL: * - None * - any other case: * - None * */ /* If this is a client, reject the message */ if (session->client) { rc = SSH_PACKET_DENIED; break; } if (session->dh_handshake_state != DH_STATE_FINISHED) { rc = SSH_PACKET_DENIED; break; } if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_GLOBAL_REQUEST: // 80 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_REQUEST_SUCCESS: // 81 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: * - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_REQUEST_FAILURE: // 82 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: * - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_OPEN: // 90 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: // 91 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - channel->state = SSH_CHANNEL_STATE_OPEN * - channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_OPEN_FAILURE: // 92 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - channel->state = SSH_CHANNEL_STATE_OPEN_DENIED * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_WINDOW_ADJUST: // 93 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_DATA: // 94 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_EXTENDED_DATA: // 95 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_EOF: // 96 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - None * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_CLOSE: // 97 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - channel->state = SSH_CHANNEL_STATE_CLOSED * - channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_REQUEST: // 98 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * * Transitions: * - Depends on the request * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_SUCCESS: // 99 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: * - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; case SSH2_MSG_CHANNEL_FAILURE: // 100 /* * States required: * - session_state == SSH_SESSION_STATE_AUTHENTICATED * - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING * * Transitions: * - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED * */ if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { rc = SSH_PACKET_DENIED; break; } rc = SSH_PACKET_ALLOWED; break; default: /* Unknown message, do not filter */ rc = SSH_PACKET_UNKNOWN; goto end; } end: #ifdef DEBUG_PACKET if (rc == SSH_PACKET_DENIED) { SSH_LOG(SSH_LOG_PACKET, "REJECTED packet type %d: ", session->in_packet.type); } if (rc == SSH_PACKET_UNKNOWN) { SSH_LOG(SSH_LOG_PACKET, "UNKNOWN packet type %d", session->in_packet.type); } #endif return rc; } /* Returns current_crypto structure from the session. * During key exchange (or rekey), after one of the sides * sending NEWKEYS packet, this might return next_crypto for one * of the directions that is ahead to send already queued packets */ struct ssh_crypto_struct * ssh_packet_get_current_crypto(ssh_session session, enum ssh_crypto_direction_e direction) { struct ssh_crypto_struct *crypto = NULL; if (session == NULL) { return NULL; } if (session->current_crypto != NULL && session->current_crypto->used & direction) { crypto = session->current_crypto; } else if (session->next_crypto != NULL && session->next_crypto->used & direction) { crypto = session->next_crypto; } else { return NULL; } switch (direction) { case SSH_DIRECTION_IN: if (crypto->in_cipher != NULL) { return crypto; } break; case SSH_DIRECTION_OUT: if (crypto->out_cipher != NULL) { return crypto; } break; case SSH_DIRECTION_BOTH: if (crypto->in_cipher != NULL && crypto->out_cipher != NULL) { return crypto; } } return NULL; } #define MAX_PACKETS (1UL<<31) static bool ssh_packet_need_rekey(ssh_session session, const uint32_t payloadsize) { bool data_rekey_needed = false; struct ssh_crypto_struct *crypto = NULL; struct ssh_cipher_struct *out_cipher = NULL, *in_cipher = NULL; uint32_t next_blocks; /* We can safely rekey only in authenticated state */ if ((session->flags & SSH_SESSION_FLAG_AUTHENTICATED) == 0) { return false; } /* Do not rekey if the rekey/key-exchange is in progress */ if (session->dh_handshake_state != DH_STATE_FINISHED) { return false; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH); if (crypto == NULL) { return false; } out_cipher = crypto->out_cipher; in_cipher = crypto->in_cipher; /* Make sure we can send at least something for very small limits */ if ((out_cipher->packets == 0) && (in_cipher->packets == 0)) { return false; } /* Time based rekeying */ if (session->opts.rekey_time != 0 && ssh_timeout_elapsed(&session->last_rekey_time, session->opts.rekey_time)) { return true; } /* RFC4344, Section 3.1 Recommends rekeying after 2^31 packets in either * direction to avoid possible information leakage through the MAC tag */ if (out_cipher->packets > MAX_PACKETS || in_cipher->packets > MAX_PACKETS) { return true; } /* Data-based rekeying: * * For outgoing packets we can still delay them * * Incoming packets need to be processed anyway, but we can * signalize our intention to rekey */ next_blocks = payloadsize / out_cipher->blocksize; data_rekey_needed = (out_cipher->max_blocks != 0 && out_cipher->blocks + next_blocks > out_cipher->max_blocks) || (in_cipher->max_blocks != 0 && in_cipher->blocks + next_blocks > in_cipher->max_blocks); SSH_LOG(SSH_LOG_PACKET, "packet: [data_rekey_needed=%d, out_blocks=%" PRIu64 ", in_blocks=%" PRIu64, data_rekey_needed, out_cipher->blocks + next_blocks, in_cipher->blocks + next_blocks); return data_rekey_needed; } /* in nonblocking mode, socket_read will read as much as it can, and return */ /* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */ /* in blocking mode, it will read at least len bytes and will block until it's ok. */ /** @internal * @handles a data received event. It then calls the handlers for the different packet types * or and exception handler callback. * @param user pointer to current ssh_session * @param data pointer to the data received * @len length of data received. It might not be enough for a complete packet * @returns number of bytes read and processed. */ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) { ssh_session session = (ssh_session)user; uint32_t blocksize = 8; uint32_t lenfield_blocksize = 8; size_t current_macsize = 0; uint8_t *ptr = NULL; int to_be_read; int rc; uint8_t *cleartext_packet = NULL; uint8_t *packet_second_block = NULL; uint8_t *mac = NULL; size_t packet_remaining; uint32_t packet_len, compsize, payloadsize; uint8_t padding; size_t processed = 0; /* number of byte processed from the callback */ enum ssh_packet_filter_result_e filter_result; struct ssh_crypto_struct *crypto = NULL; bool etm = false; uint32_t etm_packet_offset = 0; bool ok; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto != NULL) { current_macsize = hmac_digest_len(crypto->in_hmac); blocksize = crypto->in_cipher->blocksize; lenfield_blocksize = crypto->in_cipher->lenfield_blocksize; etm = crypto->in_hmac_etm; } if (etm) { /* In EtM mode packet size is unencrypted. This means * we need to use this offset and set the block size * that is part of the encrypted part to 0. */ etm_packet_offset = sizeof(uint32_t); lenfield_blocksize = 0; } else if (lenfield_blocksize == 0) { lenfield_blocksize = blocksize; } if (data == NULL) { goto error; } if (session->session_state == SSH_SESSION_STATE_ERROR) { goto error; } #ifdef DEBUG_PACKET SSH_LOG(SSH_LOG_PACKET, "rcv packet cb (len=%zu, state=%s)", receivedlen, session->packet_state == PACKET_STATE_INIT ? "INIT" : session->packet_state == PACKET_STATE_SIZEREAD ? "SIZE_READ" : session->packet_state == PACKET_STATE_PROCESSING ? "PROCESSING" : "unknown"); #endif switch(session->packet_state) { case PACKET_STATE_INIT: if (receivedlen < lenfield_blocksize + etm_packet_offset) { /* * We didn't receive enough data to read either at least one * block size or the unencrypted length in EtM mode. */ #ifdef DEBUG_PACKET SSH_LOG(SSH_LOG_PACKET, "Waiting for more data (%zu < %u)", receivedlen, lenfield_blocksize); #endif return 0; } session->in_packet = (struct packet_struct) { .type = 0, }; if (session->in_buffer) { rc = ssh_buffer_reinit(session->in_buffer); if (rc < 0) { goto error; } } else { session->in_buffer = ssh_buffer_new(); if (session->in_buffer == NULL) { goto error; } } if (!etm) { ptr = ssh_buffer_allocate(session->in_buffer, lenfield_blocksize); if (ptr == NULL) { goto error; } packet_len = ssh_packet_decrypt_len(session, ptr, (uint8_t *)data); to_be_read = packet_len - lenfield_blocksize + sizeof(uint32_t); } else { /* Length is unencrypted in case of Encrypt-then-MAC */ packet_len = PULL_BE_U32(data, 0); to_be_read = packet_len - etm_packet_offset; } processed += lenfield_blocksize + etm_packet_offset; if (packet_len > MAX_PACKET_LEN) { ssh_set_error(session, SSH_FATAL, "read_packet(): Packet len too high(%u %.4x)", packet_len, packet_len); goto error; } if (to_be_read < 0) { /* remote sshd sends invalid sizes? */ ssh_set_error(session, SSH_FATAL, "Given numbers of bytes left to be read < 0 (%d)!", to_be_read); goto error; } session->in_packet.len = packet_len; session->packet_state = PACKET_STATE_SIZEREAD; FALL_THROUGH; case PACKET_STATE_SIZEREAD: packet_len = session->in_packet.len; processed = lenfield_blocksize + etm_packet_offset; to_be_read = packet_len + sizeof(uint32_t) + current_macsize; /* if to_be_read is zero, the whole packet was blocksize bytes. */ if (to_be_read != 0) { if (receivedlen < (unsigned int)to_be_read) { /* give up, not enough data in buffer */ SSH_LOG(SSH_LOG_PACKET, "packet: partial packet (read len) " "[len=%d, receivedlen=%d, to_be_read=%d]", packet_len, (int)receivedlen, to_be_read); return 0; } packet_second_block = (uint8_t*)data + lenfield_blocksize + etm_packet_offset; processed = to_be_read - current_macsize; } /* remaining encrypted bytes from the packet, MAC not included */ packet_remaining = packet_len - (lenfield_blocksize - sizeof(uint32_t) + etm_packet_offset); cleartext_packet = ssh_buffer_allocate(session->in_buffer, packet_remaining); if (cleartext_packet == NULL) { goto error; } if (packet_second_block != NULL) { if (crypto != NULL) { mac = packet_second_block + packet_remaining; if (etm) { rc = ssh_packet_hmac_verify(session, data, processed, mac, crypto->in_hmac); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "HMAC error"); goto error; } } /* * Decrypt the packet. In case of EtM mode, the length is already * known as it's unencrypted. In the other case, lenfield_blocksize bytes * already have been decrypted. */ if (packet_remaining > 0) { rc = ssh_packet_decrypt(session, cleartext_packet, (uint8_t *)data, lenfield_blocksize + etm_packet_offset, processed - (lenfield_blocksize + etm_packet_offset)); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Decryption error"); goto error; } } if (!etm) { rc = ssh_packet_hmac_verify(session, ssh_buffer_get(session->in_buffer), ssh_buffer_get_len(session->in_buffer), mac, crypto->in_hmac); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "HMAC error"); goto error; } } processed += current_macsize; } else { memcpy(cleartext_packet, packet_second_block, packet_remaining); } } #ifdef WITH_PCAP if (session->pcap_ctx != NULL) { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_IN, ssh_buffer_get(session->in_buffer), ssh_buffer_get_len(session->in_buffer), ssh_buffer_get_len(session->in_buffer)); } #endif if (!etm) { /* skip the size field which has been processed before */ ssh_buffer_pass_bytes(session->in_buffer, sizeof(uint32_t)); } rc = ssh_buffer_get_u8(session->in_buffer, &padding); if (rc == 0) { ssh_set_error(session, SSH_FATAL, "Packet too short to read padding"); goto error; } if (padding > ssh_buffer_get_len(session->in_buffer)) { ssh_set_error(session, SSH_FATAL, "Invalid padding: %d (%d left)", padding, ssh_buffer_get_len(session->in_buffer)); goto error; } ssh_buffer_pass_bytes_end(session->in_buffer, padding); compsize = ssh_buffer_get_len(session->in_buffer); #ifdef WITH_ZLIB if (crypto && crypto->do_compress_in && ssh_buffer_get_len(session->in_buffer) > 0) { rc = decompress_buffer(session, session->in_buffer,MAX_PACKET_LEN); if (rc < 0) { goto error; } } #endif /* WITH_ZLIB */ payloadsize = ssh_buffer_get_len(session->in_buffer); session->recv_seq++; if (crypto != NULL) { struct ssh_cipher_struct *cipher = NULL; cipher = crypto->in_cipher; cipher->packets++; cipher->blocks += payloadsize / cipher->blocksize; } if (session->raw_counter != NULL) { session->raw_counter->in_bytes += payloadsize; session->raw_counter->in_packets++; } /* * We don't want to rewrite a new packet while still executing the * packet callbacks */ session->packet_state = PACKET_STATE_PROCESSING; ssh_packet_parse_type(session); SSH_LOG(SSH_LOG_PACKET, "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]", session->in_packet.type, packet_len, padding, compsize, payloadsize); /* Check if the packet is expected */ filter_result = ssh_packet_incoming_filter(session); switch(filter_result) { case SSH_PACKET_ALLOWED: /* Execute callbacks */ ssh_packet_process(session, session->in_packet.type); break; case SSH_PACKET_DENIED: ssh_set_error(session, SSH_FATAL, "Packet filter: rejected packet (type %d)", session->in_packet.type); goto error; case SSH_PACKET_UNKNOWN: ssh_packet_send_unimplemented(session, session->recv_seq - 1); break; } session->packet_state = PACKET_STATE_INIT; if (processed < receivedlen) { /* Handle a potential packet left in socket buffer */ SSH_LOG(SSH_LOG_PACKET, "Processing %" PRIdS " bytes left in socket buffer", receivedlen-processed); ptr = ((uint8_t*)data) + processed; rc = ssh_packet_socket_callback(ptr, receivedlen - processed,user); processed += rc; } ok = ssh_packet_need_rekey(session, 0); if (ok) { SSH_LOG(SSH_LOG_PACKET, "Incoming packet triggered rekey"); rc = ssh_send_rekex(session); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Rekey failed: rc = %d", rc); return rc; } } return processed; case PACKET_STATE_PROCESSING: SSH_LOG(SSH_LOG_PACKET, "Nested packet processing. Delaying."); return 0; } ssh_set_error(session, SSH_FATAL, "Invalid state into packet_read2(): %d", session->packet_state); error: session->session_state= SSH_SESSION_STATE_ERROR; SSH_LOG(SSH_LOG_PACKET,"Packet: processed %" PRIdS " bytes", processed); return processed; } static void ssh_packet_socket_controlflow_callback(int code, void *userdata) { ssh_session session = userdata; struct ssh_iterator *it; ssh_channel channel; if (code == SSH_SOCKET_FLOW_WRITEWONTBLOCK) { SSH_LOG(SSH_LOG_TRACE, "sending channel_write_wontblock callback"); /* the out pipe is empty so we can forward this to channels */ it = ssh_list_get_iterator(session->channels); while (it != NULL) { channel = ssh_iterator_value(ssh_channel, it); ssh_callbacks_execute_list(channel->callbacks, ssh_channel_callbacks, channel_write_wontblock_function, session, channel, channel->remote_window); it = it->next; } } } void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){ session->socket_callbacks.data=ssh_packet_socket_callback; session->socket_callbacks.connected=NULL; session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback; session->socket_callbacks.userdata=session; ssh_socket_set_callbacks(s,&session->socket_callbacks); } /** @internal * @brief sets the callbacks for the packet layer */ void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ if(session->packet_callbacks == NULL){ session->packet_callbacks = ssh_list_new(); } if (session->packet_callbacks != NULL) { ssh_list_append(session->packet_callbacks, callbacks); } } /** @internal * @brief remove the callbacks from the packet layer */ void ssh_packet_remove_callbacks(ssh_session session, ssh_packet_callbacks callbacks){ struct ssh_iterator *it = NULL; it = ssh_list_find(session->packet_callbacks, callbacks); if (it != NULL) { ssh_list_remove(session->packet_callbacks, it); } } /** @internal * @brief sets the default packet handlers */ void ssh_packet_set_default_callbacks(ssh_session session){ session->default_packet_callbacks.start=1; session->default_packet_callbacks.n_callbacks=sizeof(default_packet_handlers)/sizeof(ssh_packet_callback); session->default_packet_callbacks.user=session; session->default_packet_callbacks.callbacks=default_packet_handlers; ssh_packet_set_callbacks(session, &session->default_packet_callbacks); } /** @internal * @brief dispatch the call of packet handlers callbacks for a received packet * @param type type of packet */ void ssh_packet_process(ssh_session session, uint8_t type) { struct ssh_iterator *i = NULL; int rc = SSH_PACKET_NOT_USED; ssh_packet_callbacks cb; SSH_LOG(SSH_LOG_PACKET, "Dispatching handler for packet type %d", type); if (session->packet_callbacks == NULL) { SSH_LOG(SSH_LOG_RARE, "Packet callback is not initialized !"); return; } i = ssh_list_get_iterator(session->packet_callbacks); while (i != NULL) { cb = ssh_iterator_value(ssh_packet_callbacks, i); i = i->next; if (!cb) { continue; } if (cb->start > type) { continue; } if (cb->start + cb->n_callbacks <= type) { continue; } if (cb->callbacks[type - cb->start] == NULL) { continue; } rc = cb->callbacks[type - cb->start](session, type, session->in_buffer, cb->user); if (rc == SSH_PACKET_USED) { break; } } if (rc == SSH_PACKET_NOT_USED) { SSH_LOG(SSH_LOG_RARE, "Couldn't do anything with packet type %d", type); rc = ssh_packet_send_unimplemented(session, session->recv_seq - 1); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_RARE, "Failed to send unimplemented: %s", ssh_get_error(session)); } } } /** @internal * @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet * @param session the SSH session * @param seqnum the sequence number of the unknown packet * @return SSH_ERROR on error, else SSH_OK */ int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum){ int rc; rc = ssh_buffer_pack(session->out_buffer, "bd", SSH2_MSG_UNIMPLEMENTED, seqnum); if (rc != SSH_OK) { ssh_set_error_oom(session); return SSH_ERROR; } rc = ssh_packet_send(session); return rc; } /** @internal * @brief handles a SSH_MSG_UNIMPLEMENTED packet */ SSH_PACKET_CALLBACK(ssh_packet_unimplemented){ uint32_t seq; int rc; (void)session; /* unused */ (void)type; (void)user; rc = ssh_buffer_unpack(packet, "d", &seq); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARNING, "Could not unpack SSH_MSG_UNIMPLEMENTED packet"); } SSH_LOG(SSH_LOG_RARE, "Received SSH_MSG_UNIMPLEMENTED (sequence number %d)",seq); return SSH_PACKET_USED; } /** @internal * @parse the "Type" header field of a packet and updates the session */ int ssh_packet_parse_type(struct ssh_session_struct *session) { session->in_packet = (struct packet_struct) { .type = 0, }; if (session->in_buffer == NULL) { return SSH_ERROR; } if (ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) { ssh_set_error(session, SSH_FATAL, "Packet too short to read type"); return SSH_ERROR; } session->in_packet.valid = 1; return SSH_OK; } /* * This function places the outgoing packet buffer into an outgoing * socket buffer */ static int ssh_packet_write(ssh_session session) { int rc = SSH_ERROR; rc=ssh_socket_write(session->socket, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); return rc; } static int packet_send2(ssh_session session) { unsigned int blocksize = 8; unsigned int lenfield_blocksize = 0; enum ssh_hmac_e hmac_type; uint32_t currentlen = ssh_buffer_get_len(session->out_buffer); struct ssh_crypto_struct *crypto = NULL; unsigned char *hmac = NULL; uint8_t padding_data[32] = { 0 }; uint8_t padding_size; uint32_t finallen, payloadsize, compsize; uint8_t header[5] = {0}; uint8_t type, *payload; int rc = SSH_ERROR; bool etm = false; int etm_packet_offset = 0; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); if (crypto) { blocksize = crypto->out_cipher->blocksize; lenfield_blocksize = crypto->out_cipher->lenfield_blocksize; hmac_type = crypto->out_hmac; etm = crypto->out_hmac_etm; } else { hmac_type = session->next_crypto->out_hmac; } payload = (uint8_t *)ssh_buffer_get(session->out_buffer); type = payload[0]; /* type is the first byte of the packet now */ payloadsize = currentlen; if (etm) { etm_packet_offset = sizeof(uint32_t); lenfield_blocksize = 0; } #ifdef WITH_ZLIB if (crypto != NULL && crypto->do_compress_out && ssh_buffer_get_len(session->out_buffer) > 0) { rc = compress_buffer(session,session->out_buffer); if (rc < 0) { goto error; } currentlen = ssh_buffer_get_len(session->out_buffer); } #endif /* WITH_ZLIB */ compsize = currentlen; /* compressed payload + packet len (4) + padding_size len (1) */ /* totallen - lenfield_blocksize - etm_packet_offset must be equal to 0 (mod blocksize) */ padding_size = (blocksize - ((blocksize - lenfield_blocksize - etm_packet_offset + currentlen + 5) % blocksize)); if (padding_size < 4) { padding_size += blocksize; } if (crypto != NULL) { int ok; ok = ssh_get_random(padding_data, padding_size, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); goto error; } } finallen = currentlen - etm_packet_offset + padding_size + 1; PUSH_BE_U32(header, 0, finallen); PUSH_BE_U8(header, 4, padding_size); rc = ssh_buffer_prepend_data(session->out_buffer, header, sizeof(header)); if (rc < 0) { goto error; } rc = ssh_buffer_add_data(session->out_buffer, padding_data, padding_size); if (rc < 0) { goto error; } #ifdef WITH_PCAP if (session->pcap_ctx != NULL) { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_OUT, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); } #endif hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer), ssh_buffer_get_len(session->out_buffer)); if (hmac != NULL) { rc = ssh_buffer_add_data(session->out_buffer, hmac, hmac_digest_len(hmac_type)); if (rc < 0) { goto error; } } rc = ssh_packet_write(session); if (rc == SSH_ERROR) { goto error; } session->send_seq++; if (crypto != NULL) { struct ssh_cipher_struct *cipher = NULL; cipher = crypto->out_cipher; cipher->packets++; cipher->blocks += payloadsize / cipher->blocksize; } if (session->raw_counter != NULL) { session->raw_counter->out_bytes += payloadsize; session->raw_counter->out_packets++; } SSH_LOG(SSH_LOG_PACKET, "packet: wrote [type=%u, len=%u, padding_size=%hhd, comp=%u, " "payload=%u]", type, finallen, padding_size, compsize, payloadsize); rc = ssh_buffer_reinit(session->out_buffer); if (rc < 0) { rc = SSH_ERROR; goto error; } /* We sent the NEWKEYS so any further packet needs to be encrypted * with the new keys. We can not switch both directions (need to decrypt * peer NEWKEYS) and we do not want to wait for the peer NEWKEYS * too, so we will switch only the OUT direction now. */ if (type == SSH2_MSG_NEWKEYS) { rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_OUT); } error: return rc; /* SSH_OK, AGAIN or ERROR */ } static bool ssh_packet_is_kex(unsigned char type) { return type >= SSH2_MSG_DISCONNECT && type <= SSH2_MSG_KEX_DH_GEX_REQUEST && type != SSH2_MSG_SERVICE_REQUEST && type != SSH2_MSG_SERVICE_ACCEPT && type != SSH2_MSG_IGNORE && type != SSH2_MSG_EXT_INFO; } static bool ssh_packet_in_rekey(ssh_session session) { /* We know we are rekeying if we are authenticated and the DH * status is not finished */ return (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) && (session->dh_handshake_state != DH_STATE_FINISHED); } int ssh_packet_send(ssh_session session) { uint32_t payloadsize; uint8_t type, *payload; bool need_rekey, in_rekey; int rc; payloadsize = ssh_buffer_get_len(session->out_buffer); if (payloadsize < 1) { return SSH_ERROR; } payload = (uint8_t *)ssh_buffer_get(session->out_buffer); type = payload[0]; /* type is the first byte of the packet now */ need_rekey = ssh_packet_need_rekey(session, payloadsize); in_rekey = ssh_packet_in_rekey(session); /* The rekey is triggered here. After that, only the key exchange * packets can be sent, until we send our NEWKEYS. */ if (need_rekey || (in_rekey && !ssh_packet_is_kex(type))) { if (need_rekey) { SSH_LOG(SSH_LOG_PACKET, "Outgoing packet triggered rekey"); } /* Queue the current packet -- we will send it after the rekey */ SSH_LOG(SSH_LOG_PACKET, "Queuing packet type %d", type); rc = ssh_list_append(session->out_queue, session->out_buffer); if (rc != SSH_OK) { return SSH_ERROR; } session->out_buffer = ssh_buffer_new(); if (session->out_buffer == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } if (need_rekey) { /* Send the KEXINIT packet instead. * This recursivelly calls the packet_send(), but it should * not get into rekeying again. * After that we need to handle the key exchange responses * up to the point where we can send the rest of the queue. */ return ssh_send_rekex(session); } return SSH_OK; } /* Send the packet normally */ rc = packet_send2(session); /* We finished the key exchange so we can try to send our queue now */ if (rc == SSH_OK && type == SSH2_MSG_NEWKEYS) { struct ssh_iterator *it; for (it = ssh_list_get_iterator(session->out_queue); it != NULL; it = ssh_list_get_iterator(session->out_queue)) { struct ssh_buffer_struct *next_buffer = NULL; /* Peek only -- do not remove from queue yet */ next_buffer = (struct ssh_buffer_struct *)it->data; payloadsize = ssh_buffer_get_len(next_buffer); if (ssh_packet_need_rekey(session, payloadsize)) { /* Sigh ... we still can not send this packet. Repeat. */ SSH_LOG(SSH_LOG_PACKET, "Queued packet triggered rekey"); return ssh_send_rekex(session); } SSH_BUFFER_FREE(session->out_buffer); session->out_buffer = ssh_list_pop_head(struct ssh_buffer_struct *, session->out_queue); payload = (uint8_t *)ssh_buffer_get(session->out_buffer); type = payload[0]; SSH_LOG(SSH_LOG_PACKET, "Dequeue packet type %d", type); rc = packet_send2(session); if (rc != SSH_OK) { return rc; } } } return rc; } static void ssh_init_rekey_state(struct ssh_session_struct *session, struct ssh_cipher_struct *cipher) { /* Reset the counters: should be NOOP */ cipher->packets = 0; cipher->blocks = 0; /* Default rekey limits for ciphers as specified in RFC4344, Section 3.2 */ if (cipher->blocksize >= 16) { /* For larger block size (L bits) use maximum of 2**(L/4) blocks */ cipher->max_blocks = (uint64_t)1 << (cipher->blocksize*2); } else { /* For smaller blocks use limit of 1 GB as recommended in RFC4253 */ cipher->max_blocks = ((uint64_t)1 << 30) / cipher->blocksize; } /* If we have limit provided by user, use the smaller one */ if (session->opts.rekey_data != 0) { cipher->max_blocks = MIN(cipher->max_blocks, session->opts.rekey_data / cipher->blocksize); } SSH_LOG(SSH_LOG_PROTOCOL, "Set rekey after %" PRIu64 " blocks", cipher->max_blocks); } /* * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and * current_crypto for our desired direction */ int ssh_packet_set_newkeys(ssh_session session, enum ssh_crypto_direction_e direction) { int rc; SSH_LOG(SSH_LOG_TRACE, "called, direction =%s%s", direction & SSH_DIRECTION_IN ? " IN " : "", direction & SSH_DIRECTION_OUT ? " OUT " : ""); if (session->next_crypto == NULL) { return SSH_ERROR; } session->next_crypto->used |= direction; if (session->current_crypto != NULL) { if (session->current_crypto->used & direction) { SSH_LOG(SSH_LOG_WARNING, "This direction isn't used anymore."); } /* Mark the current requested direction unused */ session->current_crypto->used &= ~direction; } /* Both sides switched: do the actual switch now */ if (session->next_crypto->used == SSH_DIRECTION_BOTH) { size_t digest_len; if (session->current_crypto != NULL) { crypto_free(session->current_crypto); session->current_crypto = NULL; } session->current_crypto = session->next_crypto; session->current_crypto->used = SSH_DIRECTION_BOTH; /* Initialize the next_crypto structure */ session->next_crypto = crypto_new(); if (session->next_crypto == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } digest_len = session->current_crypto->digest_len; session->next_crypto->session_id = malloc(digest_len); if (session->next_crypto->session_id == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } memcpy(session->next_crypto->session_id, session->current_crypto->session_id, digest_len); return SSH_OK; } /* Initialize common structures so the next context can be used in * either direction */ if (session->client) { /* The server has this part already done */ rc = ssh_make_sessionid(session); if (rc != SSH_OK) { return SSH_ERROR; } /* * Set the cryptographic functions for the next crypto * (it is needed for ssh_generate_session_keys for key lengths) */ rc = crypt_set_algorithms_client(session); if (rc < 0) { return SSH_ERROR; } } if (ssh_generate_session_keys(session) < 0) { return SSH_ERROR; } if (session->next_crypto->in_cipher == NULL || session->next_crypto->out_cipher == NULL) { return SSH_ERROR; } /* Initialize rekeying states */ ssh_init_rekey_state(session, session->next_crypto->out_cipher); ssh_init_rekey_state(session, session->next_crypto->in_cipher); if (session->opts.rekey_time != 0) { ssh_timestamp_init(&session->last_rekey_time); SSH_LOG(SSH_LOG_PROTOCOL, "Set rekey after %" PRIu32 " seconds", session->opts.rekey_time/1000); } /* Initialize the encryption and decryption keys in next_crypto */ rc = session->next_crypto->in_cipher->set_decrypt_key( session->next_crypto->in_cipher, session->next_crypto->decryptkey, session->next_crypto->decryptIV); if (rc < 0) { /* On error, make sure it is not used */ session->next_crypto->used = 0; return SSH_ERROR; } rc = session->next_crypto->out_cipher->set_encrypt_key( session->next_crypto->out_cipher, session->next_crypto->encryptkey, session->next_crypto->encryptIV); if (rc < 0) { /* On error, make sure it is not used */ session->next_crypto->used = 0; return SSH_ERROR; } return SSH_OK; } ================================================ FILE: src/libssh/src/packet_cb.c ================================================ /* * packet.c - packet building functions * * This file is part of the SSH Library * * Copyright (c) 2011 Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #ifdef HAVE_ARPA_INET_H #include #endif #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/crypto.h" #include "libssh/dh.h" #include "libssh/misc.h" #include "libssh/packet.h" #include "libssh/pki.h" #include "libssh/session.h" #include "libssh/socket.h" #include "libssh/ssh2.h" #include "libssh/curve25519.h" /** * @internal * * @brief Handle a SSH_DISCONNECT packet. */ SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback){ int rc; uint32_t code = 0; char *error = NULL; ssh_string error_s; (void)user; (void)type; rc = ssh_buffer_get_u32(packet, &code); if (rc != 0) { code = ntohl(code); } error_s = ssh_buffer_get_ssh_string(packet); if (error_s != NULL) { error = ssh_string_to_char(error_s); SSH_STRING_FREE(error_s); } SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT %d:%s", code, error != NULL ? error : "no error"); ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT: %d:%s", code, error != NULL ? error : "no error"); SAFE_FREE(error); ssh_socket_close(session->socket); session->alive = 0; session->session_state = SSH_SESSION_STATE_ERROR; /* TODO: handle a graceful disconnect */ return SSH_PACKET_USED; } /** * @internal * * @brief Handle a SSH_IGNORE and SSH_DEBUG packet. */ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback){ (void)session; /* unused */ (void)user; (void)type; (void)packet; SSH_LOG(SSH_LOG_PROTOCOL,"Received %s packet",type==SSH2_MSG_IGNORE ? "SSH_MSG_IGNORE" : "SSH_MSG_DEBUG"); /* TODO: handle a graceful disconnect */ return SSH_PACKET_USED; } SSH_PACKET_CALLBACK(ssh_packet_newkeys){ ssh_string sig_blob = NULL; ssh_signature sig = NULL; int rc; (void)packet; (void)user; (void)type; SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_NEWKEYS"); if (session->session_state != SSH_SESSION_STATE_DH || session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) { ssh_set_error(session, SSH_FATAL, "ssh_packet_newkeys called in wrong state : %d:%d", session->session_state,session->dh_handshake_state); goto error; } if(session->server){ /* server things are done in server.c */ session->dh_handshake_state=DH_STATE_FINISHED; } else { ssh_key server_key; /* client */ /* Verify the host's signature. FIXME do it sooner */ sig_blob = session->next_crypto->dh_server_signature; session->next_crypto->dh_server_signature = NULL; /* get the server public key */ server_key = ssh_dh_get_next_server_publickey(session); if (server_key == NULL) { goto error; } rc = ssh_pki_import_signature_blob(sig_blob, server_key, &sig); if (rc != SSH_OK) { goto error; } /* Check if signature from server matches user preferences */ if (session->opts.wanted_methods[SSH_HOSTKEYS]) { if (!ssh_match_group(session->opts.wanted_methods[SSH_HOSTKEYS], sig->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from server (%s) doesn't match user " "preference (%s)", sig->type_c, session->opts.wanted_methods[SSH_HOSTKEYS]); goto error; } } rc = ssh_pki_signature_verify(session, sig, server_key, session->next_crypto->secret_hash, session->next_crypto->digest_len); ssh_string_burn(sig_blob); SSH_STRING_FREE(sig_blob); ssh_signature_free(sig); if (rc == SSH_ERROR) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL,"Signature verified and valid"); /* When receiving this packet, we switch on the incomming crypto. */ rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); if (rc != SSH_OK) { goto error; } } session->dh_handshake_state = DH_STATE_FINISHED; session->ssh_connection_callback(session); return SSH_PACKET_USED; error: session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } /** * @internal * @brief handles a SSH_SERVICE_ACCEPT packet * */ SSH_PACKET_CALLBACK(ssh_packet_service_accept){ (void)packet; (void)type; (void)user; session->auth.service_state = SSH_AUTH_SERVICE_ACCEPTED; SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_SERVICE_ACCEPT"); return SSH_PACKET_USED; } /** * @internal * @brief handles a SSH2_MSG_EXT_INFO packet defined in RFC 8308 * */ SSH_PACKET_CALLBACK(ssh_packet_ext_info) { int rc; uint32_t nr_extensions = 0; uint32_t i; (void)type; (void)user; SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_EXT_INFO"); rc = ssh_buffer_get_u32(packet, &nr_extensions); if (rc == 0) { SSH_LOG(SSH_LOG_PACKET, "Failed to read number of extensions"); return SSH_PACKET_USED; } nr_extensions = ntohl(nr_extensions); if (nr_extensions > 128) { SSH_LOG(SSH_LOG_PACKET, "Invalid number of extensions"); return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_PACKET, "Follows %u extensions", nr_extensions); for (i = 0; i < nr_extensions; i++) { char *name = NULL; char *value = NULL; int cmp; rc = ssh_buffer_unpack(packet, "ss", &name, &value); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_PACKET, "Error reading extension name-value pair"); return SSH_PACKET_USED; } cmp = strcmp(name, "server-sig-algs"); if (cmp == 0) { /* TODO check for NULL bytes */ SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value); if (ssh_match_group(value, "rsa-sha2-512")) { session->extensions |= SSH_EXT_SIG_RSA_SHA512; } if (ssh_match_group(value, "rsa-sha2-256")) { session->extensions |= SSH_EXT_SIG_RSA_SHA256; } } free(name); free(value); } return SSH_PACKET_USED; } ================================================ FILE: src/libssh/src/packet_crypt.c ================================================ /* * crypt.c - blowfish-cbc code * * This file is part of the SSH Library * * Copyright (c) 2003 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #ifndef _WIN32 #include #include #endif #ifdef OPENSSL_CRYPTO #include #include #endif #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/wrapper.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/bytearray.h" /** @internal * @brief decrypt the packet length from a raw encrypted packet, and store the first decrypted * blocksize. * @returns native byte-ordered decrypted length of the upcoming packet */ uint32_t ssh_packet_decrypt_len(ssh_session session, uint8_t *destination, uint8_t *source) { struct ssh_crypto_struct *crypto = NULL; uint32_t decrypted; int rc; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto != NULL) { if (crypto->in_cipher->aead_decrypt_length != NULL) { rc = crypto->in_cipher->aead_decrypt_length( crypto->in_cipher, source, destination, crypto->in_cipher->lenfield_blocksize, session->recv_seq); } else { rc = ssh_packet_decrypt( session, destination, source, 0, crypto->in_cipher->blocksize); } if (rc < 0) { return 0; } } else { memcpy(destination, source, 8); } memcpy(&decrypted,destination,sizeof(decrypted)); return ntohl(decrypted); } /** @internal * @brief decrypts the content of an SSH packet. * @param[source] source packet, including the encrypted length field * @param[start] index in the packet that was not decrypted yet. * @param[encrypted_size] size of the encrypted data to be decrypted after start. */ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *source, size_t start, size_t encrypted_size) { struct ssh_crypto_struct *crypto = NULL; struct ssh_cipher_struct *cipher = NULL; if (encrypted_size <= 0) { return SSH_ERROR; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto == NULL) { return SSH_ERROR; } cipher = crypto->in_cipher; if (encrypted_size % cipher->blocksize != 0) { ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be used on multiple of " "blocksize (received %" PRIdS ")", encrypted_size); return SSH_ERROR; } if (cipher->aead_decrypt != NULL) { return cipher->aead_decrypt(cipher, source, destination, encrypted_size, session->recv_seq); } else { cipher->decrypt(cipher, source + start, destination, encrypted_size); } return 0; } unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) { struct ssh_crypto_struct *crypto = NULL; struct ssh_cipher_struct *cipher = NULL; HMACCTX ctx = NULL; char *out = NULL; int etm_packet_offset = 0; unsigned int finallen, blocksize; uint32_t seq, lenfield_blocksize; enum ssh_hmac_e type; bool etm; assert(len); crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); if (crypto == NULL) { return NULL; /* nothing to do here */ } blocksize = crypto->out_cipher->blocksize; lenfield_blocksize = crypto->out_cipher->lenfield_blocksize; type = crypto->out_hmac; etm = crypto->out_hmac_etm; if (etm) { etm_packet_offset = sizeof(uint32_t); } if ((len - lenfield_blocksize - etm_packet_offset) % blocksize != 0) { ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set" " on at least one blocksize (received %d)", len); return NULL; } out = calloc(1, len); if (out == NULL) { return NULL; } seq = ntohl(session->send_seq); cipher = crypto->out_cipher; if (cipher->aead_encrypt != NULL) { cipher->aead_encrypt(cipher, data, out, len, crypto->hmacbuf, session->send_seq); memcpy(data, out, len); } else { ctx = hmac_init(crypto->encryptMAC, hmac_key_len(type), type); if (ctx == NULL) { SAFE_FREE(out); return NULL; } if (!etm) { hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, data, len); hmac_final(ctx, crypto->hmacbuf, &finallen, type); } cipher->encrypt(cipher, (uint8_t*)data + etm_packet_offset, out, len - etm_packet_offset); memcpy((uint8_t*)data + etm_packet_offset, out, len - etm_packet_offset); if (etm) { PUSH_BE_U32(data, 0, len - etm_packet_offset); hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t)); hmac_update(ctx, data, len); hmac_final(ctx, crypto->hmacbuf, &finallen, type); } #ifdef DEBUG_CRYPTO ssh_log_hexdump("mac: ", data, len); if (finallen != hmac_digest_len(type)) { printf("Final len is %d\n", finallen); } ssh_log_hexdump("Packet hmac", crypto->hmacbuf, hmac_digest_len(type)); #endif } explicit_bzero(out, len); SAFE_FREE(out); return crypto->hmacbuf; } static int secure_memcmp(const void *s1, const void *s2, size_t n) { int rc = 0; const unsigned char *p1 = s1; const unsigned char *p2 = s2; for (; n > 0; --n) { rc |= *p1++ ^ *p2++; } return (rc != 0); } /** * @internal * * @brief Verify the hmac of a packet * * @param session The session to use. * @param data The pointer to the data to verify the hmac from. * @param len The length of the given data. * @param mac The mac to compare with the hmac. * * @return 0 if hmac and mac are equal, < 0 if not or an error * occurred. */ int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len, uint8_t *mac, enum ssh_hmac_e type) { struct ssh_crypto_struct *crypto = NULL; unsigned char hmacbuf[DIGEST_MAX_LEN] = {0}; HMACCTX ctx; unsigned int hmaclen; uint32_t seq; /* AEAD types have no mac checking */ if (type == SSH_HMAC_AEAD_POLY1305 || type == SSH_HMAC_AEAD_GCM) { return SSH_OK; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto == NULL) { return SSH_ERROR; } ctx = hmac_init(crypto->decryptMAC, hmac_key_len(type), type); if (ctx == NULL) { return -1; } seq = htonl(session->recv_seq); hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t)); hmac_update(ctx, data, len); hmac_final(ctx, hmacbuf, &hmaclen, type); #ifdef DEBUG_CRYPTO ssh_log_hexdump("received mac",mac,hmaclen); ssh_log_hexdump("Computed mac",hmacbuf,hmaclen); ssh_log_hexdump("seq",(unsigned char *)&seq,sizeof(uint32_t)); #endif if (secure_memcmp(mac, hmacbuf, hmaclen) == 0) { return 0; } return -1; } ================================================ FILE: src/libssh/src/pcap.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* pcap.c */ #include "config.h" #ifdef WITH_PCAP #include #ifdef _WIN32 #include #include #else #include #include #endif #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #include #include #include "libssh/libssh.h" #include "libssh/pcap.h" #include "libssh/session.h" #include "libssh/buffer.h" #include "libssh/socket.h" /** * @internal * * @defgroup libssh_pcap The libssh pcap functions * @ingroup libssh * * The pcap file generation * * * @{ */ /* The header of a pcap file is the following. We are not going to make it * very complicated. * Just for information. */ struct pcap_hdr_s { uint32_t magic_number; /* magic number */ uint16_t version_major; /* major version number */ uint16_t version_minor; /* minor version number */ int32_t thiszone; /* GMT to local correction */ uint32_t sigfigs; /* accuracy of timestamps */ uint32_t snaplen; /* max length of captured packets, in octets */ uint32_t network; /* data link type */ }; #define PCAP_MAGIC 0xa1b2c3d4 #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 #define DLT_RAW 12 /* raw IP */ /* TCP flags */ #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 /* The header of a pcap packet. * Just for information. */ struct pcaprec_hdr_s { uint32_t ts_sec; /* timestamp seconds */ uint32_t ts_usec; /* timestamp microseconds */ uint32_t incl_len; /* number of octets of packet saved in file */ uint32_t orig_len; /* actual length of packet */ }; /** @private * @brief a pcap context expresses the state of a pcap dump * in a SSH session only. Multiple pcap contexts may be used into * a single pcap file. */ struct ssh_pcap_context_struct { ssh_session session; ssh_pcap_file file; int connected; /* All of these information are useful to generate * the dummy IP and TCP packets */ uint32_t ipsource; uint32_t ipdest; uint16_t portsource; uint16_t portdest; uint32_t outsequence; uint32_t insequence; }; /** @private * @brief a pcap file expresses the state of a pcap file which may * contain several streams. */ struct ssh_pcap_file_struct { FILE *output; uint16_t ipsequence; }; /** * @brief create a new ssh_pcap_file object */ ssh_pcap_file ssh_pcap_file_new(void) { struct ssh_pcap_file_struct *pcap; pcap = (struct ssh_pcap_file_struct *) malloc(sizeof(struct ssh_pcap_file_struct)); if (pcap == NULL) { return NULL; } ZERO_STRUCTP(pcap); return pcap; } /** @internal * @brief writes a packet on file */ static int ssh_pcap_file_write(ssh_pcap_file pcap, ssh_buffer packet){ int err; uint32_t len; if(pcap == NULL || pcap->output==NULL) return SSH_ERROR; len=ssh_buffer_get_len(packet); err=fwrite(ssh_buffer_get(packet),len,1,pcap->output); if(err<0) return SSH_ERROR; else return SSH_OK; } /** @internal * @brief prepends a packet with the pcap header and writes packet * on file */ int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len){ ssh_buffer header=ssh_buffer_new(); struct timeval now; int err; if(header == NULL) return SSH_ERROR; gettimeofday(&now,NULL); err = ssh_buffer_allocate_size(header, sizeof(uint32_t) * 4 + ssh_buffer_get_len(packet)); if (err < 0) { goto error; } err = ssh_buffer_add_u32(header,htonl(now.tv_sec)); if (err < 0) { goto error; } err = ssh_buffer_add_u32(header,htonl(now.tv_usec)); if (err < 0) { goto error; } err = ssh_buffer_add_u32(header,htonl(ssh_buffer_get_len(packet))); if (err < 0) { goto error; } err = ssh_buffer_add_u32(header,htonl(original_len)); if (err < 0) { goto error; } err = ssh_buffer_add_buffer(header,packet); if (err < 0) { goto error; } err=ssh_pcap_file_write(pcap,header); error: SSH_BUFFER_FREE(header); return err; } /** * @brief opens a new pcap file and create header */ int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){ ssh_buffer header; int err; if(pcap == NULL) return SSH_ERROR; if(pcap->output){ fclose(pcap->output); pcap->output=NULL; } pcap->output=fopen(filename,"wb"); if(pcap->output==NULL) return SSH_ERROR; header=ssh_buffer_new(); if(header==NULL) return SSH_ERROR; err = ssh_buffer_allocate_size(header, sizeof(uint32_t) * 5 + sizeof(uint16_t) * 2); if (err < 0) { goto error; } err = ssh_buffer_add_u32(header,htonl(PCAP_MAGIC)); if (err < 0) { goto error; } err = ssh_buffer_add_u16(header,htons(PCAP_VERSION_MAJOR)); if (err < 0) { goto error; } err = ssh_buffer_add_u16(header,htons(PCAP_VERSION_MINOR)); if (err < 0) { goto error; } /* currently hardcode GMT to 0 */ err = ssh_buffer_add_u32(header,htonl(0)); if (err < 0) { goto error; } /* accuracy */ err = ssh_buffer_add_u32(header,htonl(0)); if (err < 0) { goto error; } /* size of the biggest packet */ err = ssh_buffer_add_u32(header,htonl(MAX_PACKET_LEN)); if (err < 0) { goto error; } /* we will write sort-of IP */ err = ssh_buffer_add_u32(header,htonl(DLT_RAW)); if (err < 0) { goto error; } err=ssh_pcap_file_write(pcap,header); error: SSH_BUFFER_FREE(header); return err; } int ssh_pcap_file_close(ssh_pcap_file pcap){ int err; if(pcap ==NULL || pcap->output==NULL) return SSH_ERROR; err=fclose(pcap->output); pcap->output=NULL; if(err != 0) return SSH_ERROR; else return SSH_OK; } void ssh_pcap_file_free(ssh_pcap_file pcap){ ssh_pcap_file_close(pcap); SAFE_FREE(pcap); } /** @internal * @brief allocates a new ssh_pcap_context object */ ssh_pcap_context ssh_pcap_context_new(ssh_session session){ ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct)); if(ctx==NULL){ ssh_set_error_oom(session); return NULL; } ZERO_STRUCTP(ctx); ctx->session=session; return ctx; } void ssh_pcap_context_free(ssh_pcap_context ctx){ SAFE_FREE(ctx); } void ssh_pcap_context_set_file(ssh_pcap_context ctx, ssh_pcap_file pcap){ ctx->file=pcap; } /** @internal * @brief sets the IP and port parameters in the connection */ static int ssh_pcap_context_connect(ssh_pcap_context ctx) { ssh_session session=ctx->session; struct sockaddr_in local = { .sin_family = AF_UNSPEC, }; struct sockaddr_in remote = { .sin_family = AF_UNSPEC, }; socket_t fd; socklen_t len; int rc; if (session == NULL) { return SSH_ERROR; } if (session->socket == NULL) { return SSH_ERROR; } fd = ssh_socket_get_fd(session->socket); /* TODO: adapt for windows */ if (fd < 0) { return SSH_ERROR; } len = sizeof(local); rc = getsockname(fd, (struct sockaddr *)&local, &len); if (rc < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Getting local IP address: %s", strerror(errno)); return SSH_ERROR; } len = sizeof(remote); rc = getpeername(fd, (struct sockaddr *)&remote, &len); if (rc < 0) { ssh_set_error(session, SSH_REQUEST_DENIED, "Getting remote IP address: %s", strerror(errno)); return SSH_ERROR; } if (local.sin_family != AF_INET) { ssh_set_error(session, SSH_REQUEST_DENIED, "Only IPv4 supported for pcap logging"); return SSH_ERROR; } memcpy(&ctx->ipsource, &local.sin_addr, sizeof(ctx->ipsource)); memcpy(&ctx->ipdest, &remote.sin_addr, sizeof(ctx->ipdest)); memcpy(&ctx->portsource, &local.sin_port, sizeof(ctx->portsource)); memcpy(&ctx->portdest, &remote.sin_port, sizeof(ctx->portdest)); ctx->connected = 1; return SSH_OK; } #define IPHDR_LEN 20 #define TCPHDR_LEN 20 #define TCPIPHDR_LEN (IPHDR_LEN + TCPHDR_LEN) /** @internal * @brief write a SSH packet as a TCP over IP in a pcap file * @param ctx open pcap context * @param direction SSH_PCAP_DIRECTION_IN if the packet has been received * @param direction SSH_PCAP_DIRECTION_OUT if the packet has been emitted * @param data pointer to the data to write * @param len data to write in the pcap file. May be smaller than origlen. * @param origlen number of bytes of complete data. * @returns SSH_OK write is successful * @returns SSH_ERROR an error happened. */ int ssh_pcap_context_write(ssh_pcap_context ctx, enum ssh_pcap_direction direction, void *data, uint32_t len, uint32_t origlen) { ssh_buffer ip; int rc; if (ctx == NULL || ctx->file == NULL) { return SSH_ERROR; } if (ctx->connected == 0) { if (ssh_pcap_context_connect(ctx) == SSH_ERROR) { return SSH_ERROR; } } ip = ssh_buffer_new(); if (ip == NULL) { ssh_set_error_oom(ctx->session); return SSH_ERROR; } /* build an IP packet */ rc = ssh_buffer_pack(ip, "bbwwwbbw", 4 << 4 | 5, /* V4, 20 bytes */ 0, /* tos */ origlen + TCPIPHDR_LEN, /* total len */ ctx->file->ipsequence, /* IP id number */ 0, /* fragment offset */ 64, /* TTL */ 6, /* protocol TCP=6 */ 0); /* checksum */ ctx->file->ipsequence++; if (rc != SSH_OK){ goto error; } if (direction == SSH_PCAP_DIR_OUT) { rc = ssh_buffer_add_u32(ip, ctx->ipsource); if (rc < 0) { goto error; } rc = ssh_buffer_add_u32(ip, ctx->ipdest); if (rc < 0) { goto error; } } else { rc = ssh_buffer_add_u32(ip, ctx->ipdest); if (rc < 0) { goto error; } rc = ssh_buffer_add_u32(ip, ctx->ipsource); if (rc < 0) { goto error; } } /* TCP */ if (direction == SSH_PCAP_DIR_OUT) { rc = ssh_buffer_add_u16(ip, ctx->portsource); if (rc < 0) { goto error; } rc = ssh_buffer_add_u16(ip, ctx->portdest); if (rc < 0) { goto error; } } else { rc = ssh_buffer_add_u16(ip, ctx->portdest); if (rc < 0) { goto error; } rc = ssh_buffer_add_u16(ip, ctx->portsource); if (rc < 0) { goto error; } } /* sequence number */ if (direction == SSH_PCAP_DIR_OUT) { rc = ssh_buffer_pack(ip, "d", ctx->outsequence); if (rc != SSH_OK) { goto error; } ctx->outsequence += origlen; } else { rc = ssh_buffer_pack(ip, "d", ctx->insequence); if (rc != SSH_OK) { goto error; } ctx->insequence += origlen; } /* ack number */ if (direction == SSH_PCAP_DIR_OUT) { rc = ssh_buffer_pack(ip, "d", ctx->insequence); if (rc != SSH_OK) { goto error; } } else { rc = ssh_buffer_pack(ip, "d", ctx->outsequence); if (rc != SSH_OK) { goto error; } } rc = ssh_buffer_pack(ip, "bbwwwP", 5 << 4, /* header len = 20 = 5 * 32 bits, at offset 4*/ TH_PUSH | TH_ACK, /* flags */ 65535, /* window */ 0, /* checksum */ 0, /* urgent data ptr */ (size_t)len, data); /* actual data */ if (rc != SSH_OK) { goto error; } rc = ssh_pcap_file_write_packet(ctx->file, ip, origlen + TCPIPHDR_LEN); error: SSH_BUFFER_FREE(ip); return rc; } /** @brief sets the pcap file used to trace the session * @param current session * @param pcap an handler to a pcap file. A pcap file may be used in several * sessions. * @returns SSH_ERROR in case of error, SSH_OK otherwise. */ int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcap){ ssh_pcap_context ctx=ssh_pcap_context_new(session); if(ctx==NULL){ ssh_set_error_oom(session); return SSH_ERROR; } ctx->file=pcap; if(session->pcap_ctx) ssh_pcap_context_free(session->pcap_ctx); session->pcap_ctx=ctx; return SSH_OK; } #else /* WITH_PCAP */ /* Simple stub returning errors when no pcap compiled in */ #include "libssh/libssh.h" #include "libssh/priv.h" int ssh_pcap_file_close(ssh_pcap_file pcap){ (void) pcap; return SSH_ERROR; } void ssh_pcap_file_free(ssh_pcap_file pcap){ (void) pcap; } ssh_pcap_file ssh_pcap_file_new(void){ return NULL; } int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){ (void) pcap; (void) filename; return SSH_ERROR; } int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile){ (void) pcapfile; ssh_set_error(session,SSH_REQUEST_DENIED,"Pcap support not compiled in"); return SSH_ERROR; } #endif /** @} */ ================================================ FILE: src/libssh/src/pki.c ================================================ /* * pki.c * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * Copyright (c) 2011-2013 Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /** * @defgroup libssh_pki The SSH Public Key Infrastructure * @ingroup libssh * * Functions for the creation, importation and manipulation of public and * private keys in the context of the SSH protocol * * @{ */ #include "config.h" #include #include #include #include #include #include #ifdef _WIN32 # ifdef HAVE_IO_H # include # undef open # define open _open # undef close # define close _close # undef read # define read _read # undef unlink # define unlink _unlink # endif /* HAVE_IO_H */ #endif #include "libssh/libssh.h" #include "libssh/session.h" #include "libssh/priv.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/keys.h" #include "libssh/buffer.h" #include "libssh/misc.h" #include "libssh/agent.h" enum ssh_keytypes_e pki_privatekey_type_from_string(const char *privkey) { char *start = NULL; start = strstr(privkey, DSA_HEADER_BEGIN); if (start != NULL) { return SSH_KEYTYPE_DSS; } start = strstr(privkey, RSA_HEADER_BEGIN); if (start != NULL) { return SSH_KEYTYPE_RSA; } start = strstr(privkey, ECDSA_HEADER_BEGIN); if (start != 0) { /* We don't know what the curve is at this point, so we don't actually * know the type. We figure out the actual curve and fix things up in * pki_private_key_from_base64 */ return SSH_KEYTYPE_ECDSA_P256; } return SSH_KEYTYPE_UNKNOWN; } /** * @brief returns the ECDSA key name ("ecdsa-sha2-nistp256" for example) * * @param[in] key the ssh_key whose ECDSA name to get * * @returns the ECDSA key name ("ecdsa-sha2-nistp256" for example) * * @returns "unknown" if the ECDSA key name is not known */ const char *ssh_pki_key_ecdsa_name(const ssh_key key) { if (key == NULL) { return NULL; } #ifdef HAVE_ECC /* FIXME Better ECC check needed */ return pki_key_ecdsa_nid_to_name(key->ecdsa_nid); #else return NULL; #endif } /** * @brief creates a new empty SSH key * @returns an empty ssh_key handle, or NULL on error. */ ssh_key ssh_key_new (void) { ssh_key ptr = malloc (sizeof (struct ssh_key_struct)); if (ptr == NULL) { return NULL; } ZERO_STRUCTP(ptr); return ptr; } ssh_key ssh_key_dup(const ssh_key key) { if (key == NULL) { return NULL; } return pki_key_dup(key, 0); } /** * @brief clean up the key and deallocate all existing keys * @param[in] key ssh_key to clean */ void ssh_key_clean (ssh_key key){ if(key == NULL) return; #ifdef HAVE_LIBGCRYPT if(key->dsa) gcry_sexp_release(key->dsa); if(key->rsa) gcry_sexp_release(key->rsa); if(key->ecdsa) gcry_sexp_release(key->ecdsa); #elif defined HAVE_LIBCRYPTO if(key->dsa) DSA_free(key->dsa); if(key->rsa) RSA_free(key->rsa); #ifdef HAVE_OPENSSL_ECC if(key->ecdsa) EC_KEY_free(key->ecdsa); #endif /* HAVE_OPENSSL_ECC */ #elif defined HAVE_LIBMBEDCRYPTO if (key->rsa != NULL) { mbedtls_pk_free(key->rsa); SAFE_FREE(key->rsa); } if (key->ecdsa != NULL) { mbedtls_ecdsa_free(key->ecdsa); SAFE_FREE(key->ecdsa); } #endif if (key->ed25519_privkey != NULL){ #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL implementation the private key is only the private * original seed. In the internal implementation the private key is the * concatenation of the original private seed with the public key.*/ explicit_bzero(key->ed25519_privkey, ED25519_KEY_LEN); #else explicit_bzero(key->ed25519_privkey, sizeof(ed25519_privkey)); #endif SAFE_FREE(key->ed25519_privkey); } SAFE_FREE(key->ed25519_pubkey); if (key->cert != NULL) { SSH_BUFFER_FREE(key->cert); } key->cert_type = SSH_KEYTYPE_UNKNOWN; key->flags=SSH_KEY_FLAG_EMPTY; key->type=SSH_KEYTYPE_UNKNOWN; key->ecdsa_nid = 0; key->type_c=NULL; key->dsa = NULL; key->rsa = NULL; key->ecdsa = NULL; } /** * @brief deallocate a SSH key * @param[in] key ssh_key handle to free */ void ssh_key_free (ssh_key key){ if(key){ ssh_key_clean(key); SAFE_FREE(key); } } /** * @brief returns the type of a ssh key * @param[in] key the ssh_key handle * @returns one of SSH_KEYTYPE_RSA, SSH_KEYTYPE_DSS, * SSH_KEYTYPE_ECDSA_P256, SSH_KEYTYPE_ECDSA_P384, * SSH_KEYTYPE_ECDSA_P521, SSH_KEYTYPE_ED25519, SSH_KEYTYPE_DSS_CERT01, * SSH_KEYTYPE_RSA_CERT01, SSH_KEYTYPE_ECDSA_P256_CERT01, * SSH_KEYTYPE_ECDSA_P384_CERT01, SSH_KEYTYPE_ECDSA_P521_CERT01, or * SSH_KEYTYPE_ED25519_CERT01. * @returns SSH_KEYTYPE_UNKNOWN if the type is unknown */ enum ssh_keytypes_e ssh_key_type(const ssh_key key){ if (key == NULL) { return SSH_KEYTYPE_UNKNOWN; } return key->type; } /** * @brief Convert a signature type to a string. * * @param[in] type The algorithm type to convert. * * @return A string for the keytype or NULL if unknown. */ const char * ssh_key_signature_to_char(enum ssh_keytypes_e type, enum ssh_digest_e hash_type) { switch (type) { case SSH_KEYTYPE_RSA: switch (hash_type) { case SSH_DIGEST_SHA256: return "rsa-sha2-256"; case SSH_DIGEST_SHA512: return "rsa-sha2-512"; case SSH_DIGEST_SHA1: case SSH_DIGEST_AUTO: return "ssh-rsa"; default: return NULL; } break; case SSH_KEYTYPE_RSA_CERT01: switch (hash_type) { case SSH_DIGEST_SHA256: return "rsa-sha2-256-cert-v01@openssh.com"; case SSH_DIGEST_SHA512: return "rsa-sha2-512-cert-v01@openssh.com"; case SSH_DIGEST_SHA1: case SSH_DIGEST_AUTO: return "ssh-rsa-cert-v01@openssh.com"; default: return NULL; } break; default: return ssh_key_type_to_char(type); } /* We should never reach this */ return NULL; } /** * @brief Convert a key type to a string. * * @param[in] type The type to convert. * * @return A string for the keytype or NULL if unknown. */ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) { switch (type) { case SSH_KEYTYPE_DSS: return "ssh-dss"; case SSH_KEYTYPE_RSA: return "ssh-rsa"; case SSH_KEYTYPE_ECDSA: return "ssh-ecdsa"; /* deprecated. invalid value */ case SSH_KEYTYPE_ECDSA_P256: return "ecdsa-sha2-nistp256"; case SSH_KEYTYPE_ECDSA_P384: return "ecdsa-sha2-nistp384"; case SSH_KEYTYPE_ECDSA_P521: return "ecdsa-sha2-nistp521"; case SSH_KEYTYPE_ED25519: return "ssh-ed25519"; case SSH_KEYTYPE_DSS_CERT01: return "ssh-dss-cert-v01@openssh.com"; case SSH_KEYTYPE_RSA_CERT01: return "ssh-rsa-cert-v01@openssh.com"; case SSH_KEYTYPE_ECDSA_P256_CERT01: return "ecdsa-sha2-nistp256-cert-v01@openssh.com"; case SSH_KEYTYPE_ECDSA_P384_CERT01: return "ecdsa-sha2-nistp384-cert-v01@openssh.com"; case SSH_KEYTYPE_ECDSA_P521_CERT01: return "ecdsa-sha2-nistp521-cert-v01@openssh.com"; case SSH_KEYTYPE_ED25519_CERT01: return "ssh-ed25519-cert-v01@openssh.com"; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: return NULL; } /* We should never reach this */ return NULL; } enum ssh_digest_e ssh_key_hash_from_name(const char *name) { if (name == NULL) { /* TODO we should rather fail */ return SSH_DIGEST_AUTO; } if (strcmp(name, "ssh-rsa") == 0) { return SSH_DIGEST_SHA1; } else if (strcmp(name, "ssh-dss") == 0) { return SSH_DIGEST_SHA1; } else if (strcmp(name, "rsa-sha2-256") == 0) { return SSH_DIGEST_SHA256; } else if (strcmp(name, "rsa-sha2-512") == 0) { return SSH_DIGEST_SHA512; } else if (strcmp(name, "ecdsa-sha2-nistp256") == 0) { return SSH_DIGEST_SHA256; } else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) { return SSH_DIGEST_SHA384; } else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) { return SSH_DIGEST_SHA512; } else if (strcmp(name, "ssh-ed25519") == 0) { return SSH_DIGEST_AUTO; } SSH_LOG(SSH_LOG_WARN, "Unknown signature name %s", name); /* TODO we should rather fail */ return SSH_DIGEST_AUTO; } /** * @brief Checks the given key against the configured allowed * public key algorithm types * * @param[in] session The SSH session * @param[in] type The key algorithm to check * @returns 1 if the key algorithm is allowed, 0 otherwise */ int ssh_key_algorithm_allowed(ssh_session session, const char *type) { const char *allowed_list; if (session->client) { allowed_list = session->opts.pubkey_accepted_types; if (allowed_list == NULL) { if (ssh_fips_mode()) { allowed_list = ssh_kex_get_fips_methods(SSH_HOSTKEYS); } else { allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS); } } } #ifdef WITH_SERVER else if (session->server) { allowed_list = session->opts.wanted_methods[SSH_HOSTKEYS]; if (allowed_list == NULL) { SSH_LOG(SSH_LOG_WARN, "Session invalid: no host key available"); return 0; } } #endif else { SSH_LOG(SSH_LOG_WARN, "Session invalid: not set as client nor server"); return 0; } SSH_LOG(SSH_LOG_DEBUG, "Checking %s with list <%s>", type, allowed_list); return ssh_match_group(allowed_list, type); } /** * @brief Convert a key type to a hash type. This is usually unambiguous * for all the key types, unless the SHA2 extension (RFC 8332) is * negotiated during key exchange. * * @param[in] session SSH Session. * * @param[in] type The type to convert. * * @return A hash type to be used. */ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session, enum ssh_keytypes_e type) { switch (type) { case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_DSS: return SSH_DIGEST_SHA1; case SSH_KEYTYPE_RSA_CERT01: /* If we are talking to an old OpenSSH version which does not support * SHA2 in certificates */ if ((session->openssh > 0) && (session->openssh < SSH_VERSION_INT(7, 2, 0))) { SSH_LOG(SSH_LOG_DEBUG, "We are talking to an old OpenSSH (%x); " "returning SSH_DIGEST_SHA1", session->openssh); return SSH_DIGEST_SHA1; } FALL_THROUGH; case SSH_KEYTYPE_RSA: if (ssh_key_algorithm_allowed(session, "rsa-sha2-512") && (session->extensions & SSH_EXT_SIG_RSA_SHA512)) { return SSH_DIGEST_SHA512; } if (ssh_key_algorithm_allowed(session, "rsa-sha2-256") && (session->extensions & SSH_EXT_SIG_RSA_SHA256)) { return SSH_DIGEST_SHA256; } /* Default algorithm for RSA is SHA1 */ return SSH_DIGEST_SHA1; case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P256: return SSH_DIGEST_SHA256; case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P384: return SSH_DIGEST_SHA384; case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ECDSA_P521: return SSH_DIGEST_SHA512; case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_ED25519: return SSH_DIGEST_AUTO; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Digest algorithm to be used with key type %u " "is not defined", type); } /* We should never reach this */ return SSH_DIGEST_AUTO; } /** * @brief Gets signature algorithm name to be used with the given * key type. * * @param[in] session SSH session. * @param[in] type The algorithm type to convert. * * @return A string for the keytype or NULL if unknown. */ const char * ssh_key_get_signature_algorithm(ssh_session session, enum ssh_keytypes_e type) { enum ssh_digest_e hash_type; if (type == SSH_KEYTYPE_RSA_CERT01) { /* If we are talking to an old OpenSSH version which does not support * rsa-sha2-{256,512}-cert-v01@openssh.com */ if ((session->openssh > 0) && (session->openssh < SSH_VERSION_INT(7, 8, 0))) { SSH_LOG(SSH_LOG_DEBUG, "We are talking to an old OpenSSH (%x); " "using old cert format", session->openssh); return "ssh-rsa-cert-v01@openssh.com"; } } hash_type = ssh_key_type_to_hash(session, type); return ssh_key_signature_to_char(type, hash_type); } /** * @brief Convert a ssh key algorithm name to a ssh key algorithm type. * * @param[in] name The name to convert. * * @return The enum ssh key algorithm type. */ enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) { if (name == NULL) { return SSH_KEYTYPE_UNKNOWN; } if ((strcmp(name, "rsa-sha2-256") == 0) || (strcmp(name, "rsa-sha2-512") == 0)) { return SSH_KEYTYPE_RSA; } /* Otherwise the key type matches the signature type */ return ssh_key_type_from_name(name); } /** * @brief Convert a ssh key name to a ssh key type. * * @param[in] name The name to convert. * * @return The enum ssh key type. */ enum ssh_keytypes_e ssh_key_type_from_name(const char *name) { if (name == NULL) { return SSH_KEYTYPE_UNKNOWN; } if (strcmp(name, "rsa") == 0) { return SSH_KEYTYPE_RSA; } else if (strcmp(name, "dsa") == 0) { return SSH_KEYTYPE_DSS; } else if (strcmp(name, "ssh-rsa") == 0) { return SSH_KEYTYPE_RSA; } else if (strcmp(name, "ssh-dss") == 0) { return SSH_KEYTYPE_DSS; } else if (strcmp(name, "ssh-ecdsa") == 0 || strcmp(name, "ecdsa") == 0 || strcmp(name, "ecdsa-sha2-nistp256") == 0) { return SSH_KEYTYPE_ECDSA_P256; } else if (strcmp(name, "ecdsa-sha2-nistp384") == 0) { return SSH_KEYTYPE_ECDSA_P384; } else if (strcmp(name, "ecdsa-sha2-nistp521") == 0) { return SSH_KEYTYPE_ECDSA_P521; } else if (strcmp(name, "ssh-ed25519") == 0){ return SSH_KEYTYPE_ED25519; } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_DSS_CERT01; } else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_RSA_CERT01; } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_ECDSA_P256_CERT01; } else if (strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_ECDSA_P384_CERT01; } else if (strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_ECDSA_P521_CERT01; } else if (strcmp(name, "ssh-ed25519-cert-v01@openssh.com") == 0) { return SSH_KEYTYPE_ED25519_CERT01; } return SSH_KEYTYPE_UNKNOWN; } /** * @brief Get the pubic key type corresponding to a certificate type. * * @param[in] type The certificate or public key type. * * @return The matching public key type. */ enum ssh_keytypes_e ssh_key_type_plain(enum ssh_keytypes_e type) { switch (type) { case SSH_KEYTYPE_DSS_CERT01: return SSH_KEYTYPE_DSS; case SSH_KEYTYPE_RSA_CERT01: return SSH_KEYTYPE_RSA; case SSH_KEYTYPE_ECDSA_P256_CERT01: return SSH_KEYTYPE_ECDSA_P256; case SSH_KEYTYPE_ECDSA_P384_CERT01: return SSH_KEYTYPE_ECDSA_P384; case SSH_KEYTYPE_ECDSA_P521_CERT01: return SSH_KEYTYPE_ECDSA_P521; case SSH_KEYTYPE_ED25519_CERT01: return SSH_KEYTYPE_ED25519; default: return type; } } /** * @brief Check if the key has/is a public key. * * @param[in] k The key to check. * * @return 1 if it is a public key, 0 if not. */ int ssh_key_is_public(const ssh_key k) { if (k == NULL) { return 0; } return (k->flags & SSH_KEY_FLAG_PUBLIC) == SSH_KEY_FLAG_PUBLIC; } /** * @brief Check if the key is a private key. * * @param[in] k The key to check. * * @return 1 if it is a private key, 0 if not. */ int ssh_key_is_private(const ssh_key k) { if (k == NULL) { return 0; } return (k->flags & SSH_KEY_FLAG_PRIVATE) == SSH_KEY_FLAG_PRIVATE; } /** * @brief Compare keys if they are equal. * * @param[in] k1 The first key to compare. * * @param[in] k2 The second key to compare. * * @param[in] what What part or type of the key do you want to compare. * * @return 0 if equal, 1 if not. */ int ssh_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { if (k1 == NULL || k2 == NULL) { return 1; } if (k1->type != k2->type) { SSH_LOG(SSH_LOG_WARN, "key types don't match!"); return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (!ssh_key_is_private(k1) || !ssh_key_is_private(k2)) { return 1; } } if (k1->type == SSH_KEYTYPE_ED25519) { return pki_ed25519_key_cmp(k1, k2, what); } return pki_key_compare(k1, k2, what); } ssh_signature ssh_signature_new(void) { struct ssh_signature_struct *sig; sig = malloc(sizeof(struct ssh_signature_struct)); if (sig == NULL) { return NULL; } ZERO_STRUCTP(sig); return sig; } void ssh_signature_free(ssh_signature sig) { if (sig == NULL) { return; } switch(sig->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sig->dsa_sig); #endif break; case SSH_KEYTYPE_RSA: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sig->rsa_sig); #elif defined HAVE_LIBMBEDCRYPTO SAFE_FREE(sig->rsa_sig); #endif break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC gcry_sexp_release(sig->ecdsa_sig); #elif defined HAVE_LIBMBEDCRYPTO bignum_safe_free(sig->ecdsa_sig.r); bignum_safe_free(sig->ecdsa_sig.s); #endif break; case SSH_KEYTYPE_ED25519: #ifndef HAVE_OPENSSL_ED25519 /* When using OpenSSL, the signature is stored in sig->raw_sig */ SAFE_FREE(sig->ed25519_sig); #endif break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: break; } /* Explicitly zero the signature content before free */ ssh_string_burn(sig->raw_sig); SSH_STRING_FREE(sig->raw_sig); SAFE_FREE(sig); } /** * @brief import a base64 formated key from a memory c-string * * @param[in] b64_key The c-string holding the base64 encoded key * * @param[in] passphrase The passphrase to decrypt the key, or NULL * * @param[in] auth_fn An auth function you may want to use or NULL. * * @param[in] auth_data Private data passed to the auth function. * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_ERROR in case of error, SSH_OK otherwise. * * @see ssh_key_free() */ int ssh_pki_import_privkey_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, ssh_key *pkey) { ssh_key key; char *openssh_header = NULL; if (b64_key == NULL || pkey == NULL) { return SSH_ERROR; } if (b64_key == NULL || !*b64_key) { return SSH_ERROR; } SSH_LOG(SSH_LOG_INFO, "Trying to decode privkey passphrase=%s", passphrase ? "true" : "false"); /* Test for OpenSSH key format first */ openssh_header = strstr(b64_key, OPENSSH_HEADER_BEGIN); if (openssh_header != NULL) { key = ssh_pki_openssh_privkey_import(openssh_header, passphrase, auth_fn, auth_data); } else { /* fallback on PEM decoder */ key = pki_private_key_from_base64(b64_key, passphrase, auth_fn, auth_data); } if (key == NULL) { return SSH_ERROR; } *pkey = key; return SSH_OK; } /** * @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for * keytype ssh-ed25519 * * @param[in] privkey The private key to export. * * @param[in] passphrase The passphrase to use to encrypt the key with or * NULL. An empty string means no passphrase. * * @param[in] auth_fn An auth function you may want to use or NULL. * * @param[in] auth_data Private data passed to the auth function. * * @param[out] b64_key A pointer to store the allocated base64 encoded key. You * need to free the buffer. * * @return SSH_OK on success, SSH_ERROR on error. */ int ssh_pki_export_privkey_base64(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, char **b64_key) { ssh_string blob = NULL; char *b64 = NULL; if (privkey == NULL || !ssh_key_is_private(privkey)) { return SSH_ERROR; } if (privkey->type == SSH_KEYTYPE_ED25519){ blob = ssh_pki_openssh_privkey_export(privkey, passphrase, auth_fn, auth_data); } else { blob = pki_private_key_to_pem(privkey, passphrase, auth_fn, auth_data); } if (blob == NULL) { return SSH_ERROR; } b64 = strndup(ssh_string_data(blob), ssh_string_len(blob)); SSH_STRING_FREE(blob); if (b64 == NULL) { return SSH_ERROR; } *b64_key = b64; return SSH_OK; } /** * @brief Import a key from a file. * * @param[in] filename The filename of the the private key. * * @param[in] passphrase The passphrase to decrypt the private key. Set to NULL * if none is needed or it is unknown. * * @param[in] auth_fn An auth function you may want to use or NULL. * * @param[in] auth_data Private data passed to the auth function. * * @param[out] pkey A pointer to store the allocated ssh_key. You need to * free the key. * * @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission * denied, SSH_ERROR otherwise. * * @see ssh_key_free() **/ int ssh_pki_import_privkey_file(const char *filename, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, ssh_key *pkey) { struct stat sb; char *key_buf; FILE *file; off_t size; int rc; if (pkey == NULL || filename == NULL || *filename == '\0') { return SSH_ERROR; } file = fopen(filename, "rb"); if (file == NULL) { SSH_LOG(SSH_LOG_WARN, "Error opening %s: %s", filename, strerror(errno)); return SSH_EOF; } rc = fstat(fileno(file), &sb); if (rc < 0) { fclose(file); SSH_LOG(SSH_LOG_WARN, "Error getting stat of %s: %s", filename, strerror(errno)); switch (errno) { case ENOENT: case EACCES: return SSH_EOF; } return SSH_ERROR; } if (sb.st_size > MAX_PRIVKEY_SIZE) { SSH_LOG(SSH_LOG_WARN, "Private key is bigger than 4M."); fclose(file); return SSH_ERROR; } key_buf = malloc(sb.st_size + 1); if (key_buf == NULL) { fclose(file); SSH_LOG(SSH_LOG_WARN, "Out of memory!"); return SSH_ERROR; } size = fread(key_buf, 1, sb.st_size, file); fclose(file); if (size != sb.st_size) { SAFE_FREE(key_buf); SSH_LOG(SSH_LOG_WARN, "Error reading %s: %s", filename, strerror(errno)); return SSH_ERROR; } key_buf[size] = 0; rc = ssh_pki_import_privkey_base64(key_buf, passphrase, auth_fn, auth_data, pkey); SAFE_FREE(key_buf); return rc; } /** * @brief Export a private key to a pem file on disk, or OpenSSH format for * keytype ssh-ed25519 * * @param[in] privkey The private key to export. * * @param[in] passphrase The passphrase to use to encrypt the key with or * NULL. An empty string means no passphrase. * * @param[in] auth_fn An auth function you may want to use or NULL. * * @param[in] auth_data Private data passed to the auth function. * * @param[in] filename The path where to store the pem file. * * @return SSH_OK on success, SSH_ERROR on error. */ int ssh_pki_export_privkey_file(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, const char *filename) { ssh_string blob; FILE *fp; int rc; if (privkey == NULL || !ssh_key_is_private(privkey)) { return SSH_ERROR; } fp = fopen(filename, "wb"); if (fp == NULL) { SSH_LOG(SSH_LOG_FUNCTIONS, "Error opening %s: %s", filename, strerror(errno)); return SSH_EOF; } if (privkey->type == SSH_KEYTYPE_ED25519){ blob = ssh_pki_openssh_privkey_export(privkey, passphrase, auth_fn, auth_data); } else { blob = pki_private_key_to_pem(privkey, passphrase, auth_fn, auth_data); } if (blob == NULL) { fclose(fp); return -1; } rc = fwrite(ssh_string_data(blob), ssh_string_len(blob), 1, fp); SSH_STRING_FREE(blob); if (rc != 1 || ferror(fp)) { fclose(fp); unlink(filename); return SSH_ERROR; } fclose(fp); return SSH_OK; } /* temporary function to migrate seemlessly to ssh_key */ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) { ssh_public_key pub; ssh_key tmp; if(key == NULL) { return NULL; } tmp = ssh_key_dup(key); if (tmp == NULL) { return NULL; } pub = malloc(sizeof(struct ssh_public_key_struct)); if (pub == NULL) { ssh_key_free(tmp); return NULL; } ZERO_STRUCTP(pub); pub->type = tmp->type; pub->type_c = tmp->type_c; pub->dsa_pub = tmp->dsa; tmp->dsa = NULL; pub->rsa_pub = tmp->rsa; tmp->rsa = NULL; ssh_key_free(tmp); return pub; } ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) { ssh_private_key privkey; privkey = malloc(sizeof(struct ssh_private_key_struct)); if (privkey == NULL) { ssh_key_free(key); return NULL; } privkey->type = key->type; privkey->dsa_priv = key->dsa; privkey->rsa_priv = key->rsa; return privkey; } int pki_import_privkey_buffer(enum ssh_keytypes_e type, ssh_buffer buffer, ssh_key *pkey) { ssh_key key = NULL; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string pubkey = NULL; ssh_string privkey = NULL; rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g, &pubkey, &privkey); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } rc = pki_privkey_build_dss(key, p, q, g, pubkey, privkey); #ifdef DEBUG_CRYPTO ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p)); ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q)); ssh_log_hexdump("g", ssh_string_data(g), ssh_string_len(g)); ssh_log_hexdump("pubkey", ssh_string_data(pubkey), ssh_string_len(pubkey)); ssh_log_hexdump("privkey", ssh_string_data(privkey), ssh_string_len(privkey)); #endif ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(pubkey); SSH_STRING_FREE(pubkey); ssh_string_burn(privkey); SSH_STRING_FREE(privkey); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: { ssh_string n = NULL; ssh_string e = NULL; ssh_string d = NULL; ssh_string iqmp = NULL; ssh_string p = NULL; ssh_string q = NULL; rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d, &iqmp, &p, &q); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } rc = pki_privkey_build_rsa(key, n, e, d, iqmp, p, q); #ifdef DEBUG_CRYPTO ssh_log_hexdump("n", ssh_string_data(n), ssh_string_len(n)); ssh_log_hexdump("e", ssh_string_data(e), ssh_string_len(e)); ssh_log_hexdump("d", ssh_string_data(d), ssh_string_len(d)); ssh_log_hexdump("iqmp", ssh_string_data(iqmp), ssh_string_len(iqmp)); ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p)); ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q)); #endif ssh_string_burn(n); SSH_STRING_FREE(n); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(d); SSH_STRING_FREE(d); ssh_string_burn(iqmp); SSH_STRING_FREE(iqmp); ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(q); SSH_STRING_FREE(q); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key"); goto fail; } } break; #ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: { ssh_string e = NULL; ssh_string exp = NULL; ssh_string i = NULL; int nid; rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); SSH_STRING_FREE(i); if (nid == -1) { goto fail; } rc = pki_privkey_build_ecdsa(key, nid, e, exp); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(exp); SSH_STRING_FREE(exp); if (rc < 0) { SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key"); goto fail; } } break; #endif case SSH_KEYTYPE_ED25519: { ssh_string pubkey = NULL, privkey = NULL; rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey); if (rc != SSH_OK){ SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } rc = pki_privkey_build_ed25519(key, pubkey, privkey); ssh_string_burn(privkey); SSH_STRING_FREE(privkey); SSH_STRING_FREE(pubkey); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key"); goto fail; } } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; } static int pki_import_pubkey_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_key key = NULL; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string pubkey = NULL; rc = ssh_buffer_unpack(buffer, "SSSS", &p, &q, &g, &pubkey); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_log_hexdump("p", ssh_string_data(p), ssh_string_len(p)); ssh_log_hexdump("q", ssh_string_data(q), ssh_string_len(q)); ssh_log_hexdump("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(pubkey); SSH_STRING_FREE(pubkey); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key"); goto fail; } } break; case SSH_KEYTYPE_RSA: { ssh_string e = NULL; ssh_string n = NULL; rc = ssh_buffer_unpack(buffer, "SS", &e, &n); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_log_hexdump("e", ssh_string_data(e), ssh_string_len(e)); ssh_log_hexdump("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(n); SSH_STRING_FREE(n); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key"); goto fail; } } break; #ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA: /* deprecated */ case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: { ssh_string e = NULL; ssh_string i = NULL; int nid; rc = ssh_buffer_unpack(buffer, "SS", &i, &e); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Unpack error"); goto fail; } nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); SSH_STRING_FREE(i); if (nid == -1) { goto fail; } rc = pki_pubkey_build_ecdsa(key, nid, e); ssh_string_burn(e); SSH_STRING_FREE(e); if (rc < 0) { SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key"); goto fail; } /* Update key type */ if (type == SSH_KEYTYPE_ECDSA) { key->type_c = ssh_pki_key_ecdsa_name(key); } } break; #endif case SSH_KEYTYPE_ED25519: { ssh_string pubkey = ssh_buffer_get_ssh_string(buffer); if (ssh_string_len(pubkey) != ED25519_KEY_LEN) { SSH_LOG(SSH_LOG_WARN, "Invalid public key length"); ssh_string_burn(pubkey); SSH_STRING_FREE(pubkey); goto fail; } key->ed25519_pubkey = malloc(ED25519_KEY_LEN); if (key->ed25519_pubkey == NULL) { ssh_string_burn(pubkey); SSH_STRING_FREE(pubkey); goto fail; } memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN); ssh_string_burn(pubkey); SSH_STRING_FREE(pubkey); } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; } static int pki_import_cert_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer cert; ssh_string tmp_s; const char *type_c; ssh_key key = NULL; int rc; /* * The cert blob starts with the key type as an ssh_string, but this * string has been read out of the buffer to identify the key type. * Simply add it again as first element before copying the rest. */ cert = ssh_buffer_new(); if (cert == NULL) { goto fail; } type_c = ssh_key_type_to_char(type); tmp_s = ssh_string_from_char(type_c); if (tmp_s == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(cert, tmp_s); SSH_STRING_FREE(tmp_s); if (rc != 0) { goto fail; } rc = ssh_buffer_add_buffer(cert, buffer); if (rc != 0) { goto fail; } /* * After the key type, comes an ssh_string nonce. Just after this comes the * cert public key, which can be parsed out of the buffer. */ tmp_s = ssh_buffer_get_ssh_string(buffer); if (tmp_s == NULL) { goto fail; } SSH_STRING_FREE(tmp_s); switch (type) { case SSH_KEYTYPE_DSS_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_DSS, &key); break; case SSH_KEYTYPE_RSA_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_RSA, &key); break; case SSH_KEYTYPE_ECDSA_P256_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_ECDSA_P256, &key); break; case SSH_KEYTYPE_ECDSA_P384_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_ECDSA_P384, &key); break; case SSH_KEYTYPE_ECDSA_P521_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_ECDSA_P521, &key); break; case SSH_KEYTYPE_ED25519_CERT01: rc = pki_import_pubkey_buffer(buffer, SSH_KEYTYPE_ED25519, &key); break; default: key = ssh_key_new(); } if (rc != 0 || key == NULL) { goto fail; } key->type = type; key->type_c = type_c; key->cert = (void*) cert; *pkey = key; return SSH_OK; fail: ssh_key_free(key); SSH_BUFFER_FREE(cert); return SSH_ERROR; } /** * @brief Import a base64 formated public key from a memory c-string. * * @param[in] b64_key The base64 key to format. * * @param[in] type The type of the key to format. * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ int ssh_pki_import_pubkey_base64(const char *b64_key, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer buffer = NULL; ssh_string type_s = NULL; int rc; if (b64_key == NULL || pkey == NULL) { return SSH_ERROR; } buffer = base64_to_bin(b64_key); if (buffer == NULL) { return SSH_ERROR; } type_s = ssh_buffer_get_ssh_string(buffer); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return SSH_ERROR; } SSH_STRING_FREE(type_s); if (is_cert_type(type)) { rc = pki_import_cert_buffer(buffer, type, pkey); } else { rc = pki_import_pubkey_buffer(buffer, type, pkey); } SSH_BUFFER_FREE(buffer); return rc; } /** * @internal * * @brief Import a public key from a ssh string. * * @param[in] key_blob The key blob to import as specified in RFC 4253 section * 6.6 "Public Key Algorithms". * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ int ssh_pki_import_pubkey_blob(const ssh_string key_blob, ssh_key *pkey) { ssh_buffer buffer = NULL; ssh_string type_s = NULL; enum ssh_keytypes_e type; int rc; if (key_blob == NULL || pkey == NULL) { return SSH_ERROR; } buffer = ssh_buffer_new(); if (buffer == NULL) { SSH_LOG(SSH_LOG_WARN, "Out of memory!"); return SSH_ERROR; } rc = ssh_buffer_add_data(buffer, ssh_string_data(key_blob), ssh_string_len(key_blob)); if (rc < 0) { SSH_LOG(SSH_LOG_WARN, "Out of memory!"); goto fail; } type_s = ssh_buffer_get_ssh_string(buffer); if (type_s == NULL) { SSH_LOG(SSH_LOG_WARN, "Out of memory!"); goto fail; } type = ssh_key_type_from_name(ssh_string_get_char(type_s)); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown key type found!"); goto fail; } SSH_STRING_FREE(type_s); if (is_cert_type(type)) { rc = pki_import_cert_buffer(buffer, type, pkey); } else { rc = pki_import_pubkey_buffer(buffer, type, pkey); } SSH_BUFFER_FREE(buffer); return rc; fail: SSH_BUFFER_FREE(buffer); SSH_STRING_FREE(type_s); return SSH_ERROR; } /** * @brief Import a public key from the given filename. * * @param[in] filename The path to the public key. * * @param[out] pkey A pointer to store the allocated public key. You need to * free the memory. * * @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission * denied, SSH_ERROR otherwise. * * @see ssh_key_free() */ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey) { enum ssh_keytypes_e type; struct stat sb; char *key_buf, *p; size_t buflen, i; const char *q; FILE *file; off_t size; int rc, cmp; if (pkey == NULL || filename == NULL || *filename == '\0') { return SSH_ERROR; } file = fopen(filename, "rb"); if (file == NULL) { SSH_LOG(SSH_LOG_WARN, "Error opening %s: %s", filename, strerror(errno)); return SSH_EOF; } rc = fstat(fileno(file), &sb); if (rc < 0) { fclose(file); SSH_LOG(SSH_LOG_WARN, "Error gettint stat of %s: %s", filename, strerror(errno)); switch (errno) { case ENOENT: case EACCES: return SSH_EOF; } return SSH_ERROR; } if (sb.st_size > MAX_PUBKEY_SIZE) { fclose(file); return SSH_ERROR; } key_buf = malloc(sb.st_size + 1); if (key_buf == NULL) { fclose(file); SSH_LOG(SSH_LOG_WARN, "Out of memory!"); return SSH_ERROR; } size = fread(key_buf, 1, sb.st_size, file); fclose(file); if (size != sb.st_size) { SAFE_FREE(key_buf); SSH_LOG(SSH_LOG_WARN, "Error reading %s: %s", filename, strerror(errno)); return SSH_ERROR; } key_buf[size] = '\0'; buflen = strlen(key_buf); /* Test for new OpenSSH key format first */ cmp = strncmp(key_buf, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN)); if (cmp == 0) { *pkey = ssh_pki_openssh_pubkey_import(key_buf); SAFE_FREE(key_buf); if (*pkey == NULL) { SSH_LOG(SSH_LOG_WARN, "Failed to import public key from OpenSSH" " private key file"); return SSH_ERROR; } return SSH_OK; } /* This the old one-line public key format */ q = p = key_buf; for (i = 0; i < buflen; i++) { if (isspace((int)p[i])) { p[i] = '\0'; break; } } type = ssh_key_type_from_name(q); if (type == SSH_KEYTYPE_UNKNOWN) { SAFE_FREE(key_buf); return SSH_ERROR; } q = &p[i + 1]; for (; i < buflen; i++) { if (isspace((int)p[i])) { p[i] = '\0'; break; } } rc = ssh_pki_import_pubkey_base64(q, type, pkey); SAFE_FREE(key_buf); return rc; } /** * @brief Import a base64 formated certificate from a memory c-string. * * @param[in] b64_cert The base64 cert to format. * * @param[in] type The type of the cert to format. * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ int ssh_pki_import_cert_base64(const char *b64_cert, enum ssh_keytypes_e type, ssh_key *pkey) { return ssh_pki_import_pubkey_base64(b64_cert, type, pkey); } /** * @internal * * @brief Import a certificate from a ssh string. * * @param[in] cert_blob The cert blob to import as specified in RFC 4253 section * 6.6 "Public Key Algorithms". * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ int ssh_pki_import_cert_blob(const ssh_string cert_blob, ssh_key *pkey) { return ssh_pki_import_pubkey_blob(cert_blob, pkey); } /** * @brief Import a certificate from the given filename. * * @param[in] filename The path to the certificate. * * @param[out] pkey A pointer to store the allocated certificate. You need to * free the memory. * * @returns SSH_OK on success, SSH_EOF if the file doesn't exist or permission * denied, SSH_ERROR otherwise. * * @see ssh_key_free() */ int ssh_pki_import_cert_file(const char *filename, ssh_key *pkey) { return ssh_pki_import_pubkey_file(filename, pkey); } /** * @brief Generates a keypair. * * @param[in] type Type of key to create * * @param[in] parameter Parameter to the creation of key: * rsa : length of the key in bits (e.g. 1024, 2048, 4096) * dsa : length of the key in bits (e.g. 1024, 2048, 3072) * @param[out] pkey A pointer to store the allocated private key. You need * to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @warning Generating a key pair may take some time. */ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey){ int rc; ssh_key key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; switch(type){ case SSH_KEYTYPE_RSA: rc = pki_key_generate_rsa(key, parameter); if(rc == SSH_ERROR) goto error; break; case SSH_KEYTYPE_DSS: rc = pki_key_generate_dss(key, parameter); if(rc == SSH_ERROR) goto error; break; #ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA: /* deprecated */ rc = pki_key_generate_ecdsa(key, parameter); if (rc == SSH_ERROR) { goto error; } /* Update key type */ key->type_c = ssh_pki_key_ecdsa_name(key); break; case SSH_KEYTYPE_ECDSA_P256: rc = pki_key_generate_ecdsa(key, 256); if (rc == SSH_ERROR) { goto error; } break; case SSH_KEYTYPE_ECDSA_P384: rc = pki_key_generate_ecdsa(key, 384); if (rc == SSH_ERROR) { goto error; } break; case SSH_KEYTYPE_ECDSA_P521: rc = pki_key_generate_ecdsa(key, 521); if (rc == SSH_ERROR) { goto error; } break; #endif case SSH_KEYTYPE_ED25519: rc = pki_key_generate_ed25519(key); if (rc == SSH_ERROR) { goto error; } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: goto error; } *pkey = key; return SSH_OK; error: ssh_key_free(key); return SSH_ERROR; } /** * @brief Create a public key from a private key. * * @param[in] privkey The private key to get the public key from. * * @param[out] pkey A pointer to store the newly allocated public key. You * NEED to free the key. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ int ssh_pki_export_privkey_to_pubkey(const ssh_key privkey, ssh_key *pkey) { ssh_key pubkey; if (privkey == NULL || !ssh_key_is_private(privkey)) { return SSH_ERROR; } pubkey = pki_key_dup(privkey, 1); if (pubkey == NULL) { return SSH_ERROR; } *pkey = pubkey; return SSH_OK; } /** * @internal * * @brief Create a key_blob from a public key. * * The "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key * Algorithms" for any of the supported protocol 2 key types. * Encoding of EC keys is described in RFC 5656 section 3.1 "Key * Format". * * @param[in] key A public or private key to create the public ssh_string * from. * * @param[out] pblob A pointer to store the newly allocated key blob. You * NEED to free it. * * @return SSH_OK on success, SSH_ERROR otherwise. * * @see SSH_STRING_FREE() */ int ssh_pki_export_pubkey_blob(const ssh_key key, ssh_string *pblob) { ssh_string blob; if (key == NULL) { return SSH_OK; } blob = pki_publickey_to_blob(key); if (blob == NULL) { return SSH_ERROR; } *pblob = blob; return SSH_OK; } /** * @brief Convert a public key to a base64 encoded key. * * @param[in] key The key to hash * * @param[out] b64_key A pointer to store the allocated base64 encoded key. You * need to free the buffer. * * @return SSH_OK on success, SSH_ERROR on error. * * @see SSH_STRING_FREE_CHAR() */ int ssh_pki_export_pubkey_base64(const ssh_key key, char **b64_key) { ssh_string key_blob; unsigned char *b64; if (key == NULL || b64_key == NULL) { return SSH_ERROR; } key_blob = pki_publickey_to_blob(key); if (key_blob == NULL) { return SSH_ERROR; } b64 = bin_to_base64(ssh_string_data(key_blob), ssh_string_len(key_blob)); SSH_STRING_FREE(key_blob); if (b64 == NULL) { return SSH_ERROR; } *b64_key = (char *)b64; return SSH_OK; } int ssh_pki_export_pubkey_file(const ssh_key key, const char *filename) { char key_buf[4096]; char host[256]; char *b64_key; char *user; FILE *fp; int rc; if (key == NULL || filename == NULL || *filename == '\0') { return SSH_ERROR; } user = ssh_get_local_username(); if (user == NULL) { return SSH_ERROR; } rc = gethostname(host, sizeof(host)); if (rc < 0) { free(user); return SSH_ERROR; } rc = ssh_pki_export_pubkey_base64(key, &b64_key); if (rc < 0) { free(user); return SSH_ERROR; } rc = snprintf(key_buf, sizeof(key_buf), "%s %s %s@%s\n", key->type_c, b64_key, user, host); free(user); free(b64_key); if (rc < 0) { return SSH_ERROR; } fp = fopen(filename, "wb+"); if (fp == NULL) { return SSH_ERROR; } rc = fwrite(key_buf, strlen(key_buf), 1, fp); if (rc != 1 || ferror(fp)) { fclose(fp); unlink(filename); return SSH_ERROR; } fclose(fp); return SSH_OK; } /** * @brief Copy the certificate part of a public key into a private key. * * @param[in] certkey The certificate key. * * @param[in] privkey The target private key to copy the certificate to. * * @returns SSH_OK on success, SSH_ERROR otherwise. **/ int ssh_pki_copy_cert_to_privkey(const ssh_key certkey, ssh_key privkey) { ssh_buffer cert_buffer; int rc; if (certkey == NULL || privkey == NULL) { return SSH_ERROR; } if (privkey->cert != NULL) { return SSH_ERROR; } if (certkey->cert == NULL) { return SSH_ERROR; } cert_buffer = ssh_buffer_new(); if (cert_buffer == NULL) { return SSH_ERROR; } rc = ssh_buffer_add_buffer(cert_buffer, certkey->cert); if (rc != 0) { SSH_BUFFER_FREE(cert_buffer); return SSH_ERROR; } privkey->cert = cert_buffer; privkey->cert_type = certkey->type; return SSH_OK; } int ssh_pki_export_signature_blob(const ssh_signature sig, ssh_string *sig_blob) { ssh_buffer buf = NULL; ssh_string str; int rc; if (sig == NULL || sig_blob == NULL) { return SSH_ERROR; } buf = ssh_buffer_new(); if (buf == NULL) { return SSH_ERROR; } str = ssh_string_from_char(sig->type_c); if (str == NULL) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } rc = ssh_buffer_add_ssh_string(buf, str); SSH_STRING_FREE(str); if (rc < 0) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } str = pki_signature_to_blob(sig); if (str == NULL) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } rc = ssh_buffer_add_ssh_string(buf, str); SSH_STRING_FREE(str); if (rc < 0) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } str = ssh_string_new(ssh_buffer_get_len(buf)); if (str == NULL) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } ssh_string_fill(str, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); SSH_BUFFER_FREE(buf); *sig_blob = str; return SSH_OK; } int ssh_pki_import_signature_blob(const ssh_string sig_blob, const ssh_key pubkey, ssh_signature *psig) { ssh_signature sig = NULL; enum ssh_keytypes_e type; enum ssh_digest_e hash_type; ssh_string algorithm = NULL, blob = NULL; ssh_buffer buf; const char *alg = NULL; int rc; if (sig_blob == NULL || psig == NULL) { return SSH_ERROR; } buf = ssh_buffer_new(); if (buf == NULL) { return SSH_ERROR; } rc = ssh_buffer_add_data(buf, ssh_string_data(sig_blob), ssh_string_len(sig_blob)); if (rc < 0) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } algorithm = ssh_buffer_get_ssh_string(buf); if (algorithm == NULL) { SSH_BUFFER_FREE(buf); return SSH_ERROR; } alg = ssh_string_get_char(algorithm); type = ssh_key_type_from_signature_name(alg); hash_type = ssh_key_hash_from_name(alg); SSH_STRING_FREE(algorithm); blob = ssh_buffer_get_ssh_string(buf); SSH_BUFFER_FREE(buf); if (blob == NULL) { return SSH_ERROR; } sig = pki_signature_from_blob(pubkey, blob, type, hash_type); SSH_STRING_FREE(blob); if (sig == NULL) { return SSH_ERROR; } *psig = sig; return SSH_OK; } /** * @internal * * @brief Check if the provided key can be used with the provided hash type for * data signing or signature verification. * * @param[in] key The key to be checked. * @param[in] hash_type The digest algorithm to be checked. * * @return SSH_OK if compatible; SSH_ERROR otherwise */ int pki_key_check_hash_compatible(ssh_key key, enum ssh_digest_e hash_type) { if (key == NULL) { SSH_LOG(SSH_LOG_TRACE, "Null pointer provided as key to " "pki_key_check_hash_compatible()"); return SSH_ERROR; } switch(key->type) { case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_DSS: if (hash_type == SSH_DIGEST_SHA1) { if (ssh_fips_mode()) { SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode"); return SSH_ERROR; } else { return SSH_OK; } } break; case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_RSA: if (hash_type == SSH_DIGEST_SHA1) { if (ssh_fips_mode()) { SSH_LOG(SSH_LOG_WARN, "SHA1 is not allowed in FIPS mode"); return SSH_ERROR; } else { return SSH_OK; } } if (hash_type == SSH_DIGEST_SHA256 || hash_type == SSH_DIGEST_SHA512) { return SSH_OK; } break; case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P256: if (hash_type == SSH_DIGEST_SHA256) { return SSH_OK; } break; case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P384: if (hash_type == SSH_DIGEST_SHA384) { return SSH_OK; } break; case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ECDSA_P521: if (hash_type == SSH_DIGEST_SHA512) { return SSH_OK; } break; case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_ED25519: if (hash_type == SSH_DIGEST_AUTO) { return SSH_OK; } break; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown key type %d", key->type); return SSH_ERROR; } SSH_LOG(SSH_LOG_WARN, "Key type %d incompatible with hash type %d", key->type, hash_type); return SSH_ERROR; } int ssh_pki_signature_verify(ssh_session session, ssh_signature sig, const ssh_key key, const unsigned char *input, size_t input_len) { int rc; enum ssh_keytypes_e key_type; if (session == NULL || sig == NULL || key == NULL || input == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "ssh_pki_signature_verify()"); return SSH_ERROR; } key_type = ssh_key_type_plain(key->type); SSH_LOG(SSH_LOG_FUNCTIONS, "Going to verify a %s type signature", sig->type_c); if (key_type != sig->type) { SSH_LOG(SSH_LOG_WARN, "Can not verify %s signature with %s key", sig->type_c, key->type_c); return SSH_ERROR; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(key, sig->hash_type); if (rc != SSH_OK) { return SSH_ERROR; } rc = pki_verify_data_signature(sig, key, input, input_len); return rc; } ssh_signature pki_do_sign(const ssh_key privkey, const unsigned char *input, size_t input_len, enum ssh_digest_e hash_type) { int rc; if (privkey == NULL || input == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_do_sign()"); return NULL; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(privkey, hash_type); if (rc != SSH_OK) { return NULL; } return pki_sign_data(privkey, hash_type, input, input_len); } /* * This function signs the session id as a string then * the content of sigbuf */ ssh_string ssh_pki_do_sign(ssh_session session, ssh_buffer sigbuf, const ssh_key privkey, enum ssh_digest_e hash_type) { struct ssh_crypto_struct *crypto = NULL; ssh_signature sig = NULL; ssh_string sig_blob = NULL; ssh_string session_id = NULL; ssh_buffer sign_input = NULL; int rc; if (session == NULL || sigbuf == NULL || privkey == NULL || !ssh_key_is_private(privkey)) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "ssh_pki_do_sign()"); return NULL; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH); if (crypto == NULL) { return NULL; } /* Get the session ID */ session_id = ssh_string_new(crypto->digest_len); if (session_id == NULL) { return NULL; } ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); /* Fill the input */ sign_input = ssh_buffer_new(); if (sign_input == NULL) { goto end; } ssh_buffer_set_secure(sign_input); rc = ssh_buffer_pack(sign_input, "SP", session_id, ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf)); if (rc != SSH_OK) { goto end; } /* Generate the signature */ sig = pki_do_sign(privkey, ssh_buffer_get(sign_input), ssh_buffer_get_len(sign_input), hash_type); if (sig == NULL) { goto end; } /* Convert the signature to blob */ rc = ssh_pki_export_signature_blob(sig, &sig_blob); if (rc < 0) { sig_blob = NULL; } end: ssh_signature_free(sig); SSH_BUFFER_FREE(sign_input); SSH_STRING_FREE(session_id); return sig_blob; } ssh_string ssh_pki_do_sign_agent(ssh_session session, struct ssh_buffer_struct *buf, const ssh_key pubkey) { struct ssh_crypto_struct *crypto = NULL; ssh_string session_id; ssh_string sig_blob; ssh_buffer sig_buf; int rc; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_BOTH); if (crypto == NULL) { return NULL; } /* prepend session identifier */ session_id = ssh_string_new(crypto->digest_len); if (session_id == NULL) { return NULL; } ssh_string_fill(session_id, crypto->session_id, crypto->digest_len); sig_buf = ssh_buffer_new(); if (sig_buf == NULL) { SSH_STRING_FREE(session_id); return NULL; } rc = ssh_buffer_add_ssh_string(sig_buf, session_id); if (rc < 0) { SSH_STRING_FREE(session_id); SSH_BUFFER_FREE(sig_buf); return NULL; } SSH_STRING_FREE(session_id); /* append out buffer */ if (ssh_buffer_add_buffer(sig_buf, buf) < 0) { SSH_BUFFER_FREE(sig_buf); return NULL; } /* create signature */ sig_blob = ssh_agent_sign_data(session, pubkey, sig_buf); SSH_BUFFER_FREE(sig_buf); return sig_blob; } #ifdef WITH_SERVER ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session, const ssh_key privkey, const enum ssh_digest_e digest) { struct ssh_crypto_struct *crypto = NULL; ssh_signature sig = NULL; ssh_string sig_blob = NULL; ssh_buffer sign_input = NULL; int rc; if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) { return NULL; } crypto = session->next_crypto ? session->next_crypto : session->current_crypto; if (crypto->secret_hash == NULL){ ssh_set_error(session,SSH_FATAL,"Missing secret_hash"); return NULL; } /* Fill the input */ sign_input = ssh_buffer_new(); if (sign_input == NULL) { goto end; } ssh_buffer_set_secure(sign_input); rc = ssh_buffer_pack(sign_input, "P", crypto->digest_len, crypto->secret_hash); if (rc != SSH_OK) { goto end; } /* Generate the signature */ sig = pki_do_sign(privkey, ssh_buffer_get(sign_input), ssh_buffer_get_len(sign_input), digest); if (sig == NULL) { goto end; } /* Convert the signature to blob */ rc = ssh_pki_export_signature_blob(sig, &sig_blob); if (rc < 0) { sig_blob = NULL; } end: ssh_signature_free(sig); SSH_BUFFER_FREE(sign_input); return sig_blob; } #endif /* WITH_SERVER */ /** * @} */ ================================================ FILE: src/libssh/src/pki_container_openssh.c ================================================ /* * pki_container_openssh.c * This file is part of the SSH Library * * Copyright (c) 2013,2014 Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /** * @ingroup libssh_pki * * * @{ */ #include "config.h" #include #include #include #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/buffer.h" /** * @internal * * @brief Import a private key from a ssh buffer. * * @param[in] key_blob_buffer The key blob to import as specified in * key.c:key_private_serialize in OpenSSH source * code. * * @param[out] pkey A pointer where the allocated key can be stored. You * need to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @see ssh_key_free() */ static int pki_openssh_import_privkey_blob(ssh_buffer key_blob_buffer, ssh_key *pkey) { enum ssh_keytypes_e type; char *type_s = NULL; ssh_key key = NULL; int rc; if (pkey == NULL) { return SSH_ERROR; } rc = ssh_buffer_unpack(key_blob_buffer, "s", &type_s); if (rc == SSH_ERROR){ SSH_LOG(SSH_LOG_WARN, "Unpack error"); return SSH_ERROR; } type = ssh_key_type_from_name(type_s); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown key type '%s' found!", type_s); return SSH_ERROR; } SAFE_FREE(type_s); rc = pki_import_privkey_buffer(type, key_blob_buffer, &key); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Failed to read key in OpenSSH format"); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; } /** * @brief decrypts an encrypted private key blob in OpenSSH format. * */ static int pki_private_key_decrypt(ssh_string blob, const char* passphrase, const char *ciphername, const char *kdfname, ssh_string kdfoptions, ssh_auth_callback auth_fn, void *auth_data) { struct ssh_cipher_struct *ciphers = ssh_get_ciphertab(); struct ssh_cipher_struct cipher; uint8_t key_material[128] = {0}; char passphrase_buffer[128] = {0}; size_t key_material_len; ssh_buffer buffer = NULL; ssh_string salt = NULL; uint32_t rounds; int cmp; int rc; int i; cmp = strcmp(ciphername, "none"); if (cmp == 0){ /* no decryption required */ return SSH_OK; } for (i = 0; ciphers[i].name != NULL; i++) { cmp = strcmp(ciphername, ciphers[i].name); if (cmp == 0){ memcpy(&cipher, &ciphers[i], sizeof(cipher)); break; } } if (ciphers[i].name == NULL){ SSH_LOG(SSH_LOG_WARN, "Unsupported cipher %s", ciphername); return SSH_ERROR; } cmp = strcmp(kdfname, "bcrypt"); if (cmp != 0) { SSH_LOG(SSH_LOG_WARN, "Unsupported KDF %s", kdfname); return SSH_ERROR; } if (ssh_string_len(blob) % cipher.blocksize != 0) { SSH_LOG(SSH_LOG_WARN, "Encrypted string not multiple of blocksize: %zu", ssh_string_len(blob)); return SSH_ERROR; } buffer = ssh_buffer_new(); if (buffer == NULL){ return SSH_ERROR; } rc = ssh_buffer_add_data(buffer, ssh_string_data(kdfoptions), ssh_string_len(kdfoptions)); if (rc != SSH_ERROR){ rc = ssh_buffer_unpack(buffer, "Sd", &salt, &rounds); } SSH_BUFFER_FREE(buffer); if (rc == SSH_ERROR){ return SSH_ERROR; } /* We need material for key (keysize bits / 8) and IV (blocksize) */ key_material_len = cipher.keysize/8 + cipher.blocksize; if (key_material_len > sizeof(key_material)) { SSH_LOG(SSH_LOG_WARN, "Key material too big"); return SSH_ERROR; } SSH_LOG(SSH_LOG_DEBUG, "Decryption: %d key, %d IV, %d rounds, %zu bytes salt", cipher.keysize/8, cipher.blocksize, rounds, ssh_string_len(salt)); if (passphrase == NULL) { if (auth_fn == NULL) { SAFE_FREE(salt); SSH_LOG(SSH_LOG_WARN, "No passphrase provided"); return SSH_ERROR; } rc = auth_fn("Passphrase", passphrase_buffer, sizeof(passphrase_buffer), 0, 0, auth_data); if (rc != SSH_OK) { SAFE_FREE(salt); return SSH_ERROR; } passphrase = passphrase_buffer; } rc = bcrypt_pbkdf(passphrase, strlen(passphrase), ssh_string_data(salt), ssh_string_len(salt), key_material, key_material_len, rounds); SAFE_FREE(salt); if (rc < 0){ return SSH_ERROR; } explicit_bzero(passphrase_buffer, sizeof(passphrase_buffer)); cipher.set_decrypt_key(&cipher, key_material, key_material + cipher.keysize/8); cipher.decrypt(&cipher, ssh_string_data(blob), ssh_string_data(blob), ssh_string_len(blob)); ssh_cipher_clear(&cipher); return SSH_OK; } /** @internal * @brief Import a private key in OpenSSH (new) format. This format is * typically used with ed25519 keys but can be used for others. */ static ssh_key ssh_pki_openssh_import(const char *text_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data, bool private) { const char *ptr = text_key; const char *end; char *base64; int cmp; int rc; int i; ssh_buffer buffer = NULL, privkey_buffer=NULL; char *magic = NULL, *ciphername = NULL, *kdfname = NULL; uint32_t nkeys = 0, checkint1 = 0, checkint2 = 0xFFFF; ssh_string kdfoptions = NULL; ssh_string pubkey0 = NULL; ssh_string privkeys = NULL; ssh_string comment = NULL; ssh_key key = NULL; uint8_t padding; cmp = strncmp(ptr, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN)); if (cmp != 0) { SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no header)"); goto out; } ptr += strlen(OPENSSH_HEADER_BEGIN); while(ptr[0] != '\0' && !isspace((int)ptr[0])) { ptr++; } end = strstr(ptr, OPENSSH_HEADER_END); if (end == NULL) { SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (no footer)"); goto out; } base64 = malloc(end - ptr + 1); if (base64 == NULL) { goto out; } for (i = 0; ptr < end; ptr++) { if (!isspace((int)ptr[0])) { base64[i] = ptr[0]; i++; } } base64[i] = '\0'; buffer = base64_to_bin(base64); SAFE_FREE(base64); if (buffer == NULL) { SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (base64 error)"); goto out; } rc = ssh_buffer_unpack(buffer, "PssSdSS", strlen(OPENSSH_AUTH_MAGIC) + 1, &magic, &ciphername, &kdfname, &kdfoptions, &nkeys, &pubkey0, &privkeys); if (rc == SSH_ERROR) { SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (unpack error)"); goto out; } cmp = strncmp(magic, OPENSSH_AUTH_MAGIC, strlen(OPENSSH_AUTH_MAGIC)); if (cmp != 0) { SSH_LOG(SSH_LOG_WARN, "Not an OpenSSH private key (bad magic)"); goto out; } SSH_LOG(SSH_LOG_INFO, "Opening OpenSSH private key: ciphername: %s, kdf: %s, nkeys: %d", ciphername, kdfname, nkeys); if (nkeys != 1) { SSH_LOG(SSH_LOG_WARN, "Opening OpenSSH private key: only 1 key supported (%d available)", nkeys); goto out; } /* If we are interested only in public key do not progress * to the key decryption later */ if (!private) { rc = ssh_pki_import_pubkey_blob(pubkey0, &key); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_WARN, "Failed to import public key blob"); } /* in either case we clean up here */ goto out; } rc = pki_private_key_decrypt(privkeys, passphrase, ciphername, kdfname, kdfoptions, auth_fn, auth_data); if (rc == SSH_ERROR) { goto out; } privkey_buffer = ssh_buffer_new(); if (privkey_buffer == NULL) { goto out; } ssh_buffer_set_secure(privkey_buffer); ssh_buffer_add_data(privkey_buffer, ssh_string_data(privkeys), ssh_string_len(privkeys)); rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2); if (rc == SSH_ERROR || checkint1 != checkint2) { SSH_LOG(SSH_LOG_WARN, "OpenSSH private key unpack error (correct password?)"); goto out; } rc = pki_openssh_import_privkey_blob(privkey_buffer, &key); if (rc == SSH_ERROR) { goto out; } comment = ssh_buffer_get_ssh_string(privkey_buffer); SAFE_FREE(comment); /* verify that the remaining data is correct padding */ for (i = 1; ssh_buffer_get_len(privkey_buffer) > 0; ++i) { ssh_buffer_get_u8(privkey_buffer, &padding); if (padding != i) { ssh_key_free(key); key = NULL; SSH_LOG(SSH_LOG_WARN, "Invalid padding"); goto out; } } out: if (buffer != NULL) { SSH_BUFFER_FREE(buffer); buffer = NULL; } if (privkey_buffer != NULL) { SSH_BUFFER_FREE(privkey_buffer); privkey_buffer = NULL; } SAFE_FREE(magic); SAFE_FREE(ciphername); SAFE_FREE(kdfname); SAFE_FREE(kdfoptions); SAFE_FREE(pubkey0); SAFE_FREE(privkeys); return key; } ssh_key ssh_pki_openssh_privkey_import(const char *text_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { return ssh_pki_openssh_import(text_key, passphrase, auth_fn, auth_data, true); } ssh_key ssh_pki_openssh_pubkey_import(const char *text_key) { return ssh_pki_openssh_import(text_key, NULL, NULL, NULL, false); } /** @internal * @brief exports a private key to a string blob. * @param[in] privkey private key to convert * @param[out] buffer buffer to write the blob in. * @returns SSH_OK on success * @warning only supports ed25519 key type at the moment. */ static int pki_openssh_export_privkey_blob(const ssh_key privkey, ssh_buffer buffer) { int rc; if (privkey->type != SSH_KEYTYPE_ED25519) { SSH_LOG(SSH_LOG_WARN, "Type %s not supported", privkey->type_c); return SSH_ERROR; } if (privkey->ed25519_privkey == NULL || privkey->ed25519_pubkey == NULL) { return SSH_ERROR; } rc = ssh_buffer_pack(buffer, "sdPdPP", privkey->type_c, (uint32_t)ED25519_KEY_LEN, (size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey, (uint32_t)(2 * ED25519_KEY_LEN), (size_t)ED25519_KEY_LEN, privkey->ed25519_privkey, (size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey); return rc; } /** @internal * @brief encrypts an ed25519 private key blob * */ static int pki_private_key_encrypt(ssh_buffer privkey_buffer, const char* passphrase, const char *ciphername, const char *kdfname, ssh_auth_callback auth_fn, void *auth_data, uint32_t rounds, ssh_string salt) { struct ssh_cipher_struct *ciphers = ssh_get_ciphertab(); struct ssh_cipher_struct cipher; uint8_t key_material[128] = {0}; size_t key_material_len; char passphrase_buffer[128] = {0}; int rc; int i; int cmp; cmp = strcmp(ciphername, "none"); if (cmp == 0){ /* no encryption required */ return SSH_OK; } for (i = 0; ciphers[i].name != NULL; i++) { cmp = strcmp(ciphername, ciphers[i].name); if (cmp == 0){ memcpy(&cipher, &ciphers[i], sizeof(cipher)); break; } } if (ciphers[i].name == NULL){ SSH_LOG(SSH_LOG_WARN, "Unsupported cipher %s", ciphername); return SSH_ERROR; } cmp = strcmp(kdfname, "bcrypt"); if (cmp != 0){ SSH_LOG(SSH_LOG_WARN, "Unsupported KDF %s", kdfname); return SSH_ERROR; } /* We need material for key (keysize bits / 8) and IV (blocksize) */ key_material_len = cipher.keysize/8 + cipher.blocksize; if (key_material_len > sizeof(key_material)){ SSH_LOG(SSH_LOG_WARN, "Key material too big"); return SSH_ERROR; } SSH_LOG(SSH_LOG_WARN, "Encryption: %d key, %d IV, %d rounds, %zu bytes salt", cipher.keysize/8, cipher.blocksize, rounds, ssh_string_len(salt)); if (passphrase == NULL){ if (auth_fn == NULL){ SSH_LOG(SSH_LOG_WARN, "No passphrase provided"); return SSH_ERROR; } rc = auth_fn("Passphrase", passphrase_buffer, sizeof(passphrase_buffer), 0, 0, auth_data); if (rc != SSH_OK){ return SSH_ERROR; } passphrase = passphrase_buffer; } rc = bcrypt_pbkdf(passphrase, strlen(passphrase), ssh_string_data(salt), ssh_string_len(salt), key_material, key_material_len, rounds); if (rc < 0){ return SSH_ERROR; } cipher.set_encrypt_key(&cipher, key_material, key_material + cipher.keysize/8); cipher.encrypt(&cipher, ssh_buffer_get(privkey_buffer), ssh_buffer_get(privkey_buffer), ssh_buffer_get_len(privkey_buffer)); ssh_cipher_clear(&cipher); explicit_bzero(passphrase_buffer, sizeof(passphrase_buffer)); return SSH_OK; } /** @internal * generate an OpenSSH private key (defined in PROTOCOL.key) and output it in text format. * @param privkey[in] private key to export * @returns an SSH string containing the text representation of the exported key. * @warning currently only supports ED25519 key types. */ ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_buffer buffer; ssh_string str = NULL; ssh_string pubkey_s=NULL; ssh_buffer privkey_buffer = NULL; uint32_t rnd; uint32_t rounds = 16; ssh_string salt=NULL; ssh_string kdf_options=NULL; int to_encrypt=0; unsigned char *b64; uint32_t str_len, len; uint8_t padding = 1; int ok; int rc; if (privkey == NULL) { return NULL; } if (privkey->type != SSH_KEYTYPE_ED25519){ SSH_LOG(SSH_LOG_WARN, "Unsupported key type %s", privkey->type_c); return NULL; } if (passphrase != NULL || auth_fn != NULL){ SSH_LOG(SSH_LOG_INFO, "Enabling encryption for private key export"); to_encrypt = 1; } buffer = ssh_buffer_new(); pubkey_s = pki_publickey_to_blob(privkey); if(buffer == NULL || pubkey_s == NULL){ goto error; } ok = ssh_get_random(&rnd, sizeof(rnd), 0); if (!ok) { goto error; } privkey_buffer = ssh_buffer_new(); if (privkey_buffer == NULL) { goto error; } /* checkint1 & 2 */ rc = ssh_buffer_pack(privkey_buffer, "dd", rnd, rnd); if (rc == SSH_ERROR){ goto error; } rc = pki_openssh_export_privkey_blob(privkey, privkey_buffer); if (rc == SSH_ERROR){ goto error; } /* comment */ rc = ssh_buffer_pack(privkey_buffer, "s", "" /* comment */); if (rc == SSH_ERROR){ goto error; } /* Add padding regardless encryption because it is expected * by OpenSSH tools. * XXX Using 16 B as we use only AES cipher below anyway. */ while (ssh_buffer_get_len(privkey_buffer) % 16 != 0) { rc = ssh_buffer_add_u8(privkey_buffer, padding); if (rc < 0) { goto error; } padding++; } if (to_encrypt){ ssh_buffer kdf_buf; kdf_buf = ssh_buffer_new(); if (kdf_buf == NULL) { goto error; } salt = ssh_string_new(16); if (salt == NULL){ SSH_BUFFER_FREE(kdf_buf); goto error; } ok = ssh_get_random(ssh_string_data(salt), 16, 0); if (!ok) { SSH_BUFFER_FREE(kdf_buf); goto error; } ssh_buffer_pack(kdf_buf, "Sd", salt, rounds); kdf_options = ssh_string_new(ssh_buffer_get_len(kdf_buf)); if (kdf_options == NULL){ SSH_BUFFER_FREE(kdf_buf); goto error; } memcpy(ssh_string_data(kdf_options), ssh_buffer_get(kdf_buf), ssh_buffer_get_len(kdf_buf)); SSH_BUFFER_FREE(kdf_buf); rc = pki_private_key_encrypt(privkey_buffer, passphrase, "aes128-cbc", "bcrypt", auth_fn, auth_data, rounds, salt); if (rc != SSH_OK){ goto error; } } else { kdf_options = ssh_string_new(0); } rc = ssh_buffer_pack(buffer, "PssSdSdP", (size_t)strlen(OPENSSH_AUTH_MAGIC) + 1, OPENSSH_AUTH_MAGIC, to_encrypt ? "aes128-cbc" : "none", /* ciphername */ to_encrypt ? "bcrypt" : "none", /* kdfname */ kdf_options, /* kdfoptions */ (uint32_t) 1, /* nkeys */ pubkey_s, (uint32_t)ssh_buffer_get_len(privkey_buffer), /* rest of buffer is a string */ (size_t)ssh_buffer_get_len(privkey_buffer), ssh_buffer_get(privkey_buffer)); if (rc != SSH_OK) { goto error; } b64 = bin_to_base64(ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); if (b64 == NULL){ goto error; } /* we can reuse the buffer */ ssh_buffer_reinit(buffer); rc = ssh_buffer_pack(buffer, "tttttt", OPENSSH_HEADER_BEGIN, "\n", b64, "\n", OPENSSH_HEADER_END, "\n"); explicit_bzero(b64, strlen((char *)b64)); SAFE_FREE(b64); if (rc != SSH_OK){ goto error; } str = ssh_string_new(ssh_buffer_get_len(buffer)); if (str == NULL){ goto error; } str_len = ssh_buffer_get_len(buffer); len = ssh_buffer_get_data(buffer, ssh_string_data(str), str_len); if (str_len != len) { SSH_STRING_FREE(str); str = NULL; } error: if (privkey_buffer != NULL) { void *bufptr = ssh_buffer_get(privkey_buffer); explicit_bzero(bufptr, ssh_buffer_get_len(privkey_buffer)); SSH_BUFFER_FREE(privkey_buffer); } SAFE_FREE(pubkey_s); SAFE_FREE(kdf_options); SAFE_FREE(salt); if (buffer != NULL) { SSH_BUFFER_FREE(buffer); } return str; } /** * @} */ ================================================ FILE: src/libssh/src/pki_crypto.c ================================================ /* * pki_crypto.c - PKI infrastructure using OpenSSL * * This file is part of the SSH Library * * Copyright (c) 2003-2009 by Aris Adamantiadis * Copyright (c) 2009-2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef _PKI_CRYPTO_H #define _PKI_CRYPTO_H #include "config.h" #include "libssh/priv.h" #include #include #include #include #include "libcrypto-compat.h" #ifdef HAVE_OPENSSL_EC_H #include #endif #ifdef HAVE_OPENSSL_ECDSA_H #include #endif #include "libssh/libssh.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/bignum.h" struct pem_get_password_struct { ssh_auth_callback fn; void *data; }; static int pem_get_password(char *buf, int size, int rwflag, void *userdata) { struct pem_get_password_struct *pgp = userdata; (void) rwflag; /* unused */ if (buf == NULL) { return 0; } memset(buf, '\0', size); if (pgp) { int rc; rc = pgp->fn("Passphrase for private key:", buf, size, 0, 0, pgp->data); if (rc == 0) { return strlen(buf); } } return 0; } #ifdef HAVE_OPENSSL_ECC static int pki_key_ecdsa_to_nid(EC_KEY *k) { const EC_GROUP *g = EC_KEY_get0_group(k); int nid; nid = EC_GROUP_get_curve_name(g); if (nid) { return nid; } return -1; } static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k) { int nid; nid = pki_key_ecdsa_to_nid(k); switch (nid) { case NID_X9_62_prime256v1: return SSH_KEYTYPE_ECDSA_P256; case NID_secp384r1: return SSH_KEYTYPE_ECDSA_P384; case NID_secp521r1: return SSH_KEYTYPE_ECDSA_P521; default: return SSH_KEYTYPE_UNKNOWN; } } const char *pki_key_ecdsa_nid_to_name(int nid) { switch (nid) { case NID_X9_62_prime256v1: return "ecdsa-sha2-nistp256"; case NID_secp384r1: return "ecdsa-sha2-nistp384"; case NID_secp521r1: return "ecdsa-sha2-nistp521"; default: break; } return "unknown"; } static const char *pki_key_ecdsa_nid_to_char(int nid) { switch (nid) { case NID_X9_62_prime256v1: return "nistp256"; case NID_secp384r1: return "nistp384"; case NID_secp521r1: return "nistp521"; default: break; } return "unknown"; } int pki_key_ecdsa_nid_from_name(const char *name) { if (strcmp(name, "nistp256") == 0) { return NID_X9_62_prime256v1; } else if (strcmp(name, "nistp384") == 0) { return NID_secp384r1; } else if (strcmp(name, "nistp521") == 0) { return NID_secp521r1; } return -1; } static ssh_string make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p) { ssh_string s; size_t len; len = EC_POINT_point2oct(g, p, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); if (len == 0) { return NULL; } s = ssh_string_new(len); if (s == NULL) { return NULL; } len = EC_POINT_point2oct(g, p, POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(s), ssh_string_len(s), NULL); if (len != ssh_string_len(s)) { SSH_STRING_FREE(s); return NULL; } return s; } int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) { EC_POINT *p = NULL; const EC_GROUP *g = NULL; int ok; BIGNUM *bexp = NULL; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return -1; } g = EC_KEY_get0_group(key->ecdsa); p = EC_POINT_new(g); if (p == NULL) { return -1; } ok = EC_POINT_oct2point(g, p, ssh_string_data(e), ssh_string_len(e), NULL); if (!ok) { EC_POINT_free(p); return -1; } /* EC_KEY_set_public_key duplicates p */ ok = EC_KEY_set_public_key(key->ecdsa, p); EC_POINT_free(p); if (!ok) { return -1; } bexp = ssh_make_string_bn(exp); if (bexp == NULL) { EC_KEY_free(key->ecdsa); return -1; } /* EC_KEY_set_private_key duplicates exp */ ok = EC_KEY_set_private_key(key->ecdsa, bexp); BN_free(bexp); if (!ok) { EC_KEY_free(key->ecdsa); return -1; } return 0; } int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { EC_POINT *p = NULL; const EC_GROUP *g = NULL; int ok; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return -1; } g = EC_KEY_get0_group(key->ecdsa); p = EC_POINT_new(g); if (p == NULL) { return -1; } ok = EC_POINT_oct2point(g, p, ssh_string_data(e), ssh_string_len(e), NULL); if (!ok) { EC_POINT_free(p); return -1; } /* EC_KEY_set_public_key duplicates p */ ok = EC_KEY_set_public_key(key->ecdsa, p); EC_POINT_free(p); if (!ok) { return -1; } return 0; } #endif ssh_key pki_key_dup(const ssh_key key, int demote) { ssh_key new; int rc; new = ssh_key_new(); if (new == NULL) { return NULL; } new->type = key->type; new->type_c = key->type_c; if (demote) { new->flags = SSH_KEY_FLAG_PUBLIC; } else { new->flags = key->flags; } switch (key->type) { case SSH_KEYTYPE_DSS: { const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; BIGNUM *np, *nq, *ng, *npub_key, *npriv_key; new->dsa = DSA_new(); if (new->dsa == NULL) { goto fail; } /* * p = public prime number * q = public 160-bit subprime, q | p-1 * g = public generator of subgroup * pub_key = public key y = g^x * priv_key = private key x */ DSA_get0_pqg(key->dsa, &p, &q, &g); np = BN_dup(p); nq = BN_dup(q); ng = BN_dup(g); if (np == NULL || nq == NULL || ng == NULL) { BN_free(np); BN_free(nq); BN_free(ng); goto fail; } /* Memory management of np, nq and ng is transferred to DSA object */ rc = DSA_set0_pqg(new->dsa, np, nq, ng); if (rc == 0) { BN_free(np); BN_free(nq); BN_free(ng); goto fail; } DSA_get0_key(key->dsa, &pub_key, &priv_key); npub_key = BN_dup(pub_key); if (npub_key == NULL) { goto fail; } /* Memory management of npubkey is transferred to DSA object */ rc = DSA_set0_key(new->dsa, npub_key, NULL); if (rc == 0) { goto fail; } if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { npriv_key = BN_dup(priv_key); if (npriv_key == NULL) { goto fail; } /* Memory management of npriv_key is transferred to DSA object */ rc = DSA_set0_key(new->dsa, NULL, npriv_key); if (rc == 0) { goto fail; } } break; } case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { const BIGNUM *n = NULL, *e = NULL, *d = NULL; BIGNUM *nn, *ne, *nd; new->rsa = RSA_new(); if (new->rsa == NULL) { goto fail; } /* * n = public modulus * e = public exponent * d = private exponent * p = secret prime factor * q = secret prime factor * dmp1 = d mod (p-1) * dmq1 = d mod (q-1) * iqmp = q^-1 mod p */ RSA_get0_key(key->rsa, &n, &e, &d); nn = BN_dup(n); ne = BN_dup(e); if (nn == NULL || ne == NULL) { BN_free(nn); BN_free(ne); goto fail; } /* Memory management of nn and ne is transferred to RSA object */ rc = RSA_set0_key(new->rsa, nn, ne, NULL); if (rc == 0) { BN_free(nn); BN_free(ne); goto fail; } if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp; nd = BN_dup(d); if (nd == NULL) { goto fail; } /* Memory management of nd is transferred to RSA object */ rc = RSA_set0_key(new->rsa, NULL, NULL, nd); if (rc == 0) { goto fail; } /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the * RSA operations are much faster when these values are available. */ RSA_get0_factors(key->rsa, &p, &q); if (p != NULL && q != NULL) { /* need to set both of them */ np = BN_dup(p); nq = BN_dup(q); if (np == NULL || nq == NULL) { BN_free(np); BN_free(nq); goto fail; } /* Memory management of np and nq is transferred to RSA object */ rc = RSA_set0_factors(new->rsa, np, nq); if (rc == 0) { BN_free(np); BN_free(nq); goto fail; } } RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp); if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) { ndmp1 = BN_dup(dmp1); ndmq1 = BN_dup(dmq1); niqmp = BN_dup(iqmp); if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) { BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp); goto fail; } /* Memory management of ndmp1, ndmq1 and niqmp is transferred * to RSA object */ rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp); if (rc == 0) { BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp); goto fail; } } } break; } case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_OPENSSL_ECC new->ecdsa_nid = key->ecdsa_nid; /* privkey -> pubkey */ if (demote && ssh_key_is_private(key)) { const EC_POINT *p; int ok; new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (new->ecdsa == NULL) { goto fail; } p = EC_KEY_get0_public_key(key->ecdsa); if (p == NULL) { goto fail; } ok = EC_KEY_set_public_key(new->ecdsa, p); if (!ok) { goto fail; } } else { new->ecdsa = EC_KEY_dup(key->ecdsa); } break; #endif case SSH_KEYTYPE_ED25519: rc = pki_ed25519_key_dup(new, key); if (rc != SSH_OK) { goto fail; } break; case SSH_KEYTYPE_UNKNOWN: default: ssh_key_free(new); return NULL; } return new; fail: ssh_key_free(new); return NULL; } int pki_key_generate_rsa(ssh_key key, int parameter){ BIGNUM *e; int rc; e = BN_new(); key->rsa = RSA_new(); BN_set_word(e, 65537); rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL); BN_free(e); if (rc <= 0 || key->rsa == NULL) return SSH_ERROR; return SSH_OK; } int pki_key_generate_dss(ssh_key key, int parameter){ int rc; #if OPENSSL_VERSION_NUMBER > 0x00908000L key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; } rc = DSA_generate_parameters_ex(key->dsa, parameter, NULL, /* seed */ 0, /* seed_len */ NULL, /* counter_ret */ NULL, /* h_ret */ NULL); /* cb */ if (rc != 1) { DSA_free(key->dsa); key->dsa = NULL; return SSH_ERROR; } #else key->dsa = DSA_generate_parameters(parameter, NULL, 0, NULL, NULL, NULL, NULL); if(key->dsa == NULL){ return SSH_ERROR; } #endif rc = DSA_generate_key(key->dsa); if (rc != 1){ DSA_free(key->dsa); key->dsa=NULL; return SSH_ERROR; } return SSH_OK; } #ifdef HAVE_OPENSSL_ECC int pki_key_generate_ecdsa(ssh_key key, int parameter) { int ok; switch (parameter) { case 384: key->ecdsa_nid = NID_secp384r1; key->type = SSH_KEYTYPE_ECDSA_P384; break; case 521: key->ecdsa_nid = NID_secp521r1; key->type = SSH_KEYTYPE_ECDSA_P521; break; case 256: key->ecdsa_nid = NID_X9_62_prime256v1; key->type = SSH_KEYTYPE_ECDSA_P256; break; default: SSH_LOG(SSH_LOG_WARN, "Invalid parameter %d for ECDSA key " "generation", parameter); return SSH_ERROR; } key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); if (key->ecdsa == NULL) { return SSH_ERROR; } ok = EC_KEY_generate_key(key->ecdsa); if (!ok) { EC_KEY_free(key->ecdsa); return SSH_ERROR; } EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE); return SSH_OK; } #endif int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { switch (k1->type) { case SSH_KEYTYPE_DSS: { const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2, *pub_key1, *pub_key2, *priv_key1, *priv_key2; if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { return 1; } DSA_get0_pqg(k1->dsa, &p1, &q1, &g1); DSA_get0_pqg(k2->dsa, &p2, &q2, &g2); if (bignum_cmp(p1, p2) != 0) { return 1; } if (bignum_cmp(q1, q2) != 0) { return 1; } if (bignum_cmp(g1, g2) != 0) { return 1; } DSA_get0_key(k1->dsa, &pub_key1, &priv_key1); DSA_get0_key(k2->dsa, &pub_key2, &priv_key2); if (bignum_cmp(pub_key1, pub_key2) != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (bignum_cmp(priv_key1, priv_key2) != 0) { return 1; } } break; } case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2; if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { return 1; } RSA_get0_key(k1->rsa, &n1, &e1, NULL); RSA_get0_key(k2->rsa, &n2, &e2, NULL); if (bignum_cmp(e1, e2) != 0) { return 1; } if (bignum_cmp(n1, n2) != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { RSA_get0_factors(k1->rsa, &p1, &q1); RSA_get0_factors(k2->rsa, &p2, &q2); if (bignum_cmp(p1, p2) != 0) { return 1; } if (bignum_cmp(q1, q2) != 0) { return 1; } } break; } case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_OPENSSL_ECC { const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa); const EC_POINT *p2 = EC_KEY_get0_public_key(k2->ecdsa); const EC_GROUP *g1 = EC_KEY_get0_group(k1->ecdsa); const EC_GROUP *g2 = EC_KEY_get0_group(k2->ecdsa); if (p1 == NULL || p2 == NULL) { return 1; } if (EC_GROUP_cmp(g1, g2, NULL) != 0) { return 1; } if (EC_POINT_cmp(g1, p1, p2, NULL) != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (bignum_cmp(EC_KEY_get0_private_key(k1->ecdsa), EC_KEY_get0_private_key(k2->ecdsa))) { return 1; } } break; } #endif case SSH_KEYTYPE_ED25519: /* ed25519 keys handled globaly */ case SSH_KEYTYPE_UNKNOWN: default: return 1; } return 0; } ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_string blob = NULL; BUF_MEM *buf = NULL; BIO *mem = NULL; EVP_PKEY *pkey = NULL; int rc; mem = BIO_new(BIO_s_mem()); if (mem == NULL) { return NULL; } switch (key->type) { case SSH_KEYTYPE_DSS: pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; } rc = EVP_PKEY_set1_DSA(pkey, key->dsa); break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; } rc = EVP_PKEY_set1_RSA(pkey, key->rsa); break; #ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: pkey = EVP_PKEY_new(); if (pkey == NULL) { goto err; } rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; #endif case SSH_KEYTYPE_ED25519: #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL, the input is the private key seed only, which means * the first half of the SSH private key (the second half is the * public key) */ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, (const uint8_t *)key->ed25519_privkey, ED25519_KEY_LEN); if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create ed25519 EVP_PKEY: %s", ERR_error_string(ERR_get_error(), NULL)); goto err; } /* Mark the operation as successful as for the other key types */ rc = 1; break; #else SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519"); goto err; #endif case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type); goto err; } if (rc != 1) { SSH_LOG(SSH_LOG_WARN, "Failed to initialize EVP_PKEY structure"); goto err; } if (passphrase == NULL) { struct pem_get_password_struct pgp = { auth_fn, auth_data }; rc = PEM_write_bio_PrivateKey(mem, pkey, NULL, /* cipher */ NULL, /* kstr */ 0, /* klen */ pem_get_password, &pgp); } else { rc = PEM_write_bio_PrivateKey(mem, pkey, EVP_aes_128_cbc(), NULL, /* kstr */ 0, /* klen */ NULL, /* auth_fn */ (void*) passphrase); } EVP_PKEY_free(pkey); pkey = NULL; if (rc != 1) { goto err; } BIO_get_mem_ptr(mem, &buf); blob = ssh_string_new(buf->length); if (blob == NULL) { goto err; } ssh_string_fill(blob, buf->data, buf->length); BIO_free(mem); return blob; err: EVP_PKEY_free(pkey); BIO_free(mem); return NULL; } ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { BIO *mem = NULL; DSA *dsa = NULL; RSA *rsa = NULL; #ifdef HAVE_OPENSSL_ED25519 uint8_t *ed25519 = NULL; #else ed25519_privkey *ed25519 = NULL; #endif ssh_key key = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; #ifdef HAVE_OPENSSL_ECC EC_KEY *ecdsa = NULL; #else void *ecdsa = NULL; #endif EVP_PKEY *pkey = NULL; mem = BIO_new_mem_buf((void*)b64_key, -1); if (passphrase == NULL) { if (auth_fn) { struct pem_get_password_struct pgp = { auth_fn, auth_data }; pkey = PEM_read_bio_PrivateKey(mem, NULL, pem_get_password, &pgp); } else { /* openssl uses its own callback to get the passphrase here */ pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL); } } else { pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, (void *) passphrase); } BIO_free(mem); if (pkey == NULL) { SSH_LOG(SSH_LOG_WARN, "Parsing private key: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } switch (EVP_PKEY_base_id(pkey)) { case EVP_PKEY_DSA: dsa = EVP_PKEY_get1_DSA(pkey); if (dsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Parsing private key: %s", ERR_error_string(ERR_get_error(),NULL)); goto fail; } type = SSH_KEYTYPE_DSS; break; case EVP_PKEY_RSA: rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Parsing private key: %s", ERR_error_string(ERR_get_error(),NULL)); goto fail; } type = SSH_KEYTYPE_RSA; break; case EVP_PKEY_EC: #ifdef HAVE_OPENSSL_ECC ecdsa = EVP_PKEY_get1_EC_KEY(pkey); if (ecdsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Parsing private key: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } /* pki_privatekey_type_from_string always returns P256 for ECDSA * keys, so we need to figure out the correct type here */ type = pki_key_ecdsa_to_key_type(ecdsa); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Invalid private key."); goto fail; } break; #endif #ifdef HAVE_OPENSSL_ED25519 case EVP_PKEY_ED25519: { size_t key_len; int evp_rc = 0; /* Get the key length */ evp_rc = EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get ed25519 raw private key length: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } if (key_len != ED25519_KEY_LEN) { goto fail; } ed25519 = malloc(key_len); if (ed25519 == NULL) { SSH_LOG(SSH_LOG_WARN, "Out of memory"); goto fail; } evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)ed25519, &key_len); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get ed25519 raw private key: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } type = SSH_KEYTYPE_ED25519; } break; #endif default: EVP_PKEY_free(pkey); SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", EVP_PKEY_base_id(pkey)); return NULL; } EVP_PKEY_free(pkey); key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; key->ecdsa = ecdsa; key->ed25519_privkey = ed25519; #ifdef HAVE_OPENSSL_ECC if (is_ecdsa_key_type(key->type)) { key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); } #endif return key; fail: EVP_PKEY_free(pkey); ssh_key_free(key); DSA_free(dsa); RSA_free(rsa); #ifdef HAVE_OPENSSL_ECC EC_KEY_free(ecdsa); #endif #ifdef HAVE_OPENSSL_ED25519 SAFE_FREE(ed25519); #endif return NULL; } int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey, ssh_string privkey) { int rc; BIGNUM *bp, *bq, *bg, *bpub_key, *bpriv_key; key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; } bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); bg = ssh_make_string_bn(g); bpub_key = ssh_make_string_bn(pubkey); bpriv_key = ssh_make_string_bn(privkey); if (bp == NULL || bq == NULL || bg == NULL || bpub_key == NULL) { goto fail; } /* Memory management of bp, qq and bg is transferred to DSA object */ rc = DSA_set0_pqg(key->dsa, bp, bq, bg); if (rc == 0) { goto fail; } /* Memory management of bpub_key and bpriv_key is transferred to DSA object */ rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key); if (rc == 0) { goto fail; } return SSH_OK; fail: DSA_free(key->dsa); return SSH_ERROR; } int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey) { int rc; BIGNUM *bp = NULL, *bq = NULL, *bg = NULL, *bpub_key = NULL; key->dsa = DSA_new(); if (key->dsa == NULL) { return SSH_ERROR; } bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); bg = ssh_make_string_bn(g); bpub_key = ssh_make_string_bn(pubkey); if (bp == NULL || bq == NULL || bg == NULL || bpub_key == NULL) { goto fail; } /* Memory management of bp, bq and bg is transferred to DSA object */ rc = DSA_set0_pqg(key->dsa, bp, bq, bg); if (rc == 0) { goto fail; } /* Memory management of npub_key is transferred to DSA object */ rc = DSA_set0_key(key->dsa, bpub_key, NULL); if (rc == 0) { goto fail; } return SSH_OK; fail: DSA_free(key->dsa); return SSH_ERROR; } int pki_privkey_build_rsa(ssh_key key, ssh_string n, ssh_string e, ssh_string d, UNUSED_PARAM(ssh_string iqmp), ssh_string p, ssh_string q) { int rc; BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq; key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; } bn = ssh_make_string_bn(n); be = ssh_make_string_bn(e); bd = ssh_make_string_bn(d); /*biqmp = ssh_make_string_bn(iqmp);*/ bp = ssh_make_string_bn(p); bq = ssh_make_string_bn(q); if (be == NULL || bn == NULL || bd == NULL || /*biqmp == NULL ||*/ bp == NULL || bq == NULL) { goto fail; } /* Memory management of be, bn and bd is transferred to RSA object */ rc = RSA_set0_key(key->rsa, bn, be, bd); if (rc == 0) { goto fail; } /* Memory management of bp and bq is transferred to RSA object */ rc = RSA_set0_factors(key->rsa, bp, bq); if (rc == 0) { goto fail; } /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA * operations are much faster when these values are available. * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html */ /* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL); TODO calculate missing crt_params */ return SSH_OK; fail: RSA_free(key->rsa); return SSH_ERROR; } int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { int rc; BIGNUM *be = NULL, *bn = NULL; key->rsa = RSA_new(); if (key->rsa == NULL) { return SSH_ERROR; } be = ssh_make_string_bn(e); bn = ssh_make_string_bn(n); if (be == NULL || bn == NULL) { goto fail; } /* Memory management of bn and be is transferred to RSA object */ rc = RSA_set0_key(key->rsa, bn, be, NULL); if (rc == 0) { goto fail; } return SSH_OK; fail: RSA_free(key->rsa); return SSH_ERROR; } ssh_string pki_publickey_to_blob(const ssh_key key) { ssh_buffer buffer; ssh_string type_s; ssh_string str = NULL; ssh_string e = NULL; ssh_string n = NULL; ssh_string p = NULL; ssh_string g = NULL; ssh_string q = NULL; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; } if (key->cert != NULL) { rc = ssh_buffer_add_buffer(buffer, key->cert); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } goto makestring; } type_s = ssh_string_from_char(key->type_c); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } switch (key->type) { case SSH_KEYTYPE_DSS: { const BIGNUM *bp, *bq, *bg, *bpub_key; DSA_get0_pqg(key->dsa, &bp, &bq, &bg); p = ssh_make_bignum_string((BIGNUM *)bp); if (p == NULL) { goto fail; } q = ssh_make_bignum_string((BIGNUM *)bq); if (q == NULL) { goto fail; } g = ssh_make_bignum_string((BIGNUM *)bg); if (g == NULL) { goto fail; } DSA_get0_key(key->dsa, &bpub_key, NULL); n = ssh_make_bignum_string((BIGNUM *)bpub_key); if (n == NULL) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, p) < 0) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, q) < 0) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, g) < 0) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, n) < 0) { goto fail; } ssh_string_burn(p); SSH_STRING_FREE(p); p = NULL; ssh_string_burn(g); SSH_STRING_FREE(g); g = NULL; ssh_string_burn(q); SSH_STRING_FREE(q); q = NULL; ssh_string_burn(n); SSH_STRING_FREE(n); n = NULL; break; } case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { const BIGNUM *be, *bn; RSA_get0_key(key->rsa, &bn, &be, NULL); e = ssh_make_bignum_string((BIGNUM *)be); if (e == NULL) { goto fail; } n = ssh_make_bignum_string((BIGNUM *)bn); if (n == NULL) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, e) < 0) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, n) < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; ssh_string_burn(n); SSH_STRING_FREE(n); n = NULL; break; } case SSH_KEYTYPE_ED25519: rc = pki_ed25519_public_key_to_blob(buffer, key); if (rc == SSH_ERROR){ goto fail; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_OPENSSL_ECC type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), EC_KEY_get0_public_key(key->ecdsa)); if (e == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, e); if (rc < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; break; #endif case SSH_KEYTYPE_UNKNOWN: default: goto fail; } makestring: str = ssh_string_new(ssh_buffer_get_len(buffer)); if (str == NULL) { goto fail; } rc = ssh_string_fill(str, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); if (rc < 0) { goto fail; } SSH_BUFFER_FREE(buffer); return str; fail: SSH_BUFFER_FREE(buffer); ssh_string_burn(str); SSH_STRING_FREE(str); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(n); SSH_STRING_FREE(n); return NULL; } static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig) { char buffer[40] = { 0 }; ssh_string sig_blob = NULL; const BIGNUM *pr = NULL, *ps = NULL; ssh_string r = NULL; int r_len, r_offset_in, r_offset_out; ssh_string s = NULL; int s_len, s_offset_in, s_offset_out; const unsigned char *raw_sig_data = NULL; size_t raw_sig_len; DSA_SIG *dsa_sig; if (sig == NULL || sig->raw_sig == NULL) { return NULL; } raw_sig_data = ssh_string_data(sig->raw_sig); if (raw_sig_data == NULL) { return NULL; } raw_sig_len = ssh_string_len(sig->raw_sig); dsa_sig = d2i_DSA_SIG(NULL, &raw_sig_data, raw_sig_len); if (dsa_sig == NULL) { return NULL; } DSA_SIG_get0(dsa_sig, &pr, &ps); if (pr == NULL || ps == NULL) { goto error; } r = ssh_make_bignum_string((BIGNUM *)pr); if (r == NULL) { goto error; } s = ssh_make_bignum_string((BIGNUM *)ps); if (s == NULL) { goto error; } r_len = ssh_string_len(r); r_offset_in = (r_len > 20) ? (r_len - 20) : 0; r_offset_out = (r_len < 20) ? (20 - r_len) : 0; s_len = ssh_string_len(s); s_offset_in = (s_len > 20) ? (s_len - 20) : 0; s_offset_out = (s_len < 20) ? (20 - s_len) : 0; memcpy(buffer + r_offset_out, ((char *)ssh_string_data(r)) + r_offset_in, r_len - r_offset_in); memcpy(buffer + 20 + s_offset_out, ((char *)ssh_string_data(s)) + s_offset_in, s_len - s_offset_in); DSA_SIG_free(dsa_sig); SSH_STRING_FREE(r); SSH_STRING_FREE(s); sig_blob = ssh_string_new(40); if (sig_blob == NULL) { return NULL; } ssh_string_fill(sig_blob, buffer, 40); return sig_blob; error: DSA_SIG_free(dsa_sig); SSH_STRING_FREE(r); SSH_STRING_FREE(s); return NULL; } static ssh_string pki_ecdsa_signature_to_blob(const ssh_signature sig) { ssh_string r = NULL; ssh_string s = NULL; ssh_buffer buf = NULL; ssh_string sig_blob = NULL; const BIGNUM *pr = NULL, *ps = NULL; const unsigned char *raw_sig_data = NULL; size_t raw_sig_len; ECDSA_SIG *ecdsa_sig; int rc; if (sig == NULL || sig->raw_sig == NULL) { return NULL; } raw_sig_data = ssh_string_data(sig->raw_sig); if (raw_sig_data == NULL) { return NULL; } raw_sig_len = ssh_string_len(sig->raw_sig); ecdsa_sig = d2i_ECDSA_SIG(NULL, &raw_sig_data, raw_sig_len); if (ecdsa_sig == NULL) { return NULL; } ECDSA_SIG_get0(ecdsa_sig, &pr, &ps); if (pr == NULL || ps == NULL) { goto error; } r = ssh_make_bignum_string((BIGNUM *)pr); if (r == NULL) { goto error; } s = ssh_make_bignum_string((BIGNUM *)ps); if (s == NULL) { goto error; } buf = ssh_buffer_new(); if (buf == NULL) { goto error; } rc = ssh_buffer_add_ssh_string(buf, r); if (rc < 0) { goto error; } rc = ssh_buffer_add_ssh_string(buf, s); if (rc < 0) { goto error; } sig_blob = ssh_string_new(ssh_buffer_get_len(buf)); if (sig_blob == NULL) { goto error; } ssh_string_fill(sig_blob, ssh_buffer_get(buf), ssh_buffer_get_len(buf)); SSH_STRING_FREE(r); SSH_STRING_FREE(s); ECDSA_SIG_free(ecdsa_sig); SSH_BUFFER_FREE(buf); return sig_blob; error: SSH_STRING_FREE(r); SSH_STRING_FREE(s); ECDSA_SIG_free(ecdsa_sig); SSH_BUFFER_FREE(buf); return NULL; } ssh_string pki_signature_to_blob(const ssh_signature sig) { ssh_string sig_blob = NULL; switch(sig->type) { case SSH_KEYTYPE_DSS: sig_blob = pki_dsa_signature_to_blob(sig); break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: sig_blob = ssh_string_copy(sig->raw_sig); break; case SSH_KEYTYPE_ED25519: sig_blob = pki_ed25519_signature_to_blob(sig); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_OPENSSL_ECC sig_blob = pki_ecdsa_signature_to_blob(sig); break; #endif default: case SSH_KEYTYPE_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", sig->type_c); return NULL; } return sig_blob; } static int pki_signature_from_rsa_blob(const ssh_key pubkey, const ssh_string sig_blob, ssh_signature sig) { uint32_t pad_len = 0; char *blob_orig = NULL; char *blob_padded_data = NULL; ssh_string sig_blob_padded = NULL; size_t rsalen = 0; size_t len = ssh_string_len(sig_blob); if (pubkey->rsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); goto errout; } rsalen = RSA_size(pubkey->rsa); if (len > rsalen) { SSH_LOG(SSH_LOG_WARN, "Signature is too big: %lu > %lu", (unsigned long)len, (unsigned long)rsalen); goto errout; } #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len); ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); #endif if (len == rsalen) { sig->raw_sig = ssh_string_copy(sig_blob); } else { /* pad the blob to the expected rsalen size */ SSH_LOG(SSH_LOG_DEBUG, "RSA signature len %lu < %lu", (unsigned long)len, (unsigned long)rsalen); pad_len = rsalen - len; sig_blob_padded = ssh_string_new(rsalen); if (sig_blob_padded == NULL) { goto errout; } blob_padded_data = (char *) ssh_string_data(sig_blob_padded); blob_orig = (char *) ssh_string_data(sig_blob); if (blob_padded_data == NULL || blob_orig == NULL) { goto errout; } /* front-pad the buffer with zeroes */ explicit_bzero(blob_padded_data, pad_len); /* fill the rest with the actual signature blob */ memcpy(blob_padded_data + pad_len, blob_orig, len); sig->raw_sig = sig_blob_padded; } return SSH_OK; errout: SSH_STRING_FREE(sig_blob_padded); return SSH_ERROR; } static int pki_signature_from_dsa_blob(UNUSED_PARAM(const ssh_key pubkey), const ssh_string sig_blob, ssh_signature sig) { DSA_SIG *dsa_sig = NULL; BIGNUM *pr = NULL, *ps = NULL; ssh_string r; ssh_string s; size_t len; int raw_sig_len = 0; unsigned char *raw_sig_data = NULL; unsigned char *temp_raw_sig = NULL; int rc; len = ssh_string_len(sig_blob); /* 40 is the dual signature blob len. */ if (len != 40) { SSH_LOG(SSH_LOG_WARN, "Signature has wrong size: %lu", (unsigned long)len); goto error; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("r", ssh_string_data(sig_blob), 20); ssh_log_hexdump("s", (unsigned char *)ssh_string_data(sig_blob) + 20, 20); #endif r = ssh_string_new(20); if (r == NULL) { goto error; } ssh_string_fill(r, ssh_string_data(sig_blob), 20); pr = ssh_make_string_bn(r); ssh_string_burn(r); SSH_STRING_FREE(r); if (pr == NULL) { goto error; } s = ssh_string_new(20); if (s == NULL) { goto error; } ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20); ps = ssh_make_string_bn(s); ssh_string_burn(s); SSH_STRING_FREE(s); if (ps == NULL) { goto error; } dsa_sig = DSA_SIG_new(); if (dsa_sig == NULL) { goto error; } /* Memory management of pr and ps is transferred to DSA signature * object */ rc = DSA_SIG_set0(dsa_sig, pr, ps); if (rc == 0) { goto error; } ps = NULL; pr = NULL; /* Get the expected size of the buffer */ rc = i2d_DSA_SIG(dsa_sig, NULL); if (rc <= 0) { goto error; } raw_sig_len = rc; raw_sig_data = (unsigned char *)calloc(1, raw_sig_len); if (raw_sig_data == NULL) { goto error; } temp_raw_sig = raw_sig_data; /* It is necessary to use a temporary pointer as i2d_* "advances" the * pointer */ raw_sig_len = i2d_DSA_SIG(dsa_sig, &temp_raw_sig); if (raw_sig_len <= 0) { goto error; } sig->raw_sig = ssh_string_new(raw_sig_len); if (sig->raw_sig == NULL) { explicit_bzero(raw_sig_data, raw_sig_len); goto error; } rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len); if (rc < 0) { explicit_bzero(raw_sig_data, raw_sig_len); goto error; } explicit_bzero(raw_sig_data, raw_sig_len); SAFE_FREE(raw_sig_data); DSA_SIG_free(dsa_sig); return SSH_OK; error: bignum_safe_free(ps); bignum_safe_free(pr); SAFE_FREE(raw_sig_data); DSA_SIG_free(dsa_sig); return SSH_ERROR; } static int pki_signature_from_ecdsa_blob(UNUSED_PARAM(const ssh_key pubkey), const ssh_string sig_blob, ssh_signature sig) { ECDSA_SIG *ecdsa_sig = NULL; BIGNUM *pr = NULL, *ps = NULL; ssh_string r; ssh_string s; ssh_buffer buf = NULL; uint32_t rlen; unsigned char *raw_sig_data = NULL; unsigned char *temp_raw_sig = NULL; size_t raw_sig_len = 0; int rc; /* build ecdsa signature */ buf = ssh_buffer_new(); if (buf == NULL) { return SSH_ERROR; } rc = ssh_buffer_add_data(buf, ssh_string_data(sig_blob), ssh_string_len(sig_blob)); if (rc < 0) { goto error; } r = ssh_buffer_get_ssh_string(buf); if (r == NULL) { goto error; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r)); #endif pr = ssh_make_string_bn(r); ssh_string_burn(r); SSH_STRING_FREE(r); if (pr == NULL) { goto error; } s = ssh_buffer_get_ssh_string(buf); rlen = ssh_buffer_get_len(buf); SSH_BUFFER_FREE(buf); if (s == NULL) { goto error; } if (rlen != 0) { ssh_string_burn(s); SSH_STRING_FREE(s); SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner " "sigblob: %lu", (unsigned long)rlen); goto error; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s)); #endif ps = ssh_make_string_bn(s); ssh_string_burn(s); SSH_STRING_FREE(s); if (ps == NULL) { goto error; } ecdsa_sig = ECDSA_SIG_new(); if (ecdsa_sig == NULL) { goto error; } /* Memory management of pr and ps is transferred to * ECDSA signature object */ rc = ECDSA_SIG_set0(ecdsa_sig, pr, ps); if (rc == 0) { goto error; } pr = NULL; ps = NULL; /* Get the expected size of the buffer */ rc = i2d_ECDSA_SIG(ecdsa_sig, NULL); if (rc <= 0) { goto error; } raw_sig_len = rc; raw_sig_data = (unsigned char *)calloc(1, raw_sig_len); if (raw_sig_data == NULL) { goto error; } temp_raw_sig = raw_sig_data; /* It is necessary to use a temporary pointer as i2d_* "advances" the * pointer */ rc = i2d_ECDSA_SIG(ecdsa_sig, &temp_raw_sig); if (rc <= 0) { goto error; } sig->raw_sig = ssh_string_new(raw_sig_len); if (sig->raw_sig == NULL) { explicit_bzero(raw_sig_data, raw_sig_len); goto error; } rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len); if (rc < 0) { explicit_bzero(raw_sig_data, raw_sig_len); goto error; } explicit_bzero(raw_sig_data, raw_sig_len); SAFE_FREE(raw_sig_data); ECDSA_SIG_free(ecdsa_sig); return SSH_OK; error: SSH_BUFFER_FREE(buf); bignum_safe_free(ps); bignum_safe_free(pr); SAFE_FREE(raw_sig_data); if (ecdsa_sig != NULL) { ECDSA_SIG_free(ecdsa_sig); } return SSH_ERROR; } ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string sig_blob, enum ssh_keytypes_e type, enum ssh_digest_e hash_type) { ssh_signature sig; int rc; if (ssh_key_type_plain(pubkey->type) != type) { SSH_LOG(SSH_LOG_WARN, "Incompatible public key provided (%d) expecting (%d)", type, pubkey->type); return NULL; } sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = type; sig->type_c = ssh_key_signature_to_char(type, hash_type); sig->hash_type = hash_type; switch(type) { case SSH_KEYTYPE_DSS: rc = pki_signature_from_dsa_blob(pubkey, sig_blob, sig); if (rc != SSH_OK) { goto error; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: rc = pki_signature_from_rsa_blob(pubkey, sig_blob, sig); if (rc != SSH_OK) { goto error; } break; case SSH_KEYTYPE_ED25519: rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc != SSH_OK){ goto error; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: #ifdef HAVE_OPENSSL_ECC rc = pki_signature_from_ecdsa_blob(pubkey, sig_blob, sig); if (rc != SSH_OK) { goto error; } break; #endif default: case SSH_KEYTYPE_UNKNOWN: SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); goto error; } return sig; error: ssh_signature_free(sig); return NULL; } static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type) { const EVP_MD *md = NULL; switch (hash_type) { case SSH_DIGEST_SHA256: md = EVP_sha256(); break; case SSH_DIGEST_SHA384: md = EVP_sha384(); break; case SSH_DIGEST_SHA512: md = EVP_sha512(); break; case SSH_DIGEST_SHA1: md = EVP_sha1(); break; case SSH_DIGEST_AUTO: md = NULL; break; default: SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d", hash_type); return NULL; } return md; } static EVP_PKEY *pki_key_to_pkey(ssh_key key) { EVP_PKEY *pkey = NULL; switch(key->type) { case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS_CERT01: if (key->dsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa"); goto error; } pkey = EVP_PKEY_new(); if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); return NULL; } EVP_PKEY_set1_DSA(pkey, key->dsa); break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_RSA_CERT01: if (key->rsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa"); goto error; } pkey = EVP_PKEY_new(); if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); return NULL; } EVP_PKEY_set1_RSA(pkey, key->rsa); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: # if defined(HAVE_OPENSSL_ECC) if (key->ecdsa == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa"); goto error; } pkey = EVP_PKEY_new(); if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); return NULL; } EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; # endif case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519_CERT01: # if defined(HAVE_OPENSSL_ED25519) if (ssh_key_is_private(key)) { if (key->ed25519_privkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_privkey"); goto error; } /* In OpenSSL, the input is the private key seed only, which means * the first half of the SSH private key (the second half is the * public key). Both keys have the same length (32 bytes) */ pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, (const uint8_t *)key->ed25519_privkey, ED25519_KEY_LEN); } else { if (key->ed25519_pubkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "NULL key->ed25519_pubkey"); goto error; } pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, (const uint8_t *)key->ed25519_pubkey, ED25519_KEY_LEN); } if (pkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create ed25519 EVP_PKEY: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } break; #endif case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_TRACE, "Unknown private key algorithm for type: %d", key->type); goto error; } return pkey; error: EVP_PKEY_free(pkey); return NULL; } /** * @internal * * @brief Sign the given input data. The digest of to be signed is calculated * internally as necessary. * * @param[in] privkey The private key to be used for signing. * @param[in] hash_type The digest algorithm to be used. * @param[in] input The data to be signed. * @param[in] input_len The length of the data to be signed. * * @return a newly allocated ssh_signature or NULL on error. */ ssh_signature pki_sign_data(const ssh_key privkey, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { const EVP_MD *md = NULL; EVP_MD_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; unsigned char *raw_sig_data = NULL; size_t raw_sig_len; ssh_signature sig = NULL; int rc; if (privkey == NULL || !ssh_key_is_private(privkey) || input == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_sign_data()"); return NULL; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(privkey, hash_type); if (rc != SSH_OK) { return NULL; } #ifndef HAVE_OPENSSL_ED25519 if (privkey->type == SSH_KEYTYPE_ED25519 || privkey->type == SSH_KEYTYPE_ED25519_CERT01) { return pki_do_sign_hash(privkey, input, input_len, hash_type); } #endif /* Set hash algorithm to be used */ md = pki_digest_to_md(hash_type); if (md == NULL) { if (hash_type != SSH_DIGEST_AUTO) { return NULL; } } /* Setup private key EVP_PKEY */ pkey = pki_key_to_pkey(privkey); if (pkey == NULL) { return NULL; } /* Allocate buffer for signature */ raw_sig_len = (size_t)EVP_PKEY_size(pkey); raw_sig_data = (unsigned char *)malloc(raw_sig_len); if (raw_sig_data == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); goto out; } /* Create the context */ ctx = EVP_MD_CTX_create(); if (ctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Out of memory"); goto out; } /* Sign the data */ rc = EVP_DigestSignInit(ctx, NULL, md, NULL, pkey); if (rc != 1){ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignInit() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } #ifdef HAVE_OPENSSL_EVP_DIGESTSIGN rc = EVP_DigestSign(ctx, raw_sig_data, &raw_sig_len, input, input_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSign() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } #else rc = EVP_DigestSignUpdate(ctx, input, input_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignUpdate() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } rc = EVP_DigestSignFinal(ctx, raw_sig_data, &raw_sig_len); if (rc != 1) { SSH_LOG(SSH_LOG_TRACE, "EVP_DigestSignFinal() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } #endif #ifdef DEBUG_CRYPTO ssh_log_hexdump("Generated signature", raw_sig_data, raw_sig_len); #endif /* Allocate and fill output signature */ sig = ssh_signature_new(); if (sig == NULL) { goto out; } sig->raw_sig = ssh_string_new(raw_sig_len); if (sig->raw_sig == NULL) { ssh_signature_free(sig); sig = NULL; goto out; } rc = ssh_string_fill(sig->raw_sig, raw_sig_data, raw_sig_len); if (rc < 0) { ssh_signature_free(sig); sig = NULL; goto out; } sig->type = privkey->type; sig->hash_type = hash_type; sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type); out: if (ctx != NULL) { EVP_MD_CTX_free(ctx); } if (raw_sig_data != NULL) { explicit_bzero(raw_sig_data, raw_sig_len); } SAFE_FREE(raw_sig_data); if (pkey != NULL) { EVP_PKEY_free(pkey); } return sig; } /** * @internal * * @brief Verify the signature of a given input. The digest of the input is * calculated internally as necessary. * * @param[in] signature The signature to be verified. * @param[in] pubkey The public key used to verify the signature. * @param[in] input The signed data. * @param[in] input_len The length of the signed data. * * @return SSH_OK if the signature is valid; SSH_ERROR otherwise. */ int pki_verify_data_signature(ssh_signature signature, const ssh_key pubkey, const unsigned char *input, size_t input_len) { const EVP_MD *md = NULL; EVP_MD_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; unsigned char *raw_sig_data = NULL; unsigned int raw_sig_len; int rc = SSH_ERROR; int evp_rc; if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || signature == NULL || (signature->raw_sig == NULL #ifndef HAVE_OPENSSL_ED25519 && signature->ed25519_sig == NULL #endif )) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_verify_data_signature()"); return SSH_ERROR; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); if (rc != SSH_OK) { return SSH_ERROR; } #ifndef HAVE_OPENSSL_ED25519 if (pubkey->type == SSH_KEYTYPE_ED25519 || pubkey->type == SSH_KEYTYPE_ED25519_CERT01) { return pki_ed25519_verify(pubkey, signature, input, input_len); } #endif /* Get the signature to be verified */ raw_sig_data = ssh_string_data(signature->raw_sig); raw_sig_len = ssh_string_len(signature->raw_sig); if (raw_sig_data == NULL) { return SSH_ERROR; } /* Set hash algorithm to be used */ md = pki_digest_to_md(signature->hash_type); if (md == NULL) { if (signature->hash_type != SSH_DIGEST_AUTO) { return SSH_ERROR; } } /* Setup public key EVP_PKEY */ pkey = pki_key_to_pkey(pubkey); if (pkey == NULL) { return SSH_ERROR; } /* Create the context */ ctx = EVP_MD_CTX_create(); if (ctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create EVP_MD_CTX: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } /* Verify the signature */ evp_rc = EVP_DigestVerifyInit(ctx, NULL, md, NULL, pkey); if (evp_rc != 1){ SSH_LOG(SSH_LOG_TRACE, "EVP_DigestVerifyInit() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } #ifdef HAVE_OPENSSL_EVP_DIGESTVERIFY evp_rc = EVP_DigestVerify(ctx, raw_sig_data, raw_sig_len, input, input_len); #else evp_rc = EVP_DigestVerifyUpdate(ctx, input, input_len); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "EVP_DigestVerifyUpdate() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto out; } evp_rc = EVP_DigestVerifyFinal(ctx, raw_sig_data, raw_sig_len); #endif if (evp_rc == 1) { SSH_LOG(SSH_LOG_TRACE, "Signature valid"); rc = SSH_OK; } else { SSH_LOG(SSH_LOG_TRACE, "Signature invalid: %s", ERR_error_string(ERR_get_error(), NULL)); rc = SSH_ERROR; } out: if (ctx != NULL) { EVP_MD_CTX_free(ctx); } if (pkey != NULL) { EVP_PKEY_free(pkey); } return rc; } #ifdef HAVE_OPENSSL_ED25519 int pki_key_generate_ed25519(ssh_key key) { int evp_rc; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey = NULL; size_t privkey_len = ED25519_KEY_LEN; size_t pubkey_len = ED25519_KEY_LEN; if (key == NULL) { return SSH_ERROR; } pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); if (pctx == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to create ed25519 EVP_PKEY_CTX: %s", ERR_error_string(ERR_get_error(), NULL)); goto error; } evp_rc = EVP_PKEY_keygen_init(pctx); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to initialize ed25519 key generation: %s", ERR_error_string(ERR_get_error(), NULL)); goto error; } evp_rc = EVP_PKEY_keygen(pctx, &pkey); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to generate ed25519 key: %s", ERR_error_string(ERR_get_error(), NULL)); goto error; } key->ed25519_privkey = malloc(ED25519_KEY_LEN); if (key->ed25519_privkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to allocate memory for ed25519 private key"); goto error; } key->ed25519_pubkey = malloc(ED25519_KEY_LEN); if (key->ed25519_pubkey == NULL) { SSH_LOG(SSH_LOG_TRACE, "Failed to allocate memory for ed25519 public key"); goto error; } evp_rc = EVP_PKEY_get_raw_private_key(pkey, (uint8_t *)key->ed25519_privkey, &privkey_len); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get ed25519 raw private key: %s", ERR_error_string(ERR_get_error(), NULL)); goto error; } evp_rc = EVP_PKEY_get_raw_public_key(pkey, (uint8_t *)key->ed25519_pubkey, &pubkey_len); if (evp_rc != 1) { SSH_LOG(SSH_LOG_TRACE, "Failed to get ed25519 raw public key: %s", ERR_error_string(ERR_get_error(), NULL)); goto error; } EVP_PKEY_CTX_free(pctx); EVP_PKEY_free(pkey); return SSH_OK; error: if (pctx != NULL) { EVP_PKEY_CTX_free(pctx); } if (pkey != NULL) { EVP_PKEY_free(pkey); } SAFE_FREE(key->ed25519_privkey); SAFE_FREE(key->ed25519_pubkey); return SSH_ERROR; } #else ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type) { ssh_signature sig = NULL; int rc; sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = privkey->type; sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type); sig->hash_type = hash_type; switch(privkey->type) { case SSH_KEYTYPE_ED25519: rc = pki_ed25519_sign(privkey, sig, hash, hlen); if (rc != SSH_OK) { ssh_signature_free(sig); return NULL; } break; default: ssh_signature_free(sig); return NULL; } return sig; } #endif /* HAVE_OPENSSL_ED25519 */ #endif /* _PKI_CRYPTO_H */ ================================================ FILE: src/libssh/src/pki_ed25519.c ================================================ /* * pki_ed25519 .c - PKI infrastructure using ed25519 * * This file is part of the SSH Library * * Copyright (c) 2014 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/ed25519.h" #include "libssh/buffer.h" int pki_key_generate_ed25519(ssh_key key) { int rc; key->ed25519_privkey = malloc(sizeof (ed25519_privkey)); if (key->ed25519_privkey == NULL) { goto error; } key->ed25519_pubkey = malloc(sizeof (ed25519_pubkey)); if (key->ed25519_pubkey == NULL) { goto error; } rc = crypto_sign_ed25519_keypair(*key->ed25519_pubkey, *key->ed25519_privkey); if (rc != 0) { goto error; } return SSH_OK; error: SAFE_FREE(key->ed25519_privkey); SAFE_FREE(key->ed25519_pubkey); return SSH_ERROR; } int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig, const unsigned char *hash, size_t hlen) { int rc; uint8_t *buffer; uint64_t dlen = 0; buffer = malloc(hlen + ED25519_SIG_LEN); if (buffer == NULL) { return SSH_ERROR; } rc = crypto_sign_ed25519(buffer, &dlen, hash, hlen, *privkey->ed25519_privkey); if (rc != 0) { goto error; } /* This shouldn't happen */ if (dlen - hlen != ED25519_SIG_LEN) { goto error; } sig->ed25519_sig = malloc(ED25519_SIG_LEN); if (sig->ed25519_sig == NULL) { goto error; } memcpy(sig->ed25519_sig, buffer, ED25519_SIG_LEN); SAFE_FREE(buffer); return SSH_OK; error: SAFE_FREE(buffer); return SSH_ERROR; } int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig, const unsigned char *hash, size_t hlen) { uint64_t mlen = 0; uint8_t *buffer; uint8_t *buffer2; int rc; if (pubkey == NULL || sig == NULL || hash == NULL || sig->ed25519_sig == NULL) { return SSH_ERROR; } buffer = malloc(hlen + ED25519_SIG_LEN); if (buffer == NULL) { return SSH_ERROR; } buffer2 = malloc(hlen + ED25519_SIG_LEN); if (buffer2 == NULL) { goto error; } memcpy(buffer, sig->ed25519_sig, ED25519_SIG_LEN); memcpy(buffer + ED25519_SIG_LEN, hash, hlen); rc = crypto_sign_ed25519_open(buffer2, &mlen, buffer, hlen + ED25519_SIG_LEN, *pubkey->ed25519_pubkey); explicit_bzero(buffer, hlen + ED25519_SIG_LEN); explicit_bzero(buffer2, hlen); SAFE_FREE(buffer); SAFE_FREE(buffer2); if (rc == 0) { return SSH_OK; } else { return SSH_ERROR; } error: SAFE_FREE(buffer); SAFE_FREE(buffer2); return SSH_ERROR; } ================================================ FILE: src/libssh/src/pki_ed25519_common.c ================================================ /* * pki_ed25519_common.c - Common ed25519 functions * * This file is part of the SSH Library * * Copyright (c) 2014 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/buffer.h" int pki_privkey_build_ed25519(ssh_key key, ssh_string pubkey, ssh_string privkey) { if (ssh_string_len(pubkey) != ED25519_KEY_LEN || ssh_string_len(privkey) != (2 * ED25519_KEY_LEN)) { SSH_LOG(SSH_LOG_WARN, "Invalid ed25519 key len"); return SSH_ERROR; } #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL implementation, the private key is the original private seed, * without the public key. */ key->ed25519_privkey = malloc(ED25519_KEY_LEN); #else /* In the internal implementation, the private key is the concatenation of * the private seed with the public key. */ key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN); #endif if (key->ed25519_privkey == NULL) { goto error; } key->ed25519_pubkey = malloc(ED25519_KEY_LEN); if (key->ed25519_pubkey == NULL) { goto error; } #ifdef HAVE_OPENSSL_ED25519 memcpy(key->ed25519_privkey, ssh_string_data(privkey), ED25519_KEY_LEN); #else memcpy(key->ed25519_privkey, ssh_string_data(privkey), 2 * ED25519_KEY_LEN); #endif memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN); return SSH_OK; error: SAFE_FREE(key->ed25519_privkey); SAFE_FREE(key->ed25519_pubkey); return SSH_ERROR; } /** * @internal * * @brief Compare ed25519 keys if they are equal. * * @param[in] k1 The first key to compare. * * @param[in] k2 The second key to compare. * * @param[in] what What part or type of the key do you want to compare. * * @return 0 if equal, 1 if not. */ int pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { int cmp; switch(what) { case SSH_KEY_CMP_PRIVATE: if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) { return 1; } #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL implementation, the private key is the original private * seed, without the public key. */ cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_KEY_LEN); #else /* In the internal implementation, the private key is the concatenation * of the private seed with the public key. */ cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, 2 * ED25519_KEY_LEN); #endif if (cmp != 0) { return 1; } FALL_THROUGH; case SSH_KEY_CMP_PUBLIC: if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) { return 1; } cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_KEY_LEN); if (cmp != 0) { return 1; } } return 0; } /** * @internal * * @brief Duplicate an Ed25519 key * * @param[out] new Pre-initialized ssh_key structure * * @param[in] key Key to copy * * @return SSH_ERROR on error, SSH_OK on success */ int pki_ed25519_key_dup(ssh_key new, const ssh_key key) { if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) { return SSH_ERROR; } if (key->ed25519_privkey != NULL) { #ifdef HAVE_OPENSSL_ED25519 /* In OpenSSL implementation, the private key is the original private * seed, without the public key. */ new->ed25519_privkey = malloc(ED25519_KEY_LEN); #else /* In the internal implementation, the private key is the concatenation * of the private seed with the public key. */ new->ed25519_privkey = malloc(2 * ED25519_KEY_LEN); #endif if (new->ed25519_privkey == NULL) { return SSH_ERROR; } #ifdef HAVE_OPENSSL_ED25519 memcpy(new->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN); #else memcpy(new->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN); #endif } if (key->ed25519_pubkey != NULL) { new->ed25519_pubkey = malloc(ED25519_KEY_LEN); if (new->ed25519_pubkey == NULL) { SAFE_FREE(new->ed25519_privkey); return SSH_ERROR; } memcpy(new->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN); } return SSH_OK; } /** * @internal * * @brief Outputs an Ed25519 public key in a blob buffer. * * @param[out] buffer Output buffer * * @param[in] key Key to output * * @return SSH_ERROR on error, SSH_OK on success */ int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key) { int rc; if (key->ed25519_pubkey == NULL){ return SSH_ERROR; } rc = ssh_buffer_pack(buffer, "dP", (uint32_t)ED25519_KEY_LEN, (size_t)ED25519_KEY_LEN, key->ed25519_pubkey); return rc; } /** * @internal * * @brief output a signature blob from an ed25519 signature * * @param[in] sig signature to convert * * @return Signature blob in SSH string, or NULL on error */ ssh_string pki_ed25519_signature_to_blob(ssh_signature sig) { ssh_string sig_blob; #ifdef HAVE_OPENSSL_ED25519 /* When using the OpenSSL implementation, the signature is stored in raw_sig * which is shared by all algorithms.*/ if (sig->raw_sig == NULL) { return NULL; } #else /* When using the internal implementation, the signature is stored in an * algorithm specific field. */ if (sig->ed25519_sig == NULL) { return NULL; } #endif sig_blob = ssh_string_new(ED25519_SIG_LEN); if (sig_blob == NULL) { return NULL; } #ifdef HAVE_OPENSSL_ED25519 ssh_string_fill(sig_blob, ssh_string_data(sig->raw_sig), ssh_string_len(sig->raw_sig)); #else ssh_string_fill(sig_blob, sig->ed25519_sig, ED25519_SIG_LEN); #endif return sig_blob; } /** * @internal * * @brief Convert a signature blob in an ed25519 signature. * * @param[out] sig a preinitialized signature * * @param[in] sig_blob a signature blob * * @return SSH_ERROR on error, SSH_OK on success */ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob) { size_t len; len = ssh_string_len(sig_blob); if (len != ED25519_SIG_LEN){ SSH_LOG(SSH_LOG_WARN, "Invalid ssh-ed25519 signature len: %zu", len); return SSH_ERROR; } #ifdef HAVE_OPENSSL_ED25519 sig->raw_sig = ssh_string_copy(sig_blob); #else sig->ed25519_sig = malloc(ED25519_SIG_LEN); if (sig->ed25519_sig == NULL){ return SSH_ERROR; } memcpy(sig->ed25519_sig, ssh_string_data(sig_blob), ED25519_SIG_LEN); #endif return SSH_OK; } ================================================ FILE: src/libssh/src/pki_gcrypt.c ================================================ /* * pki_gcrypt.c private and public key handling using gcrypt. * * This file is part of the SSH Library * * Copyright (c) 2003-2009 Aris Adamantiadis * Copyright (c) 2009-2011 Andreas Schneider * Copyright (C) 2016 g10 Code GmbH * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #ifdef HAVE_LIBGCRYPT #include #include #include #include #include #include #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/session.h" #include "libssh/wrapper.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #define MAXLINESIZE 80 #define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----" #define RSA_HEADER_END "-----END RSA PRIVATE KEY-----" #define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----" #define DSA_HEADER_END "-----END DSA PRIVATE KEY-----" #define ECDSA_HEADER_BEGIN "-----BEGIN EC PRIVATE KEY-----" #define ECDSA_HEADER_END "-----END EC PRIVATE KEY-----" #define MAX_KEY_SIZE 32 #define MAX_PASSPHRASE_SIZE 1024 #define ASN1_INTEGER 2 #define ASN1_BIT_STRING 3 #define ASN1_OCTET_STRING 4 #define ASN1_OBJECT_IDENTIFIER 6 #define ASN1_SEQUENCE 48 #define PKCS5_SALT_LEN 8 static int load_iv(const char *header, unsigned char *iv, int iv_len) { int i; int j; int k; memset(iv, 0, iv_len); for (i = 0; i < iv_len; i++) { if ((header[2*i] >= '0') && (header[2*i] <= '9')) j = header[2*i] - '0'; else if ((header[2*i] >= 'A') && (header[2*i] <= 'F')) j = header[2*i] - 'A' + 10; else if ((header[2*i] >= 'a') && (header[2*i] <= 'f')) j = header[2*i] - 'a' + 10; else return -1; if ((header[2*i+1] >= '0') && (header[2*i+1] <= '9')) k = header[2*i+1] - '0'; else if ((header[2*i+1] >= 'A') && (header[2*i+1] <= 'F')) k = header[2*i+1] - 'A' + 10; else if ((header[2*i+1] >= 'a') && (header[2*i+1] <= 'f')) k = header[2*i+1] - 'a' + 10; else return -1; iv[i] = (j << 4) + k; } return 0; } static uint32_t char_to_u32(unsigned char *data, uint32_t size) { uint32_t ret; uint32_t i; for (i = 0, ret = 0; i < size; ret = ret << 8, ret += data[i++]) ; return ret; } static uint32_t asn1_get_len(ssh_buffer buffer) { uint32_t len; unsigned char tmp[4]; if (ssh_buffer_get_data(buffer,tmp,1) == 0) { return 0; } if (tmp[0] > 127) { len = tmp[0] & 127; if (len > 4) { return 0; /* Length doesn't fit in u32. Can this really happen? */ } if (ssh_buffer_get_data(buffer,tmp,len) == 0) { return 0; } len = char_to_u32(tmp, len); } else { len = char_to_u32(tmp, 1); } return len; } static ssh_string asn1_get(ssh_buffer buffer, unsigned char want) { ssh_string str; unsigned char type; uint32_t size; if (ssh_buffer_get_data(buffer, &type, 1) == 0 || type != want) { return NULL; } size = asn1_get_len(buffer); if (size == 0) { return NULL; } str = ssh_string_new(size); if (str == NULL) { return NULL; } if (ssh_buffer_get_data(buffer, ssh_string_data(str), size) == 0) { SSH_STRING_FREE(str); return NULL; } return str; } static ssh_string asn1_get_int(ssh_buffer buffer) { return asn1_get(buffer, ASN1_INTEGER); } static ssh_string asn1_get_bit_string(ssh_buffer buffer) { ssh_string str; unsigned char type; uint32_t size; unsigned char unused, last, *p; uint32_t len; len = ssh_buffer_get_data(buffer, &type, 1); if (len == 0 || type != ASN1_BIT_STRING) { return NULL; } size = asn1_get_len(buffer); if (size == 0) { return NULL; } /* The first octet encodes the number of unused bits. */ size -= 1; str = ssh_string_new(size); if (str == NULL) { return NULL; } len = ssh_buffer_get_data(buffer, &unused, 1); if (len == 0) { SSH_STRING_FREE(str); return NULL; } if (unused == 0) { len = ssh_buffer_get_data(buffer, ssh_string_data(str), size); if (len == 0) { SSH_STRING_FREE(str); return NULL; } return str; } /* The bit string is padded at the end, we must shift the whole string by UNUSED bits. */ for (p = ssh_string_data(str), last = 0; size; size--, p++) { unsigned char c; len = ssh_buffer_get_data(buffer, &c, 1); if (len == 0) { SSH_STRING_FREE(str); return NULL; } *p = last | (c >> unused); last = c << (8 - unused); } return str; } static int asn1_check_sequence(ssh_buffer buffer) { unsigned char *j = NULL; unsigned char tmp; int i; uint32_t size; uint32_t padding; if (ssh_buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) { return 0; } size = asn1_get_len(buffer); if ((padding = ssh_buffer_get_len(buffer) - size) > 0) { for (i = ssh_buffer_get_len(buffer) - size, j = (unsigned char*)ssh_buffer_get(buffer) + size; i; i--, j++) { if (*j != padding) { /* padding is allowed */ return 0; /* but nothing else */ } } } return 1; } static int asn1_check_tag(ssh_buffer buffer, unsigned char tag) { unsigned char tmp; uint32_t len; len = ssh_buffer_get_data(buffer, &tmp, 1); if (len == 0 || tmp != tag) { return 0; } (void) asn1_get_len(buffer); return 1; } static int passphrase_to_key(char *data, unsigned int datalen, unsigned char *salt, unsigned char *key, unsigned int keylen) { MD5CTX md; unsigned char digest[MD5_DIGEST_LEN] = {0}; unsigned int i; unsigned int j; unsigned int md_not_empty; for (j = 0, md_not_empty = 0; j < keylen; ) { md = md5_init(); if (md == NULL) { return -1; } if (md_not_empty) { md5_update(md, digest, MD5_DIGEST_LEN); } else { md_not_empty = 1; } md5_update(md, data, datalen); if (salt) { md5_update(md, salt, PKCS5_SALT_LEN); } md5_final(digest, md); for (i = 0; j < keylen && i < MD5_DIGEST_LEN; j++, i++) { if (key) { key[j] = digest[i]; } } } return 0; } static int privatekey_decrypt(int algo, int mode, unsigned int key_len, unsigned char *iv, unsigned int iv_len, ssh_buffer data, ssh_auth_callback cb, void *userdata, const char *desc) { char passphrase[MAX_PASSPHRASE_SIZE] = {0}; unsigned char key[MAX_KEY_SIZE] = {0}; unsigned char *tmp = NULL; gcry_cipher_hd_t cipher; int rc = -1; if (!algo) { return -1; } if (cb) { rc = (*cb)(desc, passphrase, MAX_PASSPHRASE_SIZE, 0, 0, userdata); if (rc < 0) { return -1; } } else if (cb == NULL && userdata != NULL) { snprintf(passphrase, MAX_PASSPHRASE_SIZE, "%s", (char *) userdata); } if (passphrase_to_key(passphrase, strlen(passphrase), iv, key, key_len) < 0) { return -1; } if (gcry_cipher_open(&cipher, algo, mode, 0) || gcry_cipher_setkey(cipher, key, key_len) || gcry_cipher_setiv(cipher, iv, iv_len) || (tmp = calloc(ssh_buffer_get_len(data), sizeof(unsigned char))) == NULL || gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data), ssh_buffer_get(data), ssh_buffer_get_len(data))) { gcry_cipher_close(cipher); return -1; } memcpy(ssh_buffer_get(data), tmp, ssh_buffer_get_len(data)); SAFE_FREE(tmp); gcry_cipher_close(cipher); return 0; } static int privatekey_dek_header(const char *header, unsigned int header_len, int *algo, int *mode, unsigned int *key_len, unsigned char **iv, unsigned int *iv_len) { unsigned int iv_pos; if (header_len > 13 && !strncmp("DES-EDE3-CBC", header, 12)) { *algo = GCRY_CIPHER_3DES; iv_pos = 13; *mode = GCRY_CIPHER_MODE_CBC; *key_len = 24; *iv_len = 8; } else if (header_len > 8 && !strncmp("DES-CBC", header, 7)) { *algo = GCRY_CIPHER_DES; iv_pos = 8; *mode = GCRY_CIPHER_MODE_CBC; *key_len = 8; *iv_len = 8; } else if (header_len > 12 && !strncmp("AES-128-CBC", header, 11)) { *algo = GCRY_CIPHER_AES128; iv_pos = 12; *mode = GCRY_CIPHER_MODE_CBC; *key_len = 16; *iv_len = 16; } else if (header_len > 12 && !strncmp("AES-192-CBC", header, 11)) { *algo = GCRY_CIPHER_AES192; iv_pos = 12; *mode = GCRY_CIPHER_MODE_CBC; *key_len = 24; *iv_len = 16; } else if (header_len > 12 && !strncmp("AES-256-CBC", header, 11)) { *algo = GCRY_CIPHER_AES256; iv_pos = 12; *mode = GCRY_CIPHER_MODE_CBC; *key_len = 32; *iv_len = 16; } else { return -1; } *iv = malloc(*iv_len); if (*iv == NULL) { return -1; } return load_iv(header + iv_pos, *iv, *iv_len); } #define get_next_line(p, len) { \ while(p[len] == '\n' || p[len] == '\r') /* skip empty lines */ \ len++; \ if(p[len] == '\0') /* EOL */ \ eol = true; \ else /* calculate length */ \ for(p += len, len = 0; p[len] && p[len] != '\n' \ && p[len] != '\r'; len++); \ } static ssh_buffer privatekey_string_to_buffer(const char *pkey, int type, ssh_auth_callback cb, void *userdata, const char *desc) { ssh_buffer buffer = NULL; ssh_buffer out = NULL; const char *p; unsigned char *iv = NULL; const char *header_begin; const char *header_end; unsigned int header_begin_size; unsigned int header_end_size; unsigned int key_len = 0; unsigned int iv_len = 0; int algo = 0; int mode = 0; bool eol = false; size_t len; buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; } switch(type) { case SSH_KEYTYPE_DSS: header_begin = DSA_HEADER_BEGIN; header_end = DSA_HEADER_END; break; case SSH_KEYTYPE_RSA: header_begin = RSA_HEADER_BEGIN; header_end = RSA_HEADER_END; break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: header_begin = ECDSA_HEADER_BEGIN; header_end = ECDSA_HEADER_END; break; default: SSH_BUFFER_FREE(buffer); return NULL; } header_begin_size = strlen(header_begin); header_end_size = strlen(header_end); p = pkey; len = 0; get_next_line(p, len); while(!eol && strncmp(p, header_begin, header_begin_size)) { /* skip line */ get_next_line(p, len); } if (eol) { SSH_BUFFER_FREE(buffer); return NULL; } /* skip header line */ get_next_line(p, len); if (eol) { SSH_BUFFER_FREE(buffer); return NULL; } if (len > 11 && strncmp("Proc-Type: 4,ENCRYPTED", p, 11) == 0) { /* skip line */ get_next_line(p, len); if (eol) { SSH_BUFFER_FREE(buffer); return NULL; } if (len > 10 && strncmp("DEK-Info: ", p, 10) == 0) { p += 10; len = 0; get_next_line(p, len); if (eol) { SSH_BUFFER_FREE(buffer); return NULL; } if (privatekey_dek_header(p, len, &algo, &mode, &key_len, &iv, &iv_len) < 0) { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } } else { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } } else { if(len > 0) { if (ssh_buffer_add_data(buffer, p, len) < 0) { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } } } get_next_line(p, len); while(!eol && strncmp(p, header_end, header_end_size) != 0) { if (ssh_buffer_add_data(buffer, p, len) < 0) { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } get_next_line(p, len); } if (eol || strncmp(p, header_end, header_end_size) != 0) { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } if (ssh_buffer_add_data(buffer, "\0", 1) < 0) { SSH_BUFFER_FREE(buffer); SAFE_FREE(iv); return NULL; } out = base64_to_bin(ssh_buffer_get(buffer)); SSH_BUFFER_FREE(buffer); if (out == NULL) { SAFE_FREE(iv); return NULL; } if (algo) { if (privatekey_decrypt(algo, mode, key_len, iv, iv_len, out, cb, userdata, desc) < 0) { SSH_BUFFER_FREE(out); SAFE_FREE(iv); return NULL; } } SAFE_FREE(iv); return out; } static int b64decode_rsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_callback cb, void *userdata, const char *desc) { const unsigned char *data; ssh_string n = NULL; ssh_string e = NULL; ssh_string d = NULL; ssh_string p = NULL; ssh_string q = NULL; ssh_string unused1 = NULL; ssh_string unused2 = NULL; ssh_string u = NULL; ssh_string v = NULL; ssh_buffer buffer = NULL; int rc = 1; buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_RSA, cb, userdata, desc); if (buffer == NULL) { return 0; } if (!asn1_check_sequence(buffer)) { SSH_BUFFER_FREE(buffer); return 0; } v = asn1_get_int(buffer); if (v == NULL) { SSH_BUFFER_FREE(buffer); return 0; } data = ssh_string_data(v); if (ssh_string_len(v) != 1 || data[0] != 0) { SSH_STRING_FREE(v); SSH_BUFFER_FREE(buffer); return 0; } n = asn1_get_int(buffer); e = asn1_get_int(buffer); d = asn1_get_int(buffer); q = asn1_get_int(buffer); p = asn1_get_int(buffer); unused1 = asn1_get_int(buffer); unused2 = asn1_get_int(buffer); u = asn1_get_int(buffer); SSH_BUFFER_FREE(buffer); if (n == NULL || e == NULL || d == NULL || p == NULL || q == NULL || unused1 == NULL || unused2 == NULL|| u == NULL) { rc = 0; goto error; } if (gcry_sexp_build(r, NULL, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e), ssh_string_data(e), ssh_string_len(d), ssh_string_data(d), ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(u), ssh_string_data(u))) { rc = 0; } error: ssh_string_burn(n); SSH_STRING_FREE(n); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(d); SSH_STRING_FREE(d); ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(q); SSH_STRING_FREE(q); SSH_STRING_FREE(unused1); SSH_STRING_FREE(unused2); ssh_string_burn(u); SSH_STRING_FREE(u); SSH_STRING_FREE(v); return rc; } static int b64decode_dsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_callback cb, void *userdata, const char *desc) { const unsigned char *data; ssh_buffer buffer = NULL; ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string y = NULL; ssh_string x = NULL; ssh_string v = NULL; int rc = 1; buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_DSS, cb, userdata, desc); if (buffer == NULL) { return 0; } if (!asn1_check_sequence(buffer)) { SSH_BUFFER_FREE(buffer); return 0; } v = asn1_get_int(buffer); if (v == NULL) { SSH_BUFFER_FREE(buffer); return 0; } data = ssh_string_data(v); if (ssh_string_len(v) != 1 || data[0] != 0) { SSH_STRING_FREE(v); SSH_BUFFER_FREE(buffer); return 0; } p = asn1_get_int(buffer); q = asn1_get_int(buffer); g = asn1_get_int(buffer); y = asn1_get_int(buffer); x = asn1_get_int(buffer); SSH_BUFFER_FREE(buffer); if (p == NULL || q == NULL || g == NULL || y == NULL || x == NULL) { rc = 0; goto error; } if (gcry_sexp_build(r, NULL, "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(y), ssh_string_data(y), ssh_string_len(x), ssh_string_data(x))) { rc = 0; } error: ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(y); SSH_STRING_FREE(y); ssh_string_burn(x); SSH_STRING_FREE(x); SSH_STRING_FREE(v); return rc; } #ifdef HAVE_GCRYPT_ECC static int pki_key_ecdsa_to_nid(gcry_sexp_t k) { gcry_sexp_t sexp; const char *tmp; size_t size; sexp = gcry_sexp_find_token(k, "curve", 0); if (sexp == NULL) { return -1; } tmp = gcry_sexp_nth_data(sexp, 1, &size); if (size == 10) { int cmp; cmp = memcmp("NIST P-256", tmp, size); if (cmp == 0) { gcry_sexp_release(sexp); return NID_gcrypt_nistp256; } cmp = memcmp("NIST P-384", tmp, size); if (cmp == 0) { gcry_sexp_release(sexp); return NID_gcrypt_nistp384; } cmp = memcmp("NIST P-521", tmp, size); if (cmp == 0) { gcry_sexp_release(sexp); return NID_gcrypt_nistp521; } } gcry_sexp_release(sexp); return -1; } static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(gcry_sexp_t k) { int nid; nid = pki_key_ecdsa_to_nid(k); switch (nid) { case NID_gcrypt_nistp256: return SSH_KEYTYPE_ECDSA_P256; case NID_gcrypt_nistp384: return SSH_KEYTYPE_ECDSA_P384; case NID_gcrypt_nistp521: return SSH_KEYTYPE_ECDSA_P521; default: return SSH_KEYTYPE_UNKNOWN; } } static const char *pki_key_ecdsa_nid_to_gcrypt_name(int nid) { switch (nid) { case NID_gcrypt_nistp256: return "NIST P-256"; case NID_gcrypt_nistp384: return "NIST P-384"; case NID_gcrypt_nistp521: return "NIST P-521"; } return "unknown"; } const char *pki_key_ecdsa_nid_to_name(int nid) { switch (nid) { case NID_gcrypt_nistp256: return "ecdsa-sha2-nistp256"; case NID_gcrypt_nistp384: return "ecdsa-sha2-nistp384"; case NID_gcrypt_nistp521: return "ecdsa-sha2-nistp521"; } return "unknown"; } static const char *pki_key_ecdsa_nid_to_char(int nid) { switch (nid) { case NID_gcrypt_nistp256: return "nistp256"; case NID_gcrypt_nistp384: return "nistp384"; case NID_gcrypt_nistp521: return "nistp521"; default: break; } return "unknown"; } int pki_key_ecdsa_nid_from_name(const char *name) { int cmp; cmp = strcmp(name, "nistp256"); if (cmp == 0) { return NID_gcrypt_nistp256; } cmp = strcmp(name, "nistp384"); if (cmp == 0) { return NID_gcrypt_nistp384; } cmp = strcmp(name, "nistp521"); if (cmp == 0) { return NID_gcrypt_nistp521; } return -1; } static int asn1_oi_to_nid(const ssh_string oi) { static const struct { int nid; size_t length; const char *identifier; } *e, mapping[] = { {NID_gcrypt_nistp256, 8, "\x2a\x86\x48\xce\x3d\x03\x01\x07"}, {NID_gcrypt_nistp384, 5, "\x2b\x81\x04\x00\x22"}, {NID_gcrypt_nistp521, 5, "\x2b\x81\x04\x00\x23"}, {0}, }; size_t len = ssh_string_len(oi); for (e = mapping; e->length; e++) { if (len == e->length && memcmp(ssh_string_data(oi), e->identifier, len) == 0) { return e->nid; } } return -1; } static int b64decode_ecdsa_privatekey(const char *pkey, gcry_sexp_t *r, ssh_auth_callback cb, void *userdata, const char *desc) { const unsigned char *data; ssh_buffer buffer = NULL; gcry_error_t err = 0; ssh_string v = NULL; ssh_string d = NULL; ssh_string oi = NULL; int nid; ssh_string q = NULL; int valid = 0; int ok; buffer = privatekey_string_to_buffer(pkey, SSH_KEYTYPE_ECDSA_P256, cb, userdata, desc); if (buffer == NULL) { goto error; } ok = asn1_check_sequence(buffer); if (!ok) { goto error; } /* RFC5915 specifies version 1. */ v = asn1_get_int(buffer); if (v == NULL) { goto error; } data = ssh_string_data(v); if (ssh_string_len(v) != 1 || data[0] != 1) { goto error; } d = asn1_get(buffer, ASN1_OCTET_STRING); if (!asn1_check_tag(buffer, 0xa0)) { goto error; } oi = asn1_get(buffer, ASN1_OBJECT_IDENTIFIER); nid = asn1_oi_to_nid(oi); ok = asn1_check_tag(buffer, 0xa1); if (!ok) { goto error; } q = asn1_get_bit_string(buffer); if (d == NULL || oi == NULL || nid == -1 || q == NULL) { goto error; } err = gcry_sexp_build(r, NULL, "(private-key(ecdsa(curve %s)(d %b)(q %b)))", pki_key_ecdsa_nid_to_gcrypt_name(nid), ssh_string_len(d), ssh_string_data(d), ssh_string_len(q), ssh_string_data(q)); if (err == 0) { valid = 1; } error: SSH_BUFFER_FREE(buffer); SSH_STRING_FREE(v); ssh_string_burn(d); SSH_STRING_FREE(d); SSH_STRING_FREE(oi); ssh_string_burn(q); SSH_STRING_FREE(q); return valid; } #endif ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { (void) key; (void) passphrase; (void) auth_fn; (void) auth_data; SSH_LOG(SSH_LOG_WARN, "PEM export not supported by gcrypt backend!"); return NULL; } ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { gcry_sexp_t dsa = NULL; gcry_sexp_t rsa = NULL; gcry_sexp_t ecdsa = NULL; ssh_key key = NULL; enum ssh_keytypes_e type; int valid; type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_DSS: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_dsa_privatekey(b64_key, &dsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, NULL, NULL); } } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, (void *) passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_RSA: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_rsa_privatekey(b64_key, &rsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, NULL, NULL); } } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, (void *)passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #if HAVE_GCRYPT_ECC if (passphrase == NULL) { if (auth_fn != NULL) { valid = b64decode_ecdsa_privatekey(b64_key, &ecdsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_ecdsa_privatekey(b64_key, &ecdsa, NULL, NULL, NULL); } } else { valid = b64decode_ecdsa_privatekey(b64_key, &ecdsa, NULL, (void *)passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } /* pki_privatekey_type_from_string always returns P256 for ECDSA * keys, so we need to figure out the correct type here */ type = pki_key_ecdsa_to_key_type(ecdsa); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Invalid private key."); goto fail; } break; #endif case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libgcrypt */ case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; key->ecdsa = ecdsa; #ifdef HAVE_GCRYPT_ECC if (is_ecdsa_key_type(key->type)) { key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); } #endif return key; fail: ssh_key_free(key); gcry_sexp_release(dsa); gcry_sexp_release(rsa); gcry_sexp_release(ecdsa); return NULL; } int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey, ssh_string privkey) { gcry_sexp_build(&key->dsa, NULL, "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(pubkey), ssh_string_data(pubkey), ssh_string_len(privkey), ssh_string_data(privkey)); if (key->dsa == NULL) { return SSH_ERROR; } return SSH_OK; } int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey) { gcry_sexp_build(&key->dsa, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(pubkey), ssh_string_data(pubkey)); if (key->dsa == NULL) { return SSH_ERROR; } return SSH_OK; } int pki_privkey_build_rsa(ssh_key key, ssh_string n, ssh_string e, ssh_string d, ssh_string iqmp, ssh_string p, ssh_string q) { /* in gcrypt, there is no iqmp (inverse of q mod p) argument, * but it is ipmq (inverse of p mod q) so we need to swap * the p and q arguments */ gcry_sexp_build(&key->rsa, NULL, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e), ssh_string_data(e), ssh_string_len(d), ssh_string_data(d), ssh_string_len(q), ssh_string_data(q), ssh_string_len(p), ssh_string_data(p), ssh_string_len(iqmp), ssh_string_data(iqmp)); if (key->rsa == NULL) { return SSH_ERROR; } return SSH_OK; } int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { gcry_sexp_build(&key->rsa, NULL, "(public-key(rsa(n %b)(e %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e),ssh_string_data(e)); if (key->rsa == NULL) { return SSH_ERROR; } return SSH_OK; } #ifdef HAVE_GCRYPT_ECC int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) { gpg_error_t err; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); err = gcry_sexp_build(&key->ecdsa, NULL, "(private-key(ecdsa(curve %s)(d %b)(q %b)))", pki_key_ecdsa_nid_to_gcrypt_name(nid), ssh_string_len(exp), ssh_string_data(exp), ssh_string_len(e), ssh_string_data(e)); if (err) { return SSH_ERROR; } return SSH_OK; } int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { gpg_error_t err; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); err = gcry_sexp_build(&key->ecdsa, NULL, "(public-key(ecdsa(curve %s)(q %b)))", pki_key_ecdsa_nid_to_gcrypt_name(nid), ssh_string_len(e), ssh_string_data(e)); if (err) { return SSH_ERROR; } return SSH_OK; } #endif ssh_key pki_key_dup(const ssh_key key, int demote) { ssh_key new; gcry_error_t err = 0; int rc; gcry_mpi_t p = NULL; gcry_mpi_t q = NULL; gcry_mpi_t g = NULL; gcry_mpi_t y = NULL; gcry_mpi_t x = NULL; gcry_mpi_t e = NULL; gcry_mpi_t n = NULL; gcry_mpi_t d = NULL; gcry_mpi_t u = NULL; gcry_sexp_t curve = NULL; new = ssh_key_new(); if (new == NULL) { return NULL; } new->type = key->type; new->type_c = key->type_c; if (demote) { new->flags = SSH_KEY_FLAG_PUBLIC; } else { new->flags = key->flags; } switch(key->type) { case SSH_KEYTYPE_DSS: err = gcry_sexp_extract_param(key->dsa, NULL, "pqgyx?", &p, &q, &g, &y, &x, NULL); if (err != 0) { break; } if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { err = gcry_sexp_build(&new->dsa, NULL, "(private-key(dsa(p %m)(q %m)(g %m)(y %m)(x %m)))", p, q, g, y, x); } else { err = gcry_sexp_build(&new->dsa, NULL, "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))", p, q, g, y); } break; case SSH_KEYTYPE_RSA: err = gcry_sexp_extract_param(key->rsa, NULL, "ned?p?q?u?", &n, &e, &d, &p, &q, &u, NULL); if (err != 0) { break; } if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { err = gcry_sexp_build(&new->rsa, NULL, "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))", n, e, d, p, q, u); } else { err = gcry_sexp_build(&new->rsa, NULL, "(public-key(rsa(n %m)(e %m)))", n, e); } break; case SSH_KEYTYPE_ED25519: rc = pki_ed25519_key_dup(new, key); if (rc != SSH_OK) { ssh_key_free(new); return NULL; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC new->ecdsa_nid = key->ecdsa_nid; err = gcry_sexp_extract_param(key->ecdsa, NULL, "qd?", &q, &d, NULL); if (err) { break; } curve = gcry_sexp_find_token(key->ecdsa, "curve", 0); if (curve == NULL) { break; } if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { err = gcry_sexp_build(&new->ecdsa, NULL, "(private-key(ecdsa %S (d %m)(q %m)))", curve, d, q); } else { err = gcry_sexp_build(&new->ecdsa, NULL, "(private-key(ecdsa %S (q %m)))", curve, q); } break; #endif case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: ssh_key_free(new); return NULL; } if (err) { ssh_key_free(new); new = NULL; } gcry_mpi_release(p); gcry_mpi_release(q); gcry_mpi_release(g); gcry_mpi_release(y); gcry_mpi_release(x); gcry_mpi_release(e); gcry_mpi_release(n); gcry_mpi_release(d); gcry_mpi_release(u); gcry_sexp_release(curve); return new; } static int pki_key_generate(ssh_key key, int parameter, const char *type_s, int type){ gcry_sexp_t parms; int rc; rc = gcry_sexp_build(&parms, NULL, "(genkey(%s(nbits %d)(transient-key)))", type_s, parameter); if (rc != 0) return SSH_ERROR; switch (type) { case SSH_KEYTYPE_RSA: rc = gcry_pk_genkey(&key->rsa, parms); break; case SSH_KEYTYPE_DSS: rc = gcry_pk_genkey(&key->dsa, parms); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: rc = gcry_pk_genkey(&key->ecdsa, parms); break; default: assert (! "reached"); } gcry_sexp_release(parms); if (rc != 0) return SSH_ERROR; return SSH_OK; } int pki_key_generate_rsa(ssh_key key, int parameter){ return pki_key_generate(key, parameter, "rsa", SSH_KEYTYPE_RSA); } int pki_key_generate_dss(ssh_key key, int parameter){ return pki_key_generate(key, parameter, "dsa", SSH_KEYTYPE_DSS); } #ifdef HAVE_GCRYPT_ECC int pki_key_generate_ecdsa(ssh_key key, int parameter) { switch (parameter) { case 384: key->ecdsa_nid = NID_gcrypt_nistp384; key->type = SSH_KEYTYPE_ECDSA_P384; return pki_key_generate(key, parameter, "ecdsa", SSH_KEYTYPE_ECDSA_P384); case 521: key->ecdsa_nid = NID_gcrypt_nistp521; key->type = SSH_KEYTYPE_ECDSA_P521; return pki_key_generate(key, parameter, "ecdsa", SSH_KEYTYPE_ECDSA_P521); case 256: default: key->ecdsa_nid = NID_gcrypt_nistp256; key->type = SSH_KEYTYPE_ECDSA_P256; return pki_key_generate(key, parameter, "ecdsa", SSH_KEYTYPE_ECDSA_P256); } } #endif static int _bignum_cmp(const gcry_sexp_t s1, const gcry_sexp_t s2, const char *what) { gcry_sexp_t sexp; bignum b1; bignum b2; int result; sexp = gcry_sexp_find_token(s1, what, 0); if (sexp == NULL) { return 1; } b1 = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); gcry_sexp_release(sexp); if (b1 == NULL) { return 1; } sexp = gcry_sexp_find_token(s2, what, 0); if (sexp == NULL) { bignum_safe_free(b1); return 1; } b2 = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); gcry_sexp_release(sexp); if (b2 == NULL) { bignum_safe_free(b1); return 1; } result = !! bignum_cmp(b1, b2); bignum_safe_free(b1); bignum_safe_free(b2); return result; } int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { switch (k1->type) { case SSH_KEYTYPE_DSS: if (_bignum_cmp(k1->dsa, k2->dsa, "p") != 0) { return 1; } if (_bignum_cmp(k1->dsa, k2->dsa, "q") != 0) { return 1; } if (_bignum_cmp(k1->dsa, k2->dsa, "g") != 0) { return 1; } if (_bignum_cmp(k1->dsa, k2->dsa, "y") != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (_bignum_cmp(k1->dsa, k2->dsa, "x") != 0) { return 1; } } break; case SSH_KEYTYPE_RSA: if (_bignum_cmp(k1->rsa, k2->rsa, "e") != 0) { return 1; } if (_bignum_cmp(k1->rsa, k2->rsa, "n") != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (_bignum_cmp(k1->rsa, k2->rsa, "d") != 0) { return 1; } if (_bignum_cmp(k1->rsa, k2->rsa, "p") != 0) { return 1; } if (_bignum_cmp(k1->rsa, k2->rsa, "q") != 0) { return 1; } if (_bignum_cmp(k1->rsa, k2->rsa, "u") != 0) { return 1; } } break; case SSH_KEYTYPE_ED25519: /* ed25519 keys handled globaly */ return 0; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC if (k1->ecdsa_nid != k2->ecdsa_nid) { return 1; } if (_bignum_cmp(k1->ecdsa, k2->ecdsa, "q") != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (_bignum_cmp(k1->ecdsa, k2->ecdsa, "d") != 0) { return 1; } } break; #endif case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: return 1; } return 0; } ssh_string pki_publickey_to_blob(const ssh_key key) { ssh_buffer buffer; ssh_string type_s; ssh_string str = NULL; ssh_string e = NULL; ssh_string n = NULL; ssh_string p = NULL; ssh_string g = NULL; ssh_string q = NULL; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; } if (key->cert != NULL) { rc = ssh_buffer_add_buffer(buffer, key->cert); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } goto makestring; } type_s = ssh_string_from_char(key->type_c); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } switch (key->type) { case SSH_KEYTYPE_DSS: p = ssh_sexp_extract_mpi(key->dsa, "p", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (p == NULL) { goto fail; } q = ssh_sexp_extract_mpi(key->dsa, "q", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (q == NULL) { goto fail; } g = ssh_sexp_extract_mpi(key->dsa, "g", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (g == NULL) { goto fail; } n = ssh_sexp_extract_mpi(key->dsa, "y", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (n == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, p); if (rc < 0) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, q); if (rc < 0) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, g); if (rc < 0) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, n); if (rc < 0) { goto fail; } ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(n); SSH_STRING_FREE(n); break; case SSH_KEYTYPE_RSA: e = ssh_sexp_extract_mpi(key->rsa, "e", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (e == NULL) { goto fail; } n = ssh_sexp_extract_mpi(key->rsa, "n", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (n == NULL) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, e); if (rc < 0) { goto fail; } rc = ssh_buffer_add_ssh_string(buffer, n); if (rc < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(n); SSH_STRING_FREE(n); break; case SSH_KEYTYPE_ED25519: rc = pki_ed25519_public_key_to_blob(buffer, key); if (rc != SSH_OK){ goto fail; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC type_s = ssh_string_from_char( pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } e = ssh_sexp_extract_mpi(key->ecdsa, "q", GCRYMPI_FMT_STD, GCRYMPI_FMT_STD); if (e == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, e); if (rc < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; break; #endif case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: goto fail; } makestring: str = ssh_string_new(ssh_buffer_get_len(buffer)); if (str == NULL) { goto fail; } rc = ssh_string_fill(str, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); if (rc < 0) { goto fail; } SSH_BUFFER_FREE(buffer); return str; fail: SSH_BUFFER_FREE(buffer); ssh_string_burn(str); SSH_STRING_FREE(str); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(p); SSH_STRING_FREE(p); ssh_string_burn(g); SSH_STRING_FREE(g); ssh_string_burn(q); SSH_STRING_FREE(q); ssh_string_burn(n); SSH_STRING_FREE(n); return NULL; } ssh_string pki_signature_to_blob(const ssh_signature sig) { char buffer[40] = { 0 }; const char *r = NULL; size_t r_len, r_offset_in, r_offset_out; const char *s = NULL; size_t s_len, s_offset_in, s_offset_out; gcry_sexp_t sexp; size_t size = 0; ssh_string sig_blob = NULL; switch(sig->type) { case SSH_KEYTYPE_DSS: sexp = gcry_sexp_find_token(sig->dsa_sig, "r", 0); if (sexp == NULL) { return NULL; } r = gcry_sexp_nth_data(sexp, 1, &size); /* libgcrypt put 0 when first bit is set */ if (*r == 0) { size--; r++; } r_len = size; r_offset_in = (r_len > 20) ? (r_len - 20) : 0; r_offset_out = (r_len < 20) ? (20 - r_len) : 0; memcpy(buffer + r_offset_out, r + r_offset_in, r_len - r_offset_in); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(sig->dsa_sig, "s", 0); if (sexp == NULL) { return NULL; } s = gcry_sexp_nth_data(sexp,1,&size); if (*s == 0) { size--; s++; } s_len = size; s_offset_in = (s_len > 20) ? (s_len - 20) : 0; s_offset_out = (s_len < 20) ? (20 - s_len) : 0; memcpy(buffer + 20 + s_offset_out, s + s_offset_in, s_len - s_offset_in); gcry_sexp_release(sexp); sig_blob = ssh_string_new(40); if (sig_blob == NULL) { return NULL; } ssh_string_fill(sig_blob, buffer, 40); break; case SSH_KEYTYPE_RSA: sexp = gcry_sexp_find_token(sig->rsa_sig, "s", 0); if (sexp == NULL) { return NULL; } s = gcry_sexp_nth_data(sexp, 1, &size); if (*s == 0) { size--; s++; } sig_blob = ssh_string_new(size); if (sig_blob == NULL) { return NULL; } ssh_string_fill(sig_blob, discard_const_p(char, s), size); gcry_sexp_release(sexp); break; case SSH_KEYTYPE_ED25519: sig_blob = pki_ed25519_signature_to_blob(sig); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC { ssh_string R; ssh_string S; ssh_buffer b; int rc; b = ssh_buffer_new(); if (b == NULL) { return NULL; } R = ssh_sexp_extract_mpi(sig->ecdsa_sig, "r", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (R == NULL) { SSH_BUFFER_FREE(b); return NULL; } rc = ssh_buffer_add_ssh_string(b, R); SSH_STRING_FREE(R); if (rc < 0) { SSH_BUFFER_FREE(b); return NULL; } S = ssh_sexp_extract_mpi(sig->ecdsa_sig, "s", GCRYMPI_FMT_USG, GCRYMPI_FMT_STD); if (S == NULL) { SSH_BUFFER_FREE(b); return NULL; } rc = ssh_buffer_add_ssh_string(b, S); SSH_STRING_FREE(S); if (rc < 0) { SSH_BUFFER_FREE(b); return NULL; } sig_blob = ssh_string_new(ssh_buffer_get_len(b)); if (sig_blob == NULL) { SSH_BUFFER_FREE(b); return NULL; } ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b)); SSH_BUFFER_FREE(b); break; } #endif case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %d", sig->type); return NULL; break; } return sig_blob; } ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string sig_blob, enum ssh_keytypes_e type, enum ssh_digest_e hash_type) { ssh_signature sig; gcry_error_t err; size_t len; size_t rsalen; int rc; if (ssh_key_type_plain(pubkey->type) != type) { SSH_LOG(SSH_LOG_WARN, "Incompatible public key provided (%d) expecting (%d)", type, pubkey->type); return NULL; } sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = type; sig->type_c = ssh_key_signature_to_char(type, hash_type); sig->hash_type = hash_type; len = ssh_string_len(sig_blob); switch(type) { case SSH_KEYTYPE_DSS: /* 40 is the dual signature blob len. */ if (len != 40) { SSH_LOG(SSH_LOG_WARN, "Signature has wrong size: %lu", (unsigned long)len); ssh_signature_free(sig); return NULL; } #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_DEBUG, "DSA signature len: %lu", (unsigned long)len); ssh_log_hexdump("DSA signature", ssh_string_data(sig_blob), len); #endif err = gcry_sexp_build(&sig->dsa_sig, NULL, "(sig-val(dsa(r %b)(s %b)))", 20, ssh_string_data(sig_blob), 20, (unsigned char *)ssh_string_data(sig_blob) + 20); if (err) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_RSA: rsalen = (gcry_pk_get_nbits(pubkey->rsa) + 7) / 8; if (len > rsalen) { SSH_LOG(SSH_LOG_WARN, "Signature is to big size: %lu", (unsigned long)len); ssh_signature_free(sig); return NULL; } if (len < rsalen) { SSH_LOG(SSH_LOG_DEBUG, "RSA signature len %lu < %lu", (unsigned long)len, (unsigned long)rsalen); } #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_DEBUG, "RSA signature len: %lu", (unsigned long)len); ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); #endif err = gcry_sexp_build(&sig->rsa_sig, NULL, "(sig-val(rsa(s %b)))", ssh_string_len(sig_blob), ssh_string_data(sig_blob)); if (err) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ED25519: rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc != SSH_OK){ ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC { /* build ecdsa siganature */ ssh_buffer b; ssh_string r, s; uint32_t rlen; b = ssh_buffer_new(); if (b == NULL) { ssh_signature_free(sig); return NULL; } rc = ssh_buffer_add_data(b, ssh_string_data(sig_blob), ssh_string_len(sig_blob)); if (rc < 0) { SSH_BUFFER_FREE(b); ssh_signature_free(sig); return NULL; } r = ssh_buffer_get_ssh_string(b); if (r == NULL) { SSH_BUFFER_FREE(b); ssh_signature_free(sig); return NULL; } s = ssh_buffer_get_ssh_string(b); rlen = ssh_buffer_get_len(b); SSH_BUFFER_FREE(b); if (s == NULL) { ssh_string_burn(r); SSH_STRING_FREE(r); ssh_signature_free(sig); return NULL; } if (rlen != 0) { SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner " "sigblob: %lu", (unsigned long)rlen); ssh_string_burn(r); SSH_STRING_FREE(r); ssh_string_burn(s); SSH_STRING_FREE(s); ssh_signature_free(sig); return NULL; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r)); ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s)); #endif err = gcry_sexp_build(&sig->ecdsa_sig, NULL, "(sig-val(ecdsa(r %b)(s %b)))", ssh_string_len(r), ssh_string_data(r), ssh_string_len(s), ssh_string_data(s)); ssh_string_burn(r); SSH_STRING_FREE(r); ssh_string_burn(s); SSH_STRING_FREE(s); if (err) { ssh_signature_free(sig); return NULL; } } break; #endif case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); return NULL; } return sig; } ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type) { unsigned char ghash[hlen + 1]; const char *hash_c = NULL; ssh_signature sig; gcry_sexp_t sexp; gcry_error_t err; sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = privkey->type; sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type); sig->hash_type = hash_type; switch (privkey->type) { case SSH_KEYTYPE_DSS: /* That is to mark the number as positive */ if(hash[0] >= 0x80) { memcpy(ghash + 1, hash, hlen); ghash[0] = 0; hash = ghash; hlen += 1; } err = gcry_sexp_build(&sexp, NULL, "%b", hlen, hash); if (err) { ssh_signature_free(sig); return NULL; } err = gcry_pk_sign(&sig->dsa_sig, sexp, privkey->dsa); gcry_sexp_release(sexp); if (err) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_RSA: switch (hash_type) { case SSH_DIGEST_SHA1: hash_c = "sha1"; break; case SSH_DIGEST_SHA256: hash_c = "sha256"; break; case SSH_DIGEST_SHA512: hash_c = "sha512"; break; case SSH_DIGEST_AUTO: default: SSH_LOG(SSH_LOG_WARN, "Incompatible key algorithm"); return NULL; } err = gcry_sexp_build(&sexp, NULL, "(data(flags pkcs1)(hash %s %b))", hash_c, hlen, hash); if (err) { ssh_signature_free(sig); return NULL; } err = gcry_pk_sign(&sig->rsa_sig, sexp, privkey->rsa); gcry_sexp_release(sexp); if (err) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ED25519: err = pki_ed25519_sign(privkey, sig, hash, hlen); if (err != SSH_OK){ ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: #ifdef HAVE_GCRYPT_ECC err = gcry_sexp_build(&sexp, NULL, "(data(flags raw)(value %b))", hlen, hash); if (err) { ssh_signature_free(sig); return NULL; } err = gcry_pk_sign(&sig->ecdsa_sig, sexp, privkey->ecdsa); gcry_sexp_release(sexp); if (err) { ssh_signature_free(sig); return NULL; } break; #endif case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: ssh_signature_free(sig); return NULL; } return sig; } /** * @internal * * @brief Sign the given input data. The digest of to be signed is calculated * internally as necessary. * * @param[in] privkey The private key to be used for signing. * @param[in] hash_type The digest algorithm to be used. * @param[in] input The data to be signed. * @param[in] input_len The length of the data to be signed. * * @return a newly allocated ssh_signature or NULL on error. */ ssh_signature pki_sign_data(const ssh_key privkey, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { unsigned char hash[SHA512_DIGEST_LEN] = {0}; const unsigned char *sign_input = NULL; uint32_t hlen = 0; int rc; if (privkey == NULL || !ssh_key_is_private(privkey) || input == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_sign_data()"); return NULL; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(privkey, hash_type); if (rc != SSH_OK) { return NULL; } switch (hash_type) { case SSH_DIGEST_SHA256: sha256(input, input_len, hash); hlen = SHA256_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA384: sha384(input, input_len, hash); hlen = SHA384_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA512: sha512(input, input_len, hash); hlen = SHA512_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA1: sha1(input, input_len, hash); hlen = SHA_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_AUTO: if (privkey->type == SSH_KEYTYPE_ED25519) { /* SSH_DIGEST_AUTO should only be used with ed25519 */ sign_input = input; hlen = input_len; break; } FALL_THROUGH; default: SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d", hash_type); return NULL; } return pki_do_sign_hash(privkey, sign_input, hlen, hash_type); } /** * @internal * * @brief Verify the signature of a given input. The digest of the input is * calculated internally as necessary. * * @param[in] signature The signature to be verified. * @param[in] pubkey The public key used to verify the signature. * @param[in] input The signed data. * @param[in] input_len The length of the signed data. * * @return SSH_OK if the signature is valid; SSH_ERROR otherwise. */ int pki_verify_data_signature(ssh_signature signature, const ssh_key pubkey, const unsigned char *input, size_t input_len) { const char *hash_type = NULL; gcry_sexp_t sexp; gcry_error_t err; unsigned char ghash[SHA512_DIGEST_LEN + 1] = {0}; unsigned char *hash = ghash + 1; uint32_t hlen = 0; const unsigned char *verify_input = NULL; int rc; if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || signature == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_verify_data_signature()"); return SSH_ERROR; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); if (rc != SSH_OK) { return SSH_ERROR; } switch (signature->hash_type) { case SSH_DIGEST_SHA256: sha256(input, input_len, hash); hlen = SHA256_DIGEST_LEN; hash_type = "sha256"; verify_input = hash; break; case SSH_DIGEST_SHA384: sha384(input, input_len, hash); hlen = SHA384_DIGEST_LEN; hash_type = "sha384"; verify_input = hash; break; case SSH_DIGEST_SHA512: sha512(input, input_len, hash); hlen = SHA512_DIGEST_LEN; hash_type = "sha512"; verify_input = hash; break; case SSH_DIGEST_SHA1: sha1(input, input_len, hash); hlen = SHA_DIGEST_LEN; hash_type = "sha1"; verify_input = hash; break; case SSH_DIGEST_AUTO: if (pubkey->type == SSH_KEYTYPE_ED25519 || pubkey->type == SSH_KEYTYPE_ED25519_CERT01) { verify_input = input; hlen = input_len; break; } FALL_THROUGH; default: SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", signature->hash_type); return SSH_ERROR; } switch(pubkey->type) { case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS_CERT01: /* That is to mark the number as positive */ if(hash[0] >= 0x80) { hash = ghash; hlen += 1; } err = gcry_sexp_build(&sexp, NULL, "%b", hlen, hash); if (err) { SSH_LOG(SSH_LOG_TRACE, "DSA hash error: %s", gcry_strerror(err)); return SSH_ERROR; } err = gcry_pk_verify(signature->dsa_sig, sexp, pubkey->dsa); gcry_sexp_release(sexp); if (err) { SSH_LOG(SSH_LOG_TRACE, "Invalid DSA signature"); if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) { SSH_LOG(SSH_LOG_TRACE, "DSA verify error: %s", gcry_strerror(err)); } return SSH_ERROR; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA_CERT01: err = gcry_sexp_build(&sexp, NULL, "(data(flags pkcs1)(hash %s %b))", hash_type, hlen, hash); if (err) { SSH_LOG(SSH_LOG_TRACE, "RSA hash error: %s", gcry_strerror(err)); return SSH_ERROR; } err = gcry_pk_verify(signature->rsa_sig, sexp, pubkey->rsa); gcry_sexp_release(sexp); if (err) { SSH_LOG(SSH_LOG_TRACE, "Invalid RSA signature"); if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) { SSH_LOG(SSH_LOG_TRACE, "RSA verify error: %s", gcry_strerror(err)); } return SSH_ERROR; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: #ifdef HAVE_GCRYPT_ECC err = gcry_sexp_build(&sexp, NULL, "(data(flags raw)(value %b))", hlen, hash); if (err) { SSH_LOG(SSH_LOG_TRACE, "ECDSA hash error: %s", gcry_strerror(err)); return SSH_ERROR; } err = gcry_pk_verify(signature->ecdsa_sig, sexp, pubkey->ecdsa); gcry_sexp_release(sexp); if (err) { SSH_LOG(SSH_LOG_TRACE, "Invalid ECDSA signature"); if (gcry_err_code(err) != GPG_ERR_BAD_SIGNATURE) { SSH_LOG(SSH_LOG_TRACE, "ECDSA verify error: %s", gcry_strerror(err)); } return SSH_ERROR; } break; #endif case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519_CERT01: rc = pki_ed25519_verify(pubkey, signature, verify_input, hlen); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_TRACE, "ED25519 error: Signature invalid"); return SSH_ERROR; } break; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_TRACE, "Unknown public key type"); return SSH_ERROR; } return SSH_OK; } #endif /* HAVE_LIBGCRYPT */ ================================================ FILE: src/libssh/src/pki_mbedcrypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2017 Sartura d.o.o. * * Author: Juraj Vijtiuk * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #ifdef HAVE_LIBMBEDCRYPTO #include #include #include "libssh/priv.h" #include "libssh/pki.h" #include "libssh/pki_priv.h" #include "libssh/buffer.h" #include "libssh/bignum.h" #include "libssh/misc.h" #define MAX_PASSPHRASE_SIZE 1024 #define MAX_KEY_SIZE 32 ssh_string pki_private_key_to_pem(const ssh_key key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { (void) key; (void) passphrase; (void) auth_fn; (void) auth_data; return NULL; } static int pki_key_ecdsa_to_nid(mbedtls_ecdsa_context *ecdsa) { mbedtls_ecp_group_id id; id = ecdsa->grp.id; if (id == MBEDTLS_ECP_DP_SECP256R1) { return NID_mbedtls_nistp256; } else if (id == MBEDTLS_ECP_DP_SECP384R1) { return NID_mbedtls_nistp384; } else if (id == MBEDTLS_ECP_DP_SECP521R1) { return NID_mbedtls_nistp521; } return -1; } static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(mbedtls_ecdsa_context *ecdsa) { int nid; nid = pki_key_ecdsa_to_nid(ecdsa); switch (nid) { case NID_mbedtls_nistp256: return SSH_KEYTYPE_ECDSA_P256; case NID_mbedtls_nistp384: return SSH_KEYTYPE_ECDSA_P384; case NID_mbedtls_nistp521: return SSH_KEYTYPE_ECDSA_P521; default: return SSH_KEYTYPE_UNKNOWN; } } ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_key key = NULL; mbedtls_pk_context *rsa = NULL; mbedtls_pk_context *ecdsa = NULL; ed25519_privkey *ed25519 = NULL; enum ssh_keytypes_e type; int valid; /* mbedtls pk_parse_key expects strlen to count the 0 byte */ size_t b64len = strlen(b64_key) + 1; unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_RSA: rsa = malloc(sizeof(mbedtls_pk_context)); if (rsa == NULL) { return NULL; } mbedtls_pk_init(rsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { goto fail; } /* TODO fix signedness and strlen */ valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: ecdsa = malloc(sizeof(mbedtls_pk_context)); if (ecdsa == NULL) { return NULL; } mbedtls_pk_init(ecdsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { goto fail; } valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libmbedcrypto */ default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } if (ecdsa != NULL) { mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { goto fail; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecdsa_from_keypair(key->ecdsa, keypair); mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); /* pki_privatekey_type_from_string always returns P256 for ECDSA * keys, so we need to figure out the correct type here */ type = pki_key_ecdsa_to_key_type(key->ecdsa); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Invalid private key."); goto fail; } } else { key->ecdsa = NULL; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->rsa = rsa; key->ed25519_privkey = ed25519; rsa = NULL; ecdsa = NULL; return key; fail: ssh_key_free(key); if (rsa != NULL) { mbedtls_pk_free(rsa); SAFE_FREE(rsa); } if (ecdsa != NULL) { mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } return NULL; } int pki_privkey_build_rsa(ssh_key key, ssh_string n, ssh_string e, ssh_string d, UNUSED_PARAM(ssh_string iqmp), ssh_string p, ssh_string q) { mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; int rc; key->rsa = malloc(sizeof(mbedtls_pk_context)); if (key->rsa == NULL) { return SSH_ERROR; } mbedtls_pk_init(key->rsa); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); mbedtls_pk_setup(key->rsa, pk_info); rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA); if (rc == 0) { goto fail; } rsa = mbedtls_pk_rsa(*key->rsa); rc = mbedtls_rsa_import_raw(rsa, ssh_string_data(n), ssh_string_len(n), ssh_string_data(p), ssh_string_len(p), ssh_string_data(q), ssh_string_len(q), ssh_string_data(d), ssh_string_len(d), ssh_string_data(e), ssh_string_len(e)); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "Failed to import private RSA key"); goto fail; } rc = mbedtls_rsa_complete(rsa); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "Failed to complete private RSA key"); goto fail; } rc = mbedtls_rsa_check_privkey(rsa); if (rc != 0) { SSH_LOG(SSH_LOG_WARN, "Inconsistent private RSA key"); goto fail; } return SSH_OK; fail: mbedtls_pk_free(key->rsa); SAFE_FREE(key->rsa); return SSH_ERROR; } int pki_pubkey_build_rsa(ssh_key key, ssh_string e, ssh_string n) { mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; int rc; key->rsa = malloc(sizeof(mbedtls_pk_context)); if (key->rsa == NULL) { return SSH_ERROR; } mbedtls_pk_init(key->rsa); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); mbedtls_pk_setup(key->rsa, pk_info); rc = mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA); if (rc == 0) { goto fail; } rsa = mbedtls_pk_rsa(*key->rsa); rc = mbedtls_mpi_read_binary(&rsa->N, ssh_string_data(n), ssh_string_len(n)); if (rc != 0) { goto fail; } rc = mbedtls_mpi_read_binary(&rsa->E, ssh_string_data(e), ssh_string_len(e)); if (rc != 0) { goto fail; } rsa->len = (mbedtls_mpi_bitlen(&rsa->N) + 7) >> 3; return SSH_OK; fail: mbedtls_pk_free(key->rsa); SAFE_FREE(key->rsa); return SSH_ERROR; } ssh_key pki_key_dup(const ssh_key key, int demote) { ssh_key new = NULL; int rc; const mbedtls_pk_info_t *pk_info = NULL; new = ssh_key_new(); if (new == NULL) { return NULL; } new->type = key->type; new->type_c = key->type_c; if (demote) { new->flags = SSH_KEY_FLAG_PUBLIC; } else { new->flags = key->flags; } switch(key->type) { case SSH_KEYTYPE_RSA: { mbedtls_rsa_context *rsa, *new_rsa; new->rsa = malloc(sizeof(mbedtls_pk_context)); if (new->rsa == NULL) { goto fail; } mbedtls_pk_init(new->rsa); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); mbedtls_pk_setup(new->rsa, pk_info); if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) && mbedtls_pk_can_do(new->rsa, MBEDTLS_PK_RSA)) { rsa = mbedtls_pk_rsa(*key->rsa); new_rsa = mbedtls_pk_rsa(*new->rsa); rc = mbedtls_mpi_copy(&new_rsa->N, &rsa->N); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->E, &rsa->E); if (rc != 0) { goto fail; } new_rsa->len = (mbedtls_mpi_bitlen(&new_rsa->N) + 7) >> 3; if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { rc = mbedtls_mpi_copy(&new_rsa->D, &rsa->D); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->P, &rsa->P); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->Q, &rsa->Q); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->DP, &rsa->DP); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->DQ, &rsa->DQ); if (rc != 0) { goto fail; } rc = mbedtls_mpi_copy(&new_rsa->QP, &rsa->QP); if (rc != 0) { goto fail; } } } else { goto fail; } break; } case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: new->ecdsa_nid = key->ecdsa_nid; new->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (new->ecdsa == NULL) { goto fail; } mbedtls_ecdsa_init(new->ecdsa); if (demote && ssh_key_is_private(key)) { rc = mbedtls_ecp_copy(&new->ecdsa->Q, &key->ecdsa->Q); if (rc != 0) { goto fail; } rc = mbedtls_ecp_group_copy(&new->ecdsa->grp, &key->ecdsa->grp); if (rc != 0) { goto fail; } } else { mbedtls_ecdsa_from_keypair(new->ecdsa, key->ecdsa); } break; case SSH_KEYTYPE_ED25519: rc = pki_ed25519_key_dup(new, key); if (rc != SSH_OK) { goto fail; } break; default: goto fail; } return new; fail: ssh_key_free(new); return NULL; } int pki_key_generate_rsa(ssh_key key, int parameter) { int rc; const mbedtls_pk_info_t *info = NULL; key->rsa = malloc(sizeof(mbedtls_pk_context)); if (key->rsa == NULL) { return SSH_ERROR; } mbedtls_pk_init(key->rsa); info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); rc = mbedtls_pk_setup(key->rsa, info); if (rc != 0) { return SSH_ERROR; } if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA)) { rc = mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key->rsa), mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context(), parameter, 65537); if (rc != 0) { mbedtls_pk_free(key->rsa); return SSH_ERROR; } } return SSH_OK; } int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what) { switch (k1->type) { case SSH_KEYTYPE_RSA: { mbedtls_rsa_context *rsa1, *rsa2; if (mbedtls_pk_can_do(k1->rsa, MBEDTLS_PK_RSA) && mbedtls_pk_can_do(k2->rsa, MBEDTLS_PK_RSA)) { if (mbedtls_pk_get_type(k1->rsa) != mbedtls_pk_get_type(k2->rsa) || mbedtls_pk_get_bitlen(k1->rsa) != mbedtls_pk_get_bitlen(k2->rsa)) { return 1; } rsa1 = mbedtls_pk_rsa(*k1->rsa); rsa2 = mbedtls_pk_rsa(*k2->rsa); if (mbedtls_mpi_cmp_mpi(&rsa1->N, &rsa2->N) != 0) { return 1; } if (mbedtls_mpi_cmp_mpi(&rsa1->E, &rsa2->E) != 0) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (mbedtls_mpi_cmp_mpi(&rsa1->P, &rsa2->P) != 0) { return 1; } if (mbedtls_mpi_cmp_mpi(&rsa1->Q, &rsa2->Q) != 0) { return 1; } } } break; } case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: { mbedtls_ecp_keypair *ecdsa1 = k1->ecdsa; mbedtls_ecp_keypair *ecdsa2 = k2->ecdsa; if (ecdsa1->grp.id != ecdsa2->grp.id) { return 1; } if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.X, &ecdsa2->Q.X)) { return 1; } if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Y, &ecdsa2->Q.Y)) { return 1; } if (mbedtls_mpi_cmp_mpi(&ecdsa1->Q.Z, &ecdsa2->Q.Z)) { return 1; } if (what == SSH_KEY_CMP_PRIVATE) { if (mbedtls_mpi_cmp_mpi(&ecdsa1->d, &ecdsa2->d)) { return 1; } } break; } case SSH_KEYTYPE_ED25519: /* ed25519 keys handled globally */ return 0; default: return 1; } return 0; } ssh_string make_ecpoint_string(const mbedtls_ecp_group *g, const mbedtls_ecp_point *p) { ssh_string s = NULL; size_t len = 1; int rc; s = ssh_string_new(len); if (s == NULL) { return NULL; } rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED, &len, ssh_string_data(s), ssh_string_len(s)); if (rc == MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) { SSH_STRING_FREE(s); s = ssh_string_new(len); if (s == NULL) { return NULL; } rc = mbedtls_ecp_point_write_binary(g, p, MBEDTLS_ECP_PF_UNCOMPRESSED, &len, ssh_string_data(s), ssh_string_len(s)); } if (rc != 0) { SSH_STRING_FREE(s); return NULL; } if (len != ssh_string_len(s)) { SSH_STRING_FREE(s); return NULL; } return s; } static const char* pki_key_ecdsa_nid_to_char(int nid) { switch (nid) { case NID_mbedtls_nistp256: return "nistp256"; case NID_mbedtls_nistp384: return "nistp384"; case NID_mbedtls_nistp521: return "nistp521"; default: break; } return "unknown"; } ssh_string pki_publickey_to_blob(const ssh_key key) { ssh_buffer buffer = NULL; ssh_string type_s = NULL; ssh_string e = NULL; ssh_string n = NULL; ssh_string str = NULL; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { return NULL; } if (key->cert != NULL) { rc = ssh_buffer_add_buffer(buffer, key->cert); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } goto makestring; } type_s = ssh_string_from_char(key->type_c); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } switch (key->type) { case SSH_KEYTYPE_RSA: { mbedtls_rsa_context *rsa; if (mbedtls_pk_can_do(key->rsa, MBEDTLS_PK_RSA) == 0) { SSH_BUFFER_FREE(buffer); return NULL; } rsa = mbedtls_pk_rsa(*key->rsa); e = ssh_make_bignum_string(&rsa->E); if (e == NULL) { goto fail; } n = ssh_make_bignum_string(&rsa->N); if (n == NULL) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, e) < 0) { goto fail; } if (ssh_buffer_add_ssh_string(buffer, n) < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; ssh_string_burn(n); SSH_STRING_FREE(n); n = NULL; break; } case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); if (type_s == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, type_s); SSH_STRING_FREE(type_s); if (rc < 0) { SSH_BUFFER_FREE(buffer); return NULL; } e = make_ecpoint_string(&key->ecdsa->grp, &key->ecdsa->Q); if (e == NULL) { SSH_BUFFER_FREE(buffer); return NULL; } rc = ssh_buffer_add_ssh_string(buffer, e); if (rc < 0) { goto fail; } ssh_string_burn(e); SSH_STRING_FREE(e); e = NULL; break; case SSH_KEYTYPE_ED25519: rc = pki_ed25519_public_key_to_blob(buffer, key); if (rc != SSH_OK) { goto fail; } break; default: goto fail; } makestring: str = ssh_string_new(ssh_buffer_get_len(buffer)); if (str == NULL) { goto fail; } rc = ssh_string_fill(str, ssh_buffer_get(buffer), ssh_buffer_get_len(buffer)); if (rc < 0) { goto fail; } SSH_BUFFER_FREE(buffer); return str; fail: SSH_BUFFER_FREE(buffer); ssh_string_burn(str); SSH_STRING_FREE(str); ssh_string_burn(e); SSH_STRING_FREE(e); ssh_string_burn(n); SSH_STRING_FREE(n); return NULL; } ssh_string pki_signature_to_blob(const ssh_signature sig) { ssh_string sig_blob = NULL; switch(sig->type) { case SSH_KEYTYPE_RSA: sig_blob = ssh_string_copy(sig->rsa_sig); break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: { ssh_string r; ssh_string s; ssh_buffer b; int rc; b = ssh_buffer_new(); if (b == NULL) { return NULL; } r = ssh_make_bignum_string(sig->ecdsa_sig.r); if (r == NULL) { SSH_BUFFER_FREE(b); return NULL; } rc = ssh_buffer_add_ssh_string(b, r); SSH_STRING_FREE(r); if (rc < 0) { SSH_BUFFER_FREE(b); return NULL; } s = ssh_make_bignum_string(sig->ecdsa_sig.s); if (s == NULL) { SSH_BUFFER_FREE(b); return NULL; } rc = ssh_buffer_add_ssh_string(b, s); SSH_STRING_FREE(s); if (rc < 0) { SSH_BUFFER_FREE(b); return NULL; } sig_blob = ssh_string_new(ssh_buffer_get_len(b)); if (sig_blob == NULL) { SSH_BUFFER_FREE(b); return NULL; } ssh_string_fill(sig_blob, ssh_buffer_get(b), ssh_buffer_get_len(b)); SSH_BUFFER_FREE(b); break; } case SSH_KEYTYPE_ED25519: sig_blob = pki_ed25519_signature_to_blob(sig); break; default: SSH_LOG(SSH_LOG_WARN, "Unknown signature key type: %s", sig->type_c); return NULL; } return sig_blob; } static ssh_signature pki_signature_from_rsa_blob(const ssh_key pubkey, const ssh_string sig_blob, ssh_signature sig) { size_t pad_len = 0; char *blob_orig = NULL; char *blob_padded_data = NULL; ssh_string sig_blob_padded = NULL; size_t rsalen = 0; size_t len = ssh_string_len(sig_blob); if (pubkey->rsa == NULL) { SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); goto errout; } rsalen = mbedtls_pk_get_bitlen(pubkey->rsa) / 8; if (len > rsalen) { SSH_LOG(SSH_LOG_WARN, "Signature is too big: %lu > %lu", (unsigned long) len, (unsigned long) rsalen); goto errout; } #ifdef DEBUG_CRYPTO SSH_LOG(SSH_LOG_WARN, "RSA signature len: %lu", (unsigned long)len); ssh_log_hexdump("RSA signature", ssh_string_data(sig_blob), len); #endif if (len == rsalen) { sig->rsa_sig = ssh_string_copy(sig_blob); } else { SSH_LOG(SSH_LOG_DEBUG, "RSA signature len %lu < %lu", (unsigned long) len, (unsigned long) rsalen); pad_len = rsalen - len; sig_blob_padded = ssh_string_new(rsalen); if (sig_blob_padded == NULL) { goto errout; } blob_padded_data = (char *) ssh_string_data(sig_blob_padded); blob_orig = (char *) ssh_string_data(sig_blob); explicit_bzero(blob_padded_data, pad_len); memcpy(blob_padded_data + pad_len, blob_orig, len); sig->rsa_sig = sig_blob_padded; } return sig; errout: ssh_signature_free(sig); return NULL; } ssh_signature pki_signature_from_blob(const ssh_key pubkey, const ssh_string sig_blob, enum ssh_keytypes_e type, enum ssh_digest_e hash_type) { ssh_signature sig = NULL; int rc; if (ssh_key_type_plain(pubkey->type) != type) { SSH_LOG(SSH_LOG_WARN, "Incompatible public key provided (%d) expecting (%d)", type, pubkey->type); return NULL; } sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = type; sig->type_c = ssh_key_signature_to_char(type, hash_type); sig->hash_type = hash_type; switch(type) { case SSH_KEYTYPE_RSA: sig = pki_signature_from_rsa_blob(pubkey, sig_blob, sig); if (sig == NULL) { return NULL; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: { ssh_buffer b; ssh_string r; ssh_string s; size_t rlen; b = ssh_buffer_new(); if (b == NULL) { ssh_signature_free(sig); return NULL; } rc = ssh_buffer_add_data(b, ssh_string_data(sig_blob), ssh_string_len(sig_blob)); if (rc < 0) { SSH_BUFFER_FREE(b); ssh_signature_free(sig); return NULL; } r = ssh_buffer_get_ssh_string(b); if (r == NULL) { SSH_BUFFER_FREE(b); ssh_signature_free(sig); return NULL; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("r", ssh_string_data(r), ssh_string_len(r)); #endif sig->ecdsa_sig.r = ssh_make_string_bn(r); ssh_string_burn(r); SSH_STRING_FREE(r); if (sig->ecdsa_sig.r == NULL) { SSH_BUFFER_FREE(b); ssh_signature_free(sig); return NULL; } s = ssh_buffer_get_ssh_string(b); rlen = ssh_buffer_get_len(b); SSH_BUFFER_FREE(b); if (s == NULL) { ssh_signature_free(sig); return NULL; } #ifdef DEBUG_CRYPTO ssh_log_hexdump("s", ssh_string_data(s), ssh_string_len(s)); #endif sig->ecdsa_sig.s = ssh_make_string_bn(s); ssh_string_burn(s); SSH_STRING_FREE(s); if (sig->ecdsa_sig.s == NULL) { ssh_signature_free(sig); return NULL; } if (rlen != 0) { SSH_LOG(SSH_LOG_WARN, "Signature has remaining bytes in inner " "sigblob: %lu", (unsigned long)rlen); ssh_signature_free(sig); return NULL; } break; } case SSH_KEYTYPE_ED25519: rc = pki_signature_from_ed25519_blob(sig, sig_blob); if (rc == SSH_ERROR) { ssh_signature_free(sig); return NULL; } break; default: SSH_LOG(SSH_LOG_WARN, "Unknown signature type"); return NULL; } return sig; } static ssh_string rsa_do_sign_hash(const unsigned char *digest, int dlen, mbedtls_pk_context *privkey, enum ssh_digest_e hash_type) { ssh_string sig_blob = NULL; mbedtls_md_type_t md = 0; unsigned char *sig = NULL; size_t slen; int ok; switch (hash_type) { case SSH_DIGEST_SHA1: md = MBEDTLS_MD_SHA1; break; case SSH_DIGEST_SHA256: md = MBEDTLS_MD_SHA256; break; case SSH_DIGEST_SHA512: md = MBEDTLS_MD_SHA512; break; case SSH_DIGEST_AUTO: default: SSH_LOG(SSH_LOG_WARN, "Incompatible key algorithm"); return NULL; } sig = malloc(mbedtls_pk_get_bitlen(privkey) / 8); if (sig == NULL) { return NULL; } ok = mbedtls_pk_sign(privkey, md, digest, dlen, sig, &slen, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (ok != 0) { SAFE_FREE(sig); return NULL; } sig_blob = ssh_string_new(slen); if (sig_blob == NULL) { SAFE_FREE(sig); return NULL; } ssh_string_fill(sig_blob, sig, slen); explicit_bzero(sig, slen); SAFE_FREE(sig); return sig_blob; } ssh_signature pki_do_sign_hash(const ssh_key privkey, const unsigned char *hash, size_t hlen, enum ssh_digest_e hash_type) { ssh_signature sig = NULL; int rc; sig = ssh_signature_new(); if (sig == NULL) { return NULL; } sig->type = privkey->type; sig->type_c = ssh_key_signature_to_char(privkey->type, hash_type); sig->hash_type = hash_type; switch(privkey->type) { case SSH_KEYTYPE_RSA: sig->rsa_sig = rsa_do_sign_hash(hash, hlen, privkey->rsa, hash_type); if (sig->rsa_sig == NULL) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: sig->ecdsa_sig.r = bignum_new(); if (sig->ecdsa_sig.r == NULL) { return NULL; } sig->ecdsa_sig.s = bignum_new(); if (sig->ecdsa_sig.s == NULL) { bignum_safe_free(sig->ecdsa_sig.r); return NULL; } rc = mbedtls_ecdsa_sign(&privkey->ecdsa->grp, sig->ecdsa_sig.r, sig->ecdsa_sig.s, &privkey->ecdsa->d, hash, hlen, mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (rc != 0) { ssh_signature_free(sig); return NULL; } break; case SSH_KEYTYPE_ED25519: rc = pki_ed25519_sign(privkey, sig, hash, hlen); if (rc != SSH_OK) { ssh_signature_free(sig); return NULL; } break; default: ssh_signature_free(sig); return NULL; } return sig; } /** * @internal * * @brief Sign the given input data. The digest of to be signed is calculated * internally as necessary. * * @param[in] privkey The private key to be used for signing. * @param[in] hash_type The digest algorithm to be used. * @param[in] input The data to be signed. * @param[in] input_len The length of the data to be signed. * * @return a newly allocated ssh_signature or NULL on error. */ ssh_signature pki_sign_data(const ssh_key privkey, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { unsigned char hash[SHA512_DIGEST_LEN] = {0}; const unsigned char *sign_input = NULL; uint32_t hlen = 0; int rc; if (privkey == NULL || !ssh_key_is_private(privkey) || input == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_sign_data()"); return NULL; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(privkey, hash_type); if (rc != SSH_OK) { return NULL; } switch (hash_type) { case SSH_DIGEST_SHA256: sha256(input, input_len, hash); hlen = SHA256_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA384: sha384(input, input_len, hash); hlen = SHA384_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA512: sha512(input, input_len, hash); hlen = SHA512_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_SHA1: sha1(input, input_len, hash); hlen = SHA_DIGEST_LEN; sign_input = hash; break; case SSH_DIGEST_AUTO: if (privkey->type == SSH_KEYTYPE_ED25519) { /* SSH_DIGEST_AUTO should only be used with ed25519 */ sign_input = input; hlen = input_len; break; } FALL_THROUGH; default: SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d", hash_type); return NULL; } return pki_do_sign_hash(privkey, sign_input, hlen, hash_type); } /** * @internal * * @brief Verify the signature of a given input. The digest of the input is * calculated internally as necessary. * * @param[in] signature The signature to be verified. * @param[in] pubkey The public key used to verify the signature. * @param[in] input The signed data. * @param[in] input_len The length of the signed data. * * @return SSH_OK if the signature is valid; SSH_ERROR otherwise. */ int pki_verify_data_signature(ssh_signature signature, const ssh_key pubkey, const unsigned char *input, size_t input_len) { unsigned char hash[SHA512_DIGEST_LEN] = {0}; const unsigned char *verify_input = NULL; uint32_t hlen = 0; mbedtls_md_type_t md = 0; int rc; if (pubkey == NULL || ssh_key_is_private(pubkey) || input == NULL || signature == NULL) { SSH_LOG(SSH_LOG_TRACE, "Bad parameter provided to " "pki_verify_data_signature()"); return SSH_ERROR; } /* Check if public key and hash type are compatible */ rc = pki_key_check_hash_compatible(pubkey, signature->hash_type); if (rc != SSH_OK) { return SSH_ERROR; } switch (signature->hash_type) { case SSH_DIGEST_SHA256: sha256(input, input_len, hash); hlen = SHA256_DIGEST_LEN; md = MBEDTLS_MD_SHA256; verify_input = hash; break; case SSH_DIGEST_SHA384: sha384(input, input_len, hash); hlen = SHA384_DIGEST_LEN; md = MBEDTLS_MD_SHA384; verify_input = hash; break; case SSH_DIGEST_SHA512: sha512(input, input_len, hash); hlen = SHA512_DIGEST_LEN; md = MBEDTLS_MD_SHA512; verify_input = hash; break; case SSH_DIGEST_SHA1: sha1(input, input_len, hash); hlen = SHA_DIGEST_LEN; md = MBEDTLS_MD_SHA1; verify_input = hash; break; case SSH_DIGEST_AUTO: if (pubkey->type == SSH_KEYTYPE_ED25519 || pubkey->type == SSH_KEYTYPE_ED25519_CERT01) { verify_input = input; hlen = input_len; break; } FALL_THROUGH; default: SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", signature->hash_type); return SSH_ERROR; } switch (pubkey->type) { case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA_CERT01: rc = mbedtls_pk_verify(pubkey->rsa, md, hash, hlen, ssh_string_data(signature->rsa_sig), ssh_string_len(signature->rsa_sig)); if (rc != 0) { char error_buf[100]; mbedtls_strerror(rc, error_buf, 100); SSH_LOG(SSH_LOG_TRACE, "RSA error: %s", error_buf); return SSH_ERROR; } break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P256_CERT01: case SSH_KEYTYPE_ECDSA_P384_CERT01: case SSH_KEYTYPE_ECDSA_P521_CERT01: rc = mbedtls_ecdsa_verify(&pubkey->ecdsa->grp, hash, hlen, &pubkey->ecdsa->Q, signature->ecdsa_sig.r, signature->ecdsa_sig.s); if (rc != 0) { char error_buf[100]; mbedtls_strerror(rc, error_buf, 100); SSH_LOG(SSH_LOG_TRACE, "ECDSA error: %s", error_buf); return SSH_ERROR; } break; case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519_CERT01: rc = pki_ed25519_verify(pubkey, signature, verify_input, hlen); if (rc != SSH_OK) { SSH_LOG(SSH_LOG_TRACE, "ED25519 error: Signature invalid"); return SSH_ERROR; } break; default: SSH_LOG(SSH_LOG_TRACE, "Unknown public key type"); return SSH_ERROR; } return SSH_OK; } const char *pki_key_ecdsa_nid_to_name(int nid) { switch (nid) { case NID_mbedtls_nistp256: return "ecdsa-sha2-nistp256"; case NID_mbedtls_nistp384: return "ecdsa-sha2-nistp384"; case NID_mbedtls_nistp521: return "ecdsa-sha2-nistp521"; default: break; } return "unknown"; } int pki_key_ecdsa_nid_from_name(const char *name) { if (strcmp(name, "nistp256") == 0) { return NID_mbedtls_nistp256; } else if (strcmp(name, "nistp384") == 0) { return NID_mbedtls_nistp384; } else if (strcmp(name, "nistp521") == 0) { return NID_mbedtls_nistp521; } return -1; } static mbedtls_ecp_group_id pki_key_ecdsa_nid_to_mbed_gid(int nid) { switch (nid) { case NID_mbedtls_nistp256: return MBEDTLS_ECP_DP_SECP256R1; case NID_mbedtls_nistp384: return MBEDTLS_ECP_DP_SECP384R1; case NID_mbedtls_nistp521: return MBEDTLS_ECP_DP_SECP521R1; } return MBEDTLS_ECP_DP_NONE; } int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) { int rc; mbedtls_ecp_keypair keypair; mbedtls_ecp_group group; mbedtls_ecp_point Q; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { return SSH_ERROR; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecp_keypair_init(&keypair); mbedtls_ecp_group_init(&group); mbedtls_ecp_point_init(&Q); rc = mbedtls_ecp_group_load(&group, pki_key_ecdsa_nid_to_mbed_gid(nid)); if (rc != 0) { goto fail; } rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e), ssh_string_len(e)); if (rc != 0) { goto fail; } rc = mbedtls_ecp_copy(&keypair.Q, &Q); if (rc != 0) { goto fail; } rc = mbedtls_ecp_group_copy(&keypair.grp, &group); if (rc != 0) { goto fail; } rc = mbedtls_mpi_read_binary(&keypair.d, ssh_string_data(exp), ssh_string_len(exp)); if (rc != 0) { goto fail; } rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair); if (rc != 0) { goto fail; } mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&group); mbedtls_ecp_keypair_free(&keypair); return SSH_OK; fail: mbedtls_ecdsa_free(key->ecdsa); mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&group); mbedtls_ecp_keypair_free(&keypair); SAFE_FREE(key->ecdsa); return SSH_ERROR; } int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) { int rc; mbedtls_ecp_keypair keypair; mbedtls_ecp_group group; mbedtls_ecp_point Q; key->ecdsa_nid = nid; key->type_c = pki_key_ecdsa_nid_to_name(nid); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { return SSH_ERROR; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecp_keypair_init(&keypair); mbedtls_ecp_group_init(&group); mbedtls_ecp_point_init(&Q); rc = mbedtls_ecp_group_load(&group, pki_key_ecdsa_nid_to_mbed_gid(nid)); if (rc != 0) { goto fail; } rc = mbedtls_ecp_point_read_binary(&group, &Q, ssh_string_data(e), ssh_string_len(e)); if (rc != 0) { goto fail; } rc = mbedtls_ecp_copy(&keypair.Q, &Q); if (rc != 0) { goto fail; } rc = mbedtls_ecp_group_copy(&keypair.grp, &group); if (rc != 0) { goto fail; } mbedtls_mpi_init(&keypair.d); rc = mbedtls_ecdsa_from_keypair(key->ecdsa, &keypair); if (rc != 0) { goto fail; } mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&group); mbedtls_ecp_keypair_free(&keypair); return SSH_OK; fail: mbedtls_ecdsa_free(key->ecdsa); mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&group); mbedtls_ecp_keypair_free(&keypair); SAFE_FREE(key->ecdsa); return SSH_ERROR; } int pki_key_generate_ecdsa(ssh_key key, int parameter) { int ok; switch (parameter) { case 384: key->ecdsa_nid = NID_mbedtls_nistp384; key->type = SSH_KEYTYPE_ECDSA_P384; break; case 521: key->ecdsa_nid = NID_mbedtls_nistp521; key->type = SSH_KEYTYPE_ECDSA_P521; break; case 256: default: key->ecdsa_nid = NID_mbedtls_nistp256; key->type = SSH_KEYTYPE_ECDSA_P256; break; } key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { return SSH_ERROR; } mbedtls_ecdsa_init(key->ecdsa); ok = mbedtls_ecdsa_genkey(key->ecdsa, pki_key_ecdsa_nid_to_mbed_gid(key->ecdsa_nid), mbedtls_ctr_drbg_random, ssh_get_mbedtls_ctr_drbg_context()); if (ok != 0) { mbedtls_ecdsa_free(key->ecdsa); SAFE_FREE(key->ecdsa); } return SSH_OK; } int pki_privkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey, ssh_string privkey) { (void) key; (void) p; (void) q; (void) g; (void) pubkey; (void) privkey; return SSH_ERROR; } int pki_pubkey_build_dss(ssh_key key, ssh_string p, ssh_string q, ssh_string g, ssh_string pubkey) { (void) key; (void) p; (void) q; (void) g; (void) pubkey; return SSH_ERROR; } int pki_key_generate_dss(ssh_key key, int parameter) { (void) key; (void) parameter; return SSH_ERROR; } #endif /* HAVE_LIBMBEDCRYPTO */ ================================================ FILE: src/libssh/src/poll.c ================================================ /* * poll.c - poll wrapper * * This file is part of the SSH Library * * Copyright (c) 2009-2013 by Andreas Schneider * Copyright (c) 2003-2013 by Aris Adamantiadis * Copyright (c) 2009 Aleksandar Kanchev * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include "libssh/priv.h" #include "libssh/libssh.h" #include "libssh/poll.h" #include "libssh/socket.h" #include "libssh/session.h" #include "libssh/misc.h" #ifdef WITH_SERVER #include "libssh/server.h" #endif #ifndef SSH_POLL_CTX_CHUNK #define SSH_POLL_CTX_CHUNK 5 #endif /** * @defgroup libssh_poll The SSH poll functions. * @ingroup libssh * * Add a generic way to handle sockets asynchronously. * * It's based on poll objects, each of which store a socket, its events and a * callback, which gets called whenever an event is set. The poll objects are * attached to a poll context, which should be allocated on per thread basis. * * Polling the poll context will poll all the attached poll objects and call * their callbacks (handlers) if any of the socket events are set. This should * be done within the main loop of an application. * * @{ */ struct ssh_poll_handle_struct { ssh_poll_ctx ctx; ssh_session session; union { socket_t fd; size_t idx; } x; short events; int lock; ssh_poll_callback cb; void *cb_data; }; struct ssh_poll_ctx_struct { ssh_poll_handle *pollptrs; ssh_pollfd_t *pollfds; size_t polls_allocated; size_t polls_used; size_t chunk_size; }; #ifdef HAVE_POLL #include void ssh_poll_init(void) { return; } void ssh_poll_cleanup(void) { return; } int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) { return poll((struct pollfd *) fds, nfds, timeout); } #else /* HAVE_POLL */ typedef int (*poll_fn)(ssh_pollfd_t *, nfds_t, int); static poll_fn ssh_poll_emu; #include #include #ifdef _WIN32 #ifndef STRICT #define STRICT #endif /* STRICT */ #include #include #include #else /* _WIN32 */ #include #include # ifdef HAVE_SYS_TIME_H # include # endif #endif /* _WIN32 */ #ifdef HAVE_UNISTD_H #include #endif static bool bsd_socket_not_connected(int sock_err) { switch (sock_err) { #ifdef _WIN32 case WSAENOTCONN: #else case ENOTCONN: #endif return true; default: return false; } return false; } static bool bsd_socket_reset(int sock_err) { switch (sock_err) { #ifdef _WIN32 case WSAECONNABORTED: case WSAECONNRESET: case WSAENETRESET: case WSAESHUTDOWN: case WSAECONNREFUSED: case WSAETIMEDOUT: #else case ECONNABORTED: case ECONNRESET: case ENETRESET: case ESHUTDOWN: #endif return true; default: return false; } return false; } static short bsd_socket_compute_revents(int fd, short events) { int save_errno = errno; int sock_errno = errno; char data[64] = {0}; short revents = 0; int flags = MSG_PEEK; int ret; #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; #endif /* support for POLLHUP */ #ifdef _WIN32 WSASetLastError(0); #endif ret = recv(fd, data, 64, flags); errno = save_errno; #ifdef _WIN32 sock_errno = WSAGetLastError(); WSASetLastError(0); #endif if (ret > 0 || bsd_socket_not_connected(sock_errno)) { revents = (POLLIN | POLLRDNORM) & events; } else if (ret == 0 || bsd_socket_reset(sock_errno)) { errno = sock_errno; revents = POLLHUP; } else { revents = POLLERR; } return revents; } /* * This is a poll(2)-emulation using select for systems not providing a native * poll implementation. * * Keep in mind that select is terribly inefficient. The interface is simply not * meant to be used with maximum descriptor value greater, say, 32 or so. With * a value as high as 1024 on Linux you'll pay dearly in every single call. * poll() will be orders of magnitude faster. */ static int bsd_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) { fd_set readfds, writefds, exceptfds; struct timeval tv, *ptv = NULL; socket_t max_fd; int rc; nfds_t i; if (fds == NULL) { errno = EFAULT; return -1; } ZERO_STRUCT(readfds); FD_ZERO(&readfds); ZERO_STRUCT(writefds); FD_ZERO(&writefds); ZERO_STRUCT(exceptfds); FD_ZERO(&exceptfds); /* compute fd_sets and find largest descriptor */ for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) { if (fds[i].fd == SSH_INVALID_SOCKET) { continue; } #ifndef _WIN32 if (fds[i].fd >= FD_SETSIZE) { rc = -1; break; } #endif if (fds[i].events & (POLLIN | POLLRDNORM)) { FD_SET (fds[i].fd, &readfds); } if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { FD_SET (fds[i].fd, &writefds); } if (fds[i].events & (POLLPRI | POLLRDBAND)) { FD_SET (fds[i].fd, &exceptfds); } if (fds[i].fd > max_fd && (fds[i].events & (POLLIN | POLLOUT | POLLPRI | POLLRDNORM | POLLRDBAND | POLLWRNORM | POLLWRBAND))) { max_fd = fds[i].fd; rc = 0; } } if (max_fd == SSH_INVALID_SOCKET || rc == -1) { errno = EINVAL; return -1; } if (timeout < 0) { ptv = NULL; } else { ptv = &tv; if (timeout == 0) { tv.tv_sec = 0; tv.tv_usec = 0; } else { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; } } rc = select(max_fd + 1, &readfds, &writefds, &exceptfds, ptv); if (rc < 0) { return -1; } /* A timeout occured */ if (rc == 0) { return 0; } for (rc = 0, i = 0; i < nfds; i++) { if (fds[i].fd >= 0) { fds[i].revents = 0; if (FD_ISSET(fds[i].fd, &readfds)) { fds[i].revents = bsd_socket_compute_revents(fds[i].fd, fds[i].events); } if (FD_ISSET(fds[i].fd, &writefds)) { fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND); } if (FD_ISSET(fds[i].fd, &exceptfds)) { fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND); } if (fds[i].revents != 0) { rc++; } } else { fds[i].revents = POLLNVAL; } } return rc; } void ssh_poll_init(void) { ssh_poll_emu = bsd_poll; } void ssh_poll_cleanup(void) { ssh_poll_emu = bsd_poll; } int ssh_poll(ssh_pollfd_t *fds, nfds_t nfds, int timeout) { return (ssh_poll_emu)(fds, nfds, timeout); } #endif /* HAVE_POLL */ /** * @brief Allocate a new poll object, which could be used within a poll context. * * @param fd Socket that will be polled. * @param events Poll events that will be monitored for the socket. i.e. * POLLIN, POLLPRI, POLLOUT * @param cb Function to be called if any of the events are set. * The prototype of cb is: * int (*ssh_poll_callback)(ssh_poll_handle p, socket_t fd, * int revents, void *userdata); * @param userdata Userdata to be passed to the callback function. NULL if * not needed. * * @return A new poll object, NULL on error */ ssh_poll_handle ssh_poll_new(socket_t fd, short events, ssh_poll_callback cb, void *userdata) { ssh_poll_handle p; p = malloc(sizeof(struct ssh_poll_handle_struct)); if (p == NULL) { return NULL; } ZERO_STRUCTP(p); p->x.fd = fd; p->events = events; p->cb = cb; p->cb_data = userdata; return p; } /** * @brief Free a poll object. * * @param p Pointer to an already allocated poll object. */ void ssh_poll_free(ssh_poll_handle p) { if(p->ctx != NULL){ ssh_poll_ctx_remove(p->ctx,p); p->ctx=NULL; } SAFE_FREE(p); } /** * @brief Get the poll context of a poll object. * * @param p Pointer to an already allocated poll object. * * @return Poll context or NULL if the poll object isn't attached. */ ssh_poll_ctx ssh_poll_get_ctx(ssh_poll_handle p) { return p->ctx; } /** * @brief Get the events of a poll object. * * @param p Pointer to an already allocated poll object. * * @return Poll events. */ short ssh_poll_get_events(ssh_poll_handle p) { return p->events; } /** * @brief Set the events of a poll object. The events will also be propagated * to an associated poll context. * * @param p Pointer to an already allocated poll object. * @param events Poll events. */ void ssh_poll_set_events(ssh_poll_handle p, short events) { p->events = events; if (p->ctx != NULL && !p->lock) { p->ctx->pollfds[p->x.idx].events = events; } } /** * @brief Set the file descriptor of a poll object. The FD will also be propagated * to an associated poll context. * * @param p Pointer to an already allocated poll object. * @param fd New file descriptor. */ void ssh_poll_set_fd(ssh_poll_handle p, socket_t fd) { if (p->ctx != NULL) { p->ctx->pollfds[p->x.idx].fd = fd; } else { p->x.fd = fd; } } /** * @brief Add extra events to a poll object. Duplicates are ignored. * The events will also be propagated to an associated poll context. * * @param p Pointer to an already allocated poll object. * @param events Poll events. */ void ssh_poll_add_events(ssh_poll_handle p, short events) { ssh_poll_set_events(p, ssh_poll_get_events(p) | events); } /** * @brief Remove events from a poll object. Non-existent are ignored. * The events will also be propagated to an associated poll context. * * @param p Pointer to an already allocated poll object. * @param events Poll events. */ void ssh_poll_remove_events(ssh_poll_handle p, short events) { ssh_poll_set_events(p, ssh_poll_get_events(p) & ~events); } /** * @brief Get the raw socket of a poll object. * * @param p Pointer to an already allocated poll object. * * @return Raw socket. */ socket_t ssh_poll_get_fd(ssh_poll_handle p) { if (p->ctx != NULL) { return p->ctx->pollfds[p->x.idx].fd; } return p->x.fd; } /** * @brief Set the callback of a poll object. * * @param p Pointer to an already allocated poll object. * @param cb Function to be called if any of the events are set. * @param userdata Userdata to be passed to the callback function. NULL if * not needed. */ void ssh_poll_set_callback(ssh_poll_handle p, ssh_poll_callback cb, void *userdata) { if (cb != NULL) { p->cb = cb; p->cb_data = userdata; } } /** * @brief Create a new poll context. It could be associated with many poll object * which are going to be polled at the same time as the poll context. You * would need a single poll context per thread. * * @param chunk_size The size of the memory chunk that will be allocated, when * more memory is needed. This is for efficiency reasons, * i.e. don't allocate memory for each new poll object, but * for the next 5. Set it to 0 if you want to use the * library's default value. */ ssh_poll_ctx ssh_poll_ctx_new(size_t chunk_size) { ssh_poll_ctx ctx; ctx = malloc(sizeof(struct ssh_poll_ctx_struct)); if (ctx == NULL) { return NULL; } ZERO_STRUCTP(ctx); if (chunk_size == 0) { chunk_size = SSH_POLL_CTX_CHUNK; } ctx->chunk_size = chunk_size; return ctx; } /** * @brief Free a poll context. * * @param ctx Pointer to an already allocated poll context. */ void ssh_poll_ctx_free(ssh_poll_ctx ctx) { if (ctx->polls_allocated > 0) { while (ctx->polls_used > 0){ ssh_poll_handle p = ctx->pollptrs[0]; /* * The free function calls ssh_poll_ctx_remove() and decrements * ctx->polls_used */ ssh_poll_free(p); } SAFE_FREE(ctx->pollptrs); SAFE_FREE(ctx->pollfds); } SAFE_FREE(ctx); } static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size) { ssh_poll_handle *pollptrs; ssh_pollfd_t *pollfds; pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * new_size); if (pollptrs == NULL) { return -1; } ctx->pollptrs = pollptrs; pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size); if (pollfds == NULL) { pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * ctx->polls_allocated); if (pollptrs == NULL) { return -1; } ctx->pollptrs = pollptrs; return -1; } ctx->pollfds = pollfds; ctx->polls_allocated = new_size; return 0; } /** * @brief Add a poll object to a poll context. * * @param ctx Pointer to an already allocated poll context. * @param p Pointer to an already allocated poll object. * * @return 0 on success, < 0 on error */ int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p) { socket_t fd; if (p->ctx != NULL) { /* already attached to a context */ return -1; } if (ctx->polls_used == ctx->polls_allocated && ssh_poll_ctx_resize(ctx, ctx->polls_allocated + ctx->chunk_size) < 0) { return -1; } fd = p->x.fd; p->x.idx = ctx->polls_used++; ctx->pollptrs[p->x.idx] = p; ctx->pollfds[p->x.idx].fd = fd; ctx->pollfds[p->x.idx].events = p->events; ctx->pollfds[p->x.idx].revents = 0; p->ctx = ctx; return 0; } /** * @brief Add a socket object to a poll context. * * @param ctx Pointer to an already allocated poll context. * @param s A SSH socket handle * * @return 0 on success, < 0 on error */ int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, ssh_socket s) { ssh_poll_handle p; int ret; p = ssh_socket_get_poll_handle(s); if (p == NULL) { return -1; } ret = ssh_poll_ctx_add(ctx,p); return ret; } /** * @brief Remove a poll object from a poll context. * * @param ctx Pointer to an already allocated poll context. * @param p Pointer to an already allocated poll object. */ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) { size_t i; i = p->x.idx; p->x.fd = ctx->pollfds[i].fd; p->ctx = NULL; ctx->polls_used--; /* fill the empty poll slot with the last one */ if (ctx->polls_used > 0 && ctx->polls_used != i) { ctx->pollfds[i] = ctx->pollfds[ctx->polls_used]; ctx->pollptrs[i] = ctx->pollptrs[ctx->polls_used]; ctx->pollptrs[i]->x.idx = i; } /* this will always leave at least chunk_size polls allocated */ if (ctx->polls_allocated - ctx->polls_used > ctx->chunk_size) { ssh_poll_ctx_resize(ctx, ctx->polls_allocated - ctx->chunk_size); } } /** * @brief Poll all the sockets associated through a poll object with a * poll context. If any of the events are set after the poll, the * call back function of the socket will be called. * This function should be called once within the programs main loop. * * @param ctx Pointer to an already allocated poll context. * @param timeout An upper limit on the time for which ssh_poll_ctx() will * block, in milliseconds. Specifying a negative value * means an infinite timeout. This parameter is passed to * the poll() function. * @returns SSH_OK No error. * SSH_ERROR Error happened during the poll. * SSH_AGAIN Timeout occured */ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout) { int rc; size_t i, used; ssh_poll_handle p; socket_t fd; int revents; struct ssh_timestamp ts; if (ctx->polls_used == 0) { return SSH_ERROR; } ssh_timestamp_init(&ts); do { int tm = ssh_timeout_update(&ts, timeout); rc = ssh_poll(ctx->pollfds, ctx->polls_used, tm); } while (rc == -1 && errno == EINTR); if (rc < 0) { return SSH_ERROR; } if (rc == 0) { return SSH_AGAIN; } used = ctx->polls_used; for (i = 0; i < used && rc > 0; ) { if (!ctx->pollfds[i].revents || ctx->pollptrs[i]->lock) { i++; } else { int ret; p = ctx->pollptrs[i]; fd = ctx->pollfds[i].fd; revents = ctx->pollfds[i].revents; /* avoid having any event caught during callback */ ctx->pollfds[i].events = 0; p->lock = 1; if (p->cb && (ret = p->cb(p, fd, revents, p->cb_data)) < 0) { if (ret == -2) { return -1; } /* the poll was removed, reload the used counter and start again */ used = ctx->polls_used; i = 0; } else { ctx->pollfds[i].revents = 0; ctx->pollfds[i].events = p->events; p->lock = 0; i++; } rc--; } } return rc; } /** * @internal * @brief gets the default poll structure for the current session, * when used in blocking mode. * @param session SSH session * @returns the default ssh_poll_ctx */ ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session){ if(session->default_poll_ctx != NULL) return session->default_poll_ctx; /* 2 is enough for the default one */ session->default_poll_ctx = ssh_poll_ctx_new(2); return session->default_poll_ctx; } /* public event API */ struct ssh_event_fd_wrapper { ssh_event_callback cb; void * userdata; }; struct ssh_event_struct { ssh_poll_ctx ctx; #ifdef WITH_SERVER struct ssh_list *sessions; #endif }; /** * @brief Create a new event context. It could be associated with many * ssh_session objects and socket fd which are going to be polled at the * same time as the event context. You would need a single event context * per thread. * * @return The ssh_event object on success, NULL on failure. */ ssh_event ssh_event_new(void) { ssh_event event; event = malloc(sizeof(struct ssh_event_struct)); if (event == NULL) { return NULL; } ZERO_STRUCTP(event); event->ctx = ssh_poll_ctx_new(2); if(event->ctx == NULL) { free(event); return NULL; } #ifdef WITH_SERVER event->sessions = ssh_list_new(); if(event->sessions == NULL) { ssh_poll_ctx_free(event->ctx); free(event); return NULL; } #endif return event; } static int ssh_event_fd_wrapper_callback(ssh_poll_handle p, socket_t fd, int revents, void *userdata) { struct ssh_event_fd_wrapper *pw = (struct ssh_event_fd_wrapper *)userdata; (void)p; if(pw->cb != NULL) { return pw->cb(fd, revents, pw->userdata); } return 0; } /** * @brief Add a fd to the event and assign it a callback, * when used in blocking mode. * @param event The ssh_event * @param fd Socket that will be polled. * @param events Poll events that will be monitored for the socket. i.e. * POLLIN, POLLPRI, POLLOUT * @param cb Function to be called if any of the events are set. * The prototype of cb is: * int (*ssh_event_callback)(socket_t fd, int revents, * void *userdata); * @param userdata Userdata to be passed to the callback function. NULL if * not needed. * * @returns SSH_OK on success * SSH_ERROR on failure */ int ssh_event_add_fd(ssh_event event, socket_t fd, short events, ssh_event_callback cb, void *userdata) { ssh_poll_handle p; struct ssh_event_fd_wrapper *pw; if(event == NULL || event->ctx == NULL || cb == NULL || fd == SSH_INVALID_SOCKET) { return SSH_ERROR; } pw = malloc(sizeof(struct ssh_event_fd_wrapper)); if(pw == NULL) { return SSH_ERROR; } pw->cb = cb; pw->userdata = userdata; /* pw is freed by ssh_event_remove_fd */ p = ssh_poll_new(fd, events, ssh_event_fd_wrapper_callback, pw); if(p == NULL) { free(pw); return SSH_ERROR; } if(ssh_poll_ctx_add(event->ctx, p) < 0) { free(pw); ssh_poll_free(p); return SSH_ERROR; } return SSH_OK; } /** * @brief Add a poll handle to the event. * * @param event the ssh_event * * @param p the poll handle * * @returns SSH_OK on success * SSH_ERROR on failure */ int ssh_event_add_poll(ssh_event event, ssh_poll_handle p) { return ssh_poll_ctx_add(event->ctx, p); } /** * @brief remove a poll handle to the event. * * @param event the ssh_event * * @param p the poll handle */ void ssh_event_remove_poll(ssh_event event, ssh_poll_handle p) { ssh_poll_ctx_remove(event->ctx,p); } /** * @brief remove the poll handle from session and assign them to a event, * when used in blocking mode. * * @param event The ssh_event object * @param session The session to add to the event. * * @returns SSH_OK on success * SSH_ERROR on failure */ int ssh_event_add_session(ssh_event event, ssh_session session) { ssh_poll_handle p; #ifdef WITH_SERVER struct ssh_iterator *iterator; #endif if(event == NULL || event->ctx == NULL || session == NULL) { return SSH_ERROR; } if(session->default_poll_ctx == NULL) { return SSH_ERROR; } while (session->default_poll_ctx->polls_used > 0) { p = session->default_poll_ctx->pollptrs[0]; /* * ssh_poll_ctx_remove() decrements * session->default_poll_ctx->polls_used */ ssh_poll_ctx_remove(session->default_poll_ctx, p); ssh_poll_ctx_add(event->ctx, p); /* associate the pollhandler with a session so we can put it back * at ssh_event_free() */ p->session = session; } #ifdef WITH_SERVER iterator = ssh_list_get_iterator(event->sessions); while(iterator != NULL) { if((ssh_session)iterator->data == session) { /* allow only one instance of this session */ return SSH_OK; } iterator = iterator->next; } if(ssh_list_append(event->sessions, session) == SSH_ERROR) { return SSH_ERROR; } #endif return SSH_OK; } /** * @brief Add a connector to the SSH event loop * * @param[in] event The SSH event loop * * @param[in] connector The connector object * * @return SSH_OK * * @return SSH_ERROR in case of error */ int ssh_event_add_connector(ssh_event event, ssh_connector connector){ return ssh_connector_set_event(connector, event); } /** * @brief Poll all the sockets and sessions associated through an event object.i * * If any of the events are set after the poll, the call back functions of the * sessions or sockets will be called. * This function should be called once within the programs main loop. * * @param event The ssh_event object to poll. * * @param timeout An upper limit on the time for which the poll will * block, in milliseconds. Specifying a negative value * means an infinite timeout. This parameter is passed to * the poll() function. * @returns SSH_OK on success. * SSH_ERROR Error happened during the poll. * SSH_AGAIN Timeout occured */ int ssh_event_dopoll(ssh_event event, int timeout) { int rc; if(event == NULL || event->ctx == NULL) { return SSH_ERROR; } rc = ssh_poll_ctx_dopoll(event->ctx, timeout); return rc; } /** * @brief Remove a socket fd from an event context. * * @param event The ssh_event object. * @param fd The fd to remove. * * @returns SSH_OK on success * SSH_ERROR on failure */ int ssh_event_remove_fd(ssh_event event, socket_t fd) { register size_t i, used; int rc = SSH_ERROR; if(event == NULL || event->ctx == NULL) { return SSH_ERROR; } used = event->ctx->polls_used; for (i = 0; i < used; i++) { if(fd == event->ctx->pollfds[i].fd) { ssh_poll_handle p = event->ctx->pollptrs[i]; if (p->session != NULL){ /* we cannot free that handle, it's owned by its session */ continue; } if (p->cb == ssh_event_fd_wrapper_callback) { struct ssh_event_fd_wrapper *pw = p->cb_data; SAFE_FREE(pw); } /* * The free function calls ssh_poll_ctx_remove() and decrements * event->ctx->polls_used. */ ssh_poll_free(p); rc = SSH_OK; /* restart the loop */ used = event->ctx->polls_used; i = 0; } } return rc; } /** * @brief Remove a session object from an event context. * * @param event The ssh_event object. * @param session The session to remove. * * @returns SSH_OK on success * SSH_ERROR on failure */ int ssh_event_remove_session(ssh_event event, ssh_session session) { ssh_poll_handle p; register size_t i, used; int rc = SSH_ERROR; #ifdef WITH_SERVER struct ssh_iterator *iterator; #endif if(event == NULL || event->ctx == NULL || session == NULL) { return SSH_ERROR; } used = event->ctx->polls_used; for(i = 0; i < used; i++) { p = event->ctx->pollptrs[i]; if(p->session == session){ /* * ssh_poll_ctx_remove() decrements * event->ctx->polls_used */ ssh_poll_ctx_remove(event->ctx, p); p->session = NULL; ssh_poll_ctx_add(session->default_poll_ctx, p); rc = SSH_OK; /* * Restart the loop! * A session can initially have two pollhandlers. */ used = event->ctx->polls_used; i = 0; } } #ifdef WITH_SERVER iterator = ssh_list_get_iterator(event->sessions); while(iterator != NULL) { if((ssh_session)iterator->data == session) { ssh_list_remove(event->sessions, iterator); /* there should be only one instance of this session */ break; } iterator = iterator->next; } #endif return rc; } /** @brief Remove a connector from an event context * @param[in] event The ssh_event object. * @param[in] connector connector object to remove * @return SSH_OK on success * @return SSH_ERROR on failure */ int ssh_event_remove_connector(ssh_event event, ssh_connector connector){ (void)event; return ssh_connector_remove_event(connector); } /** * @brief Free an event context. * * @param event The ssh_event object to free. * Note: you have to manually remove sessions and socket * fds before freeing the event object. * */ void ssh_event_free(ssh_event event) { size_t used, i; ssh_poll_handle p; if(event == NULL) { return; } if (event->ctx != NULL) { used = event->ctx->polls_used; for(i = 0; i < used; i++) { p = event->ctx->pollptrs[i]; if (p->session != NULL) { ssh_poll_ctx_remove(event->ctx, p); ssh_poll_ctx_add(p->session->default_poll_ctx, p); p->session = NULL; used = 0; } } ssh_poll_ctx_free(event->ctx); } #ifdef WITH_SERVER if(event->sessions != NULL) { ssh_list_free(event->sessions); } #endif free(event); } /** @} */ ================================================ FILE: src/libssh/src/scp.c ================================================ /* * scp - SSH scp wrapper functions * * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "libssh/priv.h" #include "libssh/scp.h" #include "libssh/misc.h" /** * @defgroup libssh_scp The SSH scp functions * @ingroup libssh * * SCP protocol over SSH functions * * @{ */ /** * @brief Create a new scp session. * * @param[in] session The SSH session to use. * * @param[in] mode One of SSH_SCP_WRITE or SSH_SCP_READ, depending if you * need to drop files remotely or read them. * It is not possible to combine read and write. * SSH_SCP_RECURSIVE Flag can be or'ed to this to indicate * that you're going to use recursion. Browsing through * directories is not possible without this. * * @param[in] location The directory in which write or read will be done. Any * push or pull will be relative to this place. * This can also be a pattern of files to download (read). * * @returns A ssh_scp handle, NULL if the creation was impossible. */ ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location) { ssh_scp scp = NULL; if (session == NULL) { goto error; } scp = (ssh_scp)calloc(1, sizeof(struct ssh_scp_struct)); if (scp == NULL) { ssh_set_error(session, SSH_FATAL, "Error allocating memory for ssh_scp"); goto error; } if ((mode & ~SSH_SCP_RECURSIVE) != SSH_SCP_WRITE && (mode & ~SSH_SCP_RECURSIVE) != SSH_SCP_READ) { ssh_set_error(session, SSH_FATAL, "Invalid mode %d for ssh_scp_new()", mode); goto error; } if (strlen(location) > 32 * 1024) { ssh_set_error(session, SSH_FATAL, "Location path is too long"); goto error; } scp->location = strdup(location); if (scp->location == NULL) { ssh_set_error(session, SSH_FATAL, "Error allocating memory for ssh_scp"); goto error; } scp->session = session; scp->mode = mode & ~SSH_SCP_RECURSIVE; scp->recursive = (mode & SSH_SCP_RECURSIVE) != 0; scp->channel = NULL; scp->state = SSH_SCP_NEW; return scp; error: ssh_scp_free(scp); return NULL; } /** * @brief Initialize the scp channel. * * @param[in] scp The scp context to initialize. * * @return SSH_OK on success or an SSH error code. * * @see ssh_scp_new() */ int ssh_scp_init(ssh_scp scp) { int rc; char execbuffer[1024] = {0}; char *quoted_location = NULL; size_t quoted_location_len = 0; size_t scp_location_len; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_NEW) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_init called under invalid state"); return SSH_ERROR; } if (scp->location == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Invalid scp context: location is NULL"); return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "Initializing scp session %s %son location '%s'", scp->mode == SSH_SCP_WRITE?"write":"read", scp->recursive ? "recursive " : "", scp->location); scp->channel = ssh_channel_new(scp->session); if (scp->channel == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Channel creation failed for scp"); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_channel_open_session(scp->channel); if (rc == SSH_ERROR) { ssh_set_error(scp->session, SSH_FATAL, "Failed to open channel for scp"); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } /* In the worst case, each character would be replaced by 3 plus the string * terminator '\0' */ scp_location_len = strlen(scp->location); quoted_location_len = ((size_t)3 * scp_location_len) + 1; /* Paranoia check */ if (quoted_location_len < scp_location_len) { ssh_set_error(scp->session, SSH_FATAL, "Buffer overflow detected"); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } quoted_location = (char *)calloc(1, quoted_location_len); if (quoted_location == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Failed to allocate memory for quoted location"); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_quote_file_name(scp->location, quoted_location, quoted_location_len); if (rc <= 0) { ssh_set_error(scp->session, SSH_FATAL, "Failed to single quote command location"); SAFE_FREE(quoted_location); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } if (scp->mode == SSH_SCP_WRITE) { snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s", scp->recursive ? "-r" : "", quoted_location); } else { snprintf(execbuffer, sizeof(execbuffer), "scp -f %s %s", scp->recursive ? "-r" : "", quoted_location); } SAFE_FREE(quoted_location); SSH_LOG(SSH_LOG_DEBUG, "Executing command: %s", execbuffer); rc = ssh_channel_request_exec(scp->channel, execbuffer); if (rc == SSH_ERROR){ ssh_set_error(scp->session, SSH_FATAL, "Failed executing command: %s", execbuffer); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } if (scp->mode == SSH_SCP_WRITE) { rc = ssh_scp_response(scp, NULL); if (rc != 0) { return SSH_ERROR; } } else { ssh_channel_write(scp->channel, "", 1); } if (scp->mode == SSH_SCP_WRITE) { scp->state = SSH_SCP_WRITE_INITED; } else { scp->state = SSH_SCP_READ_INITED; } return SSH_OK; } /** * @brief Close the scp channel. * * @param[in] scp The scp context to close. * * @return SSH_OK on success or an SSH error code. * * @see ssh_scp_init() */ int ssh_scp_close(ssh_scp scp) { char buffer[128] = {0}; int rc; if (scp == NULL) { return SSH_ERROR; } if (scp->channel != NULL) { if (ssh_channel_send_eof(scp->channel) == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } /* avoid situations where data are buffered and * not yet stored on disk. This can happen if the close is sent * before we got the EOF back */ while (!ssh_channel_is_eof(scp->channel)) { rc = ssh_channel_read(scp->channel, buffer, sizeof(buffer), 0); if (rc == SSH_ERROR || rc == 0) { break; } } if (ssh_channel_close(scp->channel) == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } ssh_channel_free(scp->channel); scp->channel = NULL; } scp->state = SSH_SCP_NEW; return SSH_OK; } /** * @brief Free a scp context. * * @param[in] scp The context to free. * * @see ssh_scp_new() */ void ssh_scp_free(ssh_scp scp) { if (scp == NULL) { return; } if (scp->state != SSH_SCP_NEW) { ssh_scp_close(scp); } if (scp->channel) { ssh_channel_free(scp->channel); } SAFE_FREE(scp->location); SAFE_FREE(scp->request_name); SAFE_FREE(scp->warning); SAFE_FREE(scp); } /** * @brief Create a directory in a scp in sink mode. * * @param[in] scp The scp handle. * * @param[in] dirname The name of the directory being created. * * @param[in] mode The UNIX permissions for the new directory, e.g. 0755. * * @returns SSH_OK if the directory has been created, SSH_ERROR if * an error occured. * * @see ssh_scp_leave_directory() */ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode) { char buffer[1024] = {0}; int rc; char *dir = NULL; char *perms = NULL; char *vis_encoded = NULL; size_t vis_encoded_len; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_WRITE_INITED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_push_directory called under invalid state"); return SSH_ERROR; } dir = ssh_basename(dirname); if (dir == NULL) { ssh_set_error_oom(scp->session); return SSH_ERROR; } vis_encoded_len = (2 * strlen(dir)) + 1; vis_encoded = (char *)calloc(1, vis_encoded_len); if (vis_encoded == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Failed to allocate buffer to vis encode directory name"); goto error; } rc = ssh_newline_vis(dir, vis_encoded, vis_encoded_len); if (rc <= 0) { ssh_set_error(scp->session, SSH_FATAL, "Failed to vis encode directory name"); goto error; } perms = ssh_scp_string_mode(mode); if (perms == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Failed to get directory permission string"); goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SCP pushing directory %s with permissions '%s'", vis_encoded, perms); /* Use vis encoded directory name */ snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, vis_encoded); SAFE_FREE(dir); SAFE_FREE(perms); SAFE_FREE(vis_encoded); rc = ssh_channel_write(scp->channel, buffer, strlen(buffer)); if (rc == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_scp_response(scp, NULL); if (rc != 0) { return SSH_ERROR; } return SSH_OK; error: SAFE_FREE(dir); SAFE_FREE(perms); SAFE_FREE(vis_encoded); return SSH_ERROR; } /** * @brief Leave a directory. * * @returns SSH_OK if the directory has been left, SSH_ERROR if an * error occured. * * @see ssh_scp_push_directory() */ int ssh_scp_leave_directory(ssh_scp scp) { char buffer[] = "E\n"; int rc; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_WRITE_INITED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_leave_directory called under invalid state"); return SSH_ERROR; } rc = ssh_channel_write(scp->channel, buffer, strlen(buffer)); if (rc == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_scp_response(scp, NULL); if (rc != 0) { return SSH_ERROR; } return SSH_OK; } /** * @brief Initialize the sending of a file to a scp in sink mode, using a 64-bit * size. * * @param[in] scp The scp handle. * * @param[in] filename The name of the file being sent. It should not contain * any path indicator * * @param[in] size Exact size in bytes of the file being sent. * * @param[in] mode The UNIX permissions for the new file, e.g. 0644. * * @returns SSH_OK if the file is ready to be sent, SSH_ERROR if an * error occured. * * @see ssh_scp_push_file() */ int ssh_scp_push_file64(ssh_scp scp, const char *filename, uint64_t size, int mode) { char buffer[1024] = {0}; int rc; char *file = NULL; char *perms = NULL; char *vis_encoded = NULL; size_t vis_encoded_len; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_WRITE_INITED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_push_file called under invalid state"); return SSH_ERROR; } file = ssh_basename(filename); if (file == NULL) { ssh_set_error_oom(scp->session); return SSH_ERROR; } vis_encoded_len = (2 * strlen(file)) + 1; vis_encoded = (char *)calloc(1, vis_encoded_len); if (vis_encoded == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Failed to allocate buffer to vis encode file name"); goto error; } rc = ssh_newline_vis(file, vis_encoded, vis_encoded_len); if (rc <= 0) { ssh_set_error(scp->session, SSH_FATAL, "Failed to vis encode file name"); goto error; } perms = ssh_scp_string_mode(mode); if (perms == NULL) { ssh_set_error(scp->session, SSH_FATAL, "Failed to get file permission string"); goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "SCP pushing file %s, size %" PRIu64 " with permissions '%s'", vis_encoded, size, perms); /* Use vis encoded file name */ snprintf(buffer, sizeof(buffer), "C%s %" PRIu64 " %s\n", perms, size, vis_encoded); SAFE_FREE(file); SAFE_FREE(perms); SAFE_FREE(vis_encoded); rc = ssh_channel_write(scp->channel, buffer, strlen(buffer)); if (rc == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_scp_response(scp, NULL); if (rc != 0) { return SSH_ERROR; } scp->filelen = size; scp->processed = 0; scp->state = SSH_SCP_WRITE_WRITING; return SSH_OK; error: SAFE_FREE(file); SAFE_FREE(perms); SAFE_FREE(vis_encoded); return SSH_ERROR; } /** * @brief Initialize the sending of a file to a scp in sink mode. * * @param[in] scp The scp handle. * * @param[in] filename The name of the file being sent. It should not contain * any path indicator * * @param[in] size Exact size in bytes of the file being sent. * * @param[in] mode The UNIX permissions for the new file, e.g. 0644. * * @returns SSH_OK if the file is ready to be sent, SSH_ERROR if an * error occured. */ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, int mode) { return ssh_scp_push_file64(scp, filename, (uint64_t) size, mode); } /** * @internal * * @brief Wait for a response of the scp server. * * @param[in] scp The scp handle. * * @param[out] response A pointer where the response message must be copied if * any. This pointer must then be free'd. * * @returns The return code, SSH_ERROR a error occured. */ int ssh_scp_response(ssh_scp scp, char **response) { unsigned char code; int rc; char msg[128] = {0}; if (scp == NULL) { return SSH_ERROR; } rc = ssh_channel_read(scp->channel, &code, 1, 0); if (rc == SSH_ERROR) { return SSH_ERROR; } if (code == 0) { return 0; } if (code > 2) { ssh_set_error(scp->session, SSH_FATAL, "SCP: invalid status code %u received", code); scp->state = SSH_SCP_ERROR; return SSH_ERROR; } rc = ssh_scp_read_string(scp, msg, sizeof(msg)); if (rc == SSH_ERROR) { return rc; } /* Warning */ if (code == 1) { ssh_set_error(scp->session, SSH_REQUEST_DENIED, "SCP: Warning: status code 1 received: %s", msg); SSH_LOG(SSH_LOG_RARE, "SCP: Warning: status code 1 received: %s", msg); if (response) { *response = strdup(msg); } return 1; } if (code == 2) { ssh_set_error(scp->session, SSH_FATAL, "SCP: Error: status code 2 received: %s", msg); if (response) { *response = strdup(msg); } return 2; } /* Not reached */ return SSH_ERROR; } /** * @brief Write into a remote scp file. * * @param[in] scp The scp handle. * * @param[in] buffer The buffer to write. * * @param[in] len The number of bytes to write. * * @returns SSH_OK if the write was successful, SSH_ERROR an error * occured while writing. */ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len) { int w; int rc; uint8_t code; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_WRITE_WRITING) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_write called under invalid state"); return SSH_ERROR; } if (scp->processed + len > scp->filelen) { len = (size_t) (scp->filelen - scp->processed); } /* hack to avoid waiting for window change */ rc = ssh_channel_poll(scp->channel, 0); if (rc == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } w = ssh_channel_write(scp->channel, buffer, len); if (w != SSH_ERROR) { scp->processed += w; } else { scp->state = SSH_SCP_ERROR; //return = channel_get_exit_status(scp->channel); return SSH_ERROR; } /* Far end sometimes send a status message, which we need to read * and handle */ rc = ssh_channel_poll(scp->channel, 0); if (rc > 0) { rc = ssh_scp_response(scp, NULL); if (rc != 0) { return SSH_ERROR; } } /* Check if we arrived at end of file */ if (scp->processed == scp->filelen) { code = 0; w = ssh_channel_write(scp->channel, &code, 1); if (w == SSH_ERROR) { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } scp->processed = scp->filelen = 0; scp->state = SSH_SCP_WRITE_INITED; } return SSH_OK; } /** * @brief Read a string on a channel, terminated by '\n' * * @param[in] scp The scp handle. * * @param[out] buffer A pointer to a buffer to place the string. * * @param[in] len The size of the buffer in bytes. If the string is bigger * than len-1, only len-1 bytes are read and the string is * null-terminated. * * @returns SSH_OK if the string was read, SSH_ERROR if an error * occured while reading. */ int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len) { size_t read = 0; int err = SSH_OK; if (scp == NULL) { return SSH_ERROR; } while (read < len - 1) { err = ssh_channel_read(scp->channel, &buffer[read], 1, 0); if (err == SSH_ERROR) { break; } if (err == 0) { ssh_set_error(scp->session, SSH_FATAL, "End of file while reading string"); err = SSH_ERROR; break; } read++; if (buffer[read - 1] == '\n') { break; } } buffer[read] = 0; return err; } /** * @brief Wait for a scp request (file, directory). * * @returns SSH_SCP_REQUEST_NEWFILE: The other side is sending * a file * SSH_SCP_REQUEST_NEWDIR: The other side is sending * a directory * SSH_SCP_REQUEST_ENDDIR: The other side has * finished with the current * directory * SSH_SCP_REQUEST_WARNING: The other side sent us a warning * SSH_SCP_REQUEST_EOF: The other side finished sending us * files and data. * SSH_ERROR: Some error happened * * @see ssh_scp_read() * @see ssh_scp_deny_request() * @see ssh_scp_accept_request() * @see ssh_scp_request_get_warning() */ int ssh_scp_pull_request(ssh_scp scp) { char buffer[MAX_BUF_SIZE] = {0}; char *mode = NULL; char *p, *tmp; uint64_t size; char *name = NULL; int rc; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_READ_INITED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_pull_request called under invalid state"); return SSH_ERROR; } rc = ssh_scp_read_string(scp, buffer, sizeof(buffer)); if (rc == SSH_ERROR) { if (ssh_channel_is_eof(scp->channel)) { scp->state = SSH_SCP_TERMINATED; return SSH_SCP_REQUEST_EOF; } return rc; } p = strchr(buffer, '\n'); if (p != NULL) { *p = '\0'; } SSH_LOG(SSH_LOG_PROTOCOL, "Received SCP request: '%s'", buffer); switch(buffer[0]) { case 'C': /* File */ case 'D': /* Directory */ p = strchr(buffer, ' '); if (p == NULL) { goto error; } *p = '\0'; p++; //mode = strdup(&buffer[1]); scp->request_mode = ssh_scp_integer_mode(&buffer[1]); tmp = p; p = strchr(p, ' '); if (p == NULL) { goto error; } *p = 0; size = strtoull(tmp, NULL, 10); p++; name = strdup(p); SAFE_FREE(scp->request_name); scp->request_name = name; if (buffer[0] == 'C') { scp->filelen = size; scp->request_type = SSH_SCP_REQUEST_NEWFILE; } else { scp->filelen = '0'; scp->request_type = SSH_SCP_REQUEST_NEWDIR; } scp->state = SSH_SCP_READ_REQUESTED; scp->processed = 0; return scp->request_type; break; case 'E': scp->request_type = SSH_SCP_REQUEST_ENDDIR; ssh_channel_write(scp->channel, "", 1); return scp->request_type; case 0x1: ssh_set_error(scp->session, SSH_REQUEST_DENIED, "SCP: Warning: %s", &buffer[1]); scp->request_type = SSH_SCP_REQUEST_WARNING; SAFE_FREE(scp->warning); scp->warning = strdup(&buffer[1]); return scp->request_type; case 0x2: ssh_set_error(scp->session, SSH_FATAL, "SCP: Error: %s", &buffer[1]); return SSH_ERROR; case 'T': /* Timestamp */ default: ssh_set_error(scp->session, SSH_FATAL, "Unhandled message: (%d)%s", buffer[0], buffer); return SSH_ERROR; } /* a parsing error occured */ error: SAFE_FREE(name); SAFE_FREE(mode); ssh_set_error(scp->session, SSH_FATAL, "Parsing error while parsing message: %s", buffer); return SSH_ERROR; } /** * @brief Deny the transfer of a file or creation of a directory coming from the * remote party. * * @param[in] scp The scp handle. * @param[in] reason A nul-terminated string with a human-readable * explanation of the deny. * * @returns SSH_OK if the message was sent, SSH_ERROR if the sending * the message failed, or sending it in a bad state. */ int ssh_scp_deny_request(ssh_scp scp, const char *reason) { char buffer[MAX_BUF_SIZE] = {0}; int rc; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_READ_REQUESTED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_deny_request called under invalid state"); return SSH_ERROR; } snprintf(buffer, sizeof(buffer), "%c%s\n", 2, reason); rc = ssh_channel_write(scp->channel, buffer, strlen(buffer)); if (rc == SSH_ERROR) { return SSH_ERROR; } else { scp->state = SSH_SCP_READ_INITED; return SSH_OK; } } /** * @brief Accepts transfer of a file or creation of a directory coming from the * remote party. * * @param[in] scp The scp handle. * * @returns SSH_OK if the message was sent, SSH_ERROR if sending the * message failed, or sending it in a bad state. */ int ssh_scp_accept_request(ssh_scp scp) { char buffer[] = {0x00}; int rc; if (scp == NULL) { return SSH_ERROR; } if (scp->state != SSH_SCP_READ_REQUESTED) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_deny_request called under invalid state"); return SSH_ERROR; } rc = ssh_channel_write(scp->channel, buffer, 1); if (rc == SSH_ERROR) { return SSH_ERROR; } if (scp->request_type == SSH_SCP_REQUEST_NEWFILE) { scp->state = SSH_SCP_READ_READING; } else { scp->state = SSH_SCP_READ_INITED; } return SSH_OK; } /** @brief Read from a remote scp file * @param[in] scp The scp handle. * * @param[in] buffer The destination buffer. * * @param[in] size The size of the buffer. * * @returns The nNumber of bytes read, SSH_ERROR if an error occured * while reading. */ int ssh_scp_read(ssh_scp scp, void *buffer, size_t size) { int rc; int code; if (scp == NULL) { return SSH_ERROR; } if (scp->state == SSH_SCP_READ_REQUESTED && scp->request_type == SSH_SCP_REQUEST_NEWFILE) { rc = ssh_scp_accept_request(scp); if (rc == SSH_ERROR) { return rc; } } if (scp->state != SSH_SCP_READ_READING) { ssh_set_error(scp->session, SSH_FATAL, "ssh_scp_read called under invalid state"); return SSH_ERROR; } if (scp->processed + size > scp->filelen) { size = (size_t) (scp->filelen - scp->processed); } if (size > 65536) { size = 65536; /* avoid too large reads */ } rc = ssh_channel_read(scp->channel, buffer, size, 0); if (rc != SSH_ERROR) { scp->processed += rc; } else { scp->state = SSH_SCP_ERROR; return SSH_ERROR; } /* Check if we arrived at end of file */ if (scp->processed == scp->filelen) { scp->processed = scp->filelen = 0; ssh_channel_write(scp->channel, "", 1); code = ssh_scp_response(scp, NULL); if (code == 0) { scp->state = SSH_SCP_READ_INITED; return rc; } if (code == 1) { scp->state = SSH_SCP_READ_INITED; return SSH_ERROR; } scp->state = SSH_SCP_ERROR; return SSH_ERROR; } return rc; } /** * @brief Get the name of the directory or file being pushed from the other * party. * * @returns The file name, NULL on error. The string should not be * freed. */ const char *ssh_scp_request_get_filename(ssh_scp scp) { if (scp == NULL) { return NULL; } return scp->request_name; } /** * @brief Get the permissions of the directory or file being pushed from the * other party. * * @returns The UNIX permission, e.g 0644, -1 on error. */ int ssh_scp_request_get_permissions(ssh_scp scp) { if (scp == NULL) { return -1; } return scp->request_mode; } /** @brief Get the size of the file being pushed from the other party. * * @returns The numeric size of the file being read. * @warning The real size may not fit in a 32 bits field and may * be truncated. * @see ssh_scp_request_get_size64() */ size_t ssh_scp_request_get_size(ssh_scp scp) { if (scp == NULL) { return 0; } return (size_t)scp->filelen; } /** @brief Get the size of the file being pushed from the other party. * * @returns The numeric size of the file being read. */ uint64_t ssh_scp_request_get_size64(ssh_scp scp) { if (scp == NULL) { return 0; } return scp->filelen; } /** * @brief Convert a scp text mode to an integer. * * @param[in] mode The mode to convert, e.g. "0644". * * @returns An integer value, e.g. 420 for "0644". */ int ssh_scp_integer_mode(const char *mode) { int value = strtoul(mode, NULL, 8) & 0xffff; return value; } /** * @brief Convert a unix mode into a scp string. * * @param[in] mode The mode to convert, e.g. 420 or 0644. * * @returns A pointer to a malloc'ed string containing the scp mode, * e.g. "0644". */ char *ssh_scp_string_mode(int mode) { char buffer[16] = {0}; snprintf(buffer, sizeof(buffer), "%.4o", mode); return strdup(buffer); } /** * @brief Get the warning string from a scp handle. * * @param[in] scp The scp handle. * * @returns A warning string, or NULL on error. The string should * not be freed. */ const char *ssh_scp_request_get_warning(ssh_scp scp) { if (scp == NULL) { return NULL; } return scp->warning; } /** @} */ ================================================ FILE: src/libssh/src/server.c ================================================ /* * server.c - functions for creating a SSH server * * This file is part of the SSH Library * * Copyright (c) 2004-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #ifdef _WIN32 # include # include /* * is necessary for getaddrinfo before Windows XP, but it isn't * available on some platforms like MinGW. */ # ifdef HAVE_WSPIAPI_H # include # endif #else # include #endif #include "libssh/priv.h" #include "libssh/libssh.h" #include "libssh/server.h" #include "libssh/ssh2.h" #include "libssh/buffer.h" #include "libssh/packet.h" #include "libssh/socket.h" #include "libssh/session.h" #include "libssh/kex.h" #include "libssh/misc.h" #include "libssh/pki.h" #include "libssh/dh.h" #include "libssh/messages.h" #include "libssh/options.h" #include "libssh/curve25519.h" #include "libssh/token.h" #define set_status(session, status) do {\ if (session->common.callbacks && session->common.callbacks->connect_status_function) \ session->common.callbacks->connect_status_function(session->common.callbacks->userdata, status); \ } while (0) /** * @addtogroup libssh_server * * @{ */ /** @internal * * @brief initialize the set of key exchange, hostkey, ciphers, MACs, and * compression algorithms for the given ssh_session * * The selection of algorithms and keys used are determined by the * options that are currently set in the given ssh_session structure. */ int server_set_kex(ssh_session session) { struct ssh_kex_struct *server = &session->next_crypto->server_kex; int i, j, rc; const char *wanted, *allowed; char *kept; char hostkeys[128] = {0}; enum ssh_keytypes_e keytype; size_t len; int ok; ZERO_STRUCTP(server); ok = ssh_get_random(server->cookie, 16, 0); if (!ok) { ssh_set_error(session, SSH_FATAL, "PRNG error"); return -1; } if (session->srv.ed25519_key != NULL) { snprintf(hostkeys, sizeof(hostkeys), "%s", ssh_key_type_to_char(ssh_key_type(session->srv.ed25519_key))); } #ifdef HAVE_ECC if (session->srv.ecdsa_key != NULL) { len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", session->srv.ecdsa_key->type_c); } #endif #ifdef HAVE_DSA if (session->srv.dsa_key != NULL) { len = strlen(hostkeys); keytype = ssh_key_type(session->srv.dsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } #endif if (session->srv.rsa_key != NULL) { /* We support also the SHA2 variants */ len = strlen(hostkeys); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",rsa-sha2-512,rsa-sha2-256"); len = strlen(hostkeys); keytype = ssh_key_type(session->srv.rsa_key); snprintf(hostkeys + len, sizeof(hostkeys) - len, ",%s", ssh_key_type_to_char(keytype)); } if (strlen(hostkeys) == 0) { return -1; } if (session->opts.wanted_methods[SSH_HOSTKEYS]) { allowed = session->opts.wanted_methods[SSH_HOSTKEYS]; } else { if (ssh_fips_mode()) { allowed = ssh_kex_get_fips_methods(SSH_HOSTKEYS); } else { allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS); } } /* It is expected for the list of allowed hostkeys to be ordered by * preference */ kept = ssh_find_all_matching(hostkeys[0] == ',' ? hostkeys + 1 : hostkeys, allowed); if (kept == NULL) { /* Nothing was allowed */ return -1; } rc = ssh_options_set_algo(session, SSH_HOSTKEYS, kept); SAFE_FREE(kept); if (rc < 0) { return -1; } for (i = 0; i < SSH_KEX_METHODS; i++) { wanted = session->opts.wanted_methods[i]; if (wanted == NULL) { if (ssh_fips_mode()) { wanted = ssh_kex_get_fips_methods(i); } else { wanted = ssh_kex_get_default_methods(i); } } if (wanted == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } server->methods[i] = strdup(wanted); if (server->methods[i] == NULL) { for (j = 0; j < i; j++) { SAFE_FREE(server->methods[j]); } return -1; } } return 0; } int ssh_server_init_kex(ssh_session session) { int i; if (session->session_state > SSH_SESSION_STATE_BANNER_RECEIVED) { return SSH_ERROR; } /* free any currently-set methods: server_set_kex will allocate new ones */ for (i = 0; i < SSH_KEX_METHODS; i++) { SAFE_FREE(session->next_crypto->server_kex.methods[i]); } return server_set_kex(session); } static int ssh_server_send_extensions(ssh_session session) { int rc; const char *hostkey_algorithms; SSH_LOG(SSH_LOG_PACKET, "Sending SSH_MSG_EXT_INFO"); if (session->opts.pubkey_accepted_types) { hostkey_algorithms = session->opts.pubkey_accepted_types; } else { if (ssh_fips_mode()) { hostkey_algorithms = ssh_kex_get_fips_methods(SSH_HOSTKEYS); } else { /* There are no restrictions to the accepted public keys */ hostkey_algorithms = ssh_kex_get_default_methods(SSH_HOSTKEYS); } } rc = ssh_buffer_pack(session->out_buffer, "bdss", SSH2_MSG_EXT_INFO, 1, /* nr. of extensions */ "server-sig-algs", hostkey_algorithms); if (rc != SSH_OK) { goto error; } if (ssh_packet_send(session) == SSH_ERROR) { goto error; } return 0; error: ssh_buffer_reinit(session->out_buffer); return -1; } SSH_PACKET_CALLBACK(ssh_packet_kexdh_init){ (void)packet; (void)type; (void)user; SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_KEXDH_INIT"); if(session->dh_handshake_state != DH_STATE_INIT){ SSH_LOG(SSH_LOG_RARE,"Invalid state for SSH_MSG_KEXDH_INIT"); session->session_state = SSH_SESSION_STATE_ERROR; return SSH_PACKET_USED; } /* If first_kex_packet_follows guess was wrong, ignore this message. */ if (session->first_kex_follows_guess_wrong != 0) { SSH_LOG(SSH_LOG_RARE, "first_kex_packet_follows guess was wrong, " "ignoring first SSH_MSG_KEXDH_INIT message"); session->first_kex_follows_guess_wrong = 0; return SSH_PACKET_USED; } SSH_LOG(SSH_LOG_DEBUG, "Calling next KEXDH handler"); return SSH_PACKET_NOT_USED; } int ssh_get_key_params(ssh_session session, ssh_key *privkey, enum ssh_digest_e *digest) { ssh_key pubkey; ssh_string pubkey_blob; int rc; switch(session->srv.hostkey) { case SSH_KEYTYPE_DSS: *privkey = session->srv.dsa_key; break; case SSH_KEYTYPE_RSA: *privkey = session->srv.rsa_key; break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: *privkey = session->srv.ecdsa_key; break; case SSH_KEYTYPE_ED25519: *privkey = session->srv.ed25519_key; break; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: *privkey = NULL; } *digest = session->srv.hostkey_digest; rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Could not get the public key from the private key"); return -1; } rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); ssh_key_free(pubkey); if (rc < 0) { ssh_set_error_oom(session); return -1; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); SSH_STRING_FREE(pubkey_blob); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Could not import server public key"); return -1; } return SSH_OK; } /** * @internal * * @brief A function to be called each time a step has been done in the * connection. */ static void ssh_server_connection_callback(ssh_session session){ int rc; switch(session->session_state){ case SSH_SESSION_STATE_NONE: case SSH_SESSION_STATE_CONNECTING: case SSH_SESSION_STATE_SOCKET_CONNECTED: break; case SSH_SESSION_STATE_BANNER_RECEIVED: if (session->clientbanner == NULL) { goto error; } set_status(session, 0.4f); SSH_LOG(SSH_LOG_PROTOCOL, "SSH client banner: %s", session->clientbanner); /* Here we analyze the different protocols the server allows. */ rc = ssh_analyze_banner(session, 1); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "No version of SSH protocol usable (banner: %s)", session->clientbanner); goto error; } /* from now, the packet layer is handling incoming packets */ session->socket_callbacks.data=ssh_packet_socket_callback; ssh_packet_register_socket_callback(session, session->socket); ssh_packet_set_default_callbacks(session); set_status(session, 0.5f); session->session_state=SSH_SESSION_STATE_INITIAL_KEX; if (ssh_send_kex(session, 1) < 0) { goto error; } break; case SSH_SESSION_STATE_INITIAL_KEX: /* TODO: This state should disappear in favor of get_key handle */ break; case SSH_SESSION_STATE_KEXINIT_RECEIVED: set_status(session,0.6f); if(session->next_crypto->server_kex.methods[0]==NULL){ if(server_set_kex(session) == SSH_ERROR) goto error; /* We are in a rekeying, so we need to send the server kex */ if(ssh_send_kex(session, 1) < 0) goto error; } ssh_list_kex(&session->next_crypto->client_kex); // log client kex if (ssh_kex_select_methods(session) < 0) { goto error; } if (crypt_set_algorithms_server(session) == SSH_ERROR) goto error; set_status(session,0.8f); session->session_state=SSH_SESSION_STATE_DH; break; case SSH_SESSION_STATE_DH: if(session->dh_handshake_state==DH_STATE_FINISHED){ rc = ssh_packet_set_newkeys(session, SSH_DIRECTION_IN); if (rc != SSH_OK) { goto error; } /* * If the client supports extension negotiation, we will send * our supported extensions now. This is the first message after * sending NEWKEYS message and after turning on crypto. */ if (session->extensions & SSH_EXT_NEGOTIATION && session->session_state != SSH_SESSION_STATE_AUTHENTICATED) { /* * Only send an SSH_MSG_EXT_INFO message the first time the client * undergoes NEWKEYS. It is unexpected for this message to be sent * upon rekey, and may cause clients to log error messages. * * The session_state can not be used for this purpose because it is * re-set to SSH_SESSION_STATE_KEXINIT_RECEIVED during rekey. So, * use the connected flag which transitions from non-zero below. * * See also: * - https://bugzilla.mindrot.org/show_bug.cgi?id=2929 */ if (session->connected == 0) { ssh_server_send_extensions(session); } } set_status(session,1.0f); session->connected = 1; session->session_state=SSH_SESSION_STATE_AUTHENTICATING; if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) session->session_state = SSH_SESSION_STATE_AUTHENTICATED; } break; case SSH_SESSION_STATE_AUTHENTICATING: break; case SSH_SESSION_STATE_ERROR: goto error; default: ssh_set_error(session,SSH_FATAL,"Invalid state %d",session->session_state); } return; error: ssh_socket_close(session->socket); session->alive = 0; session->session_state=SSH_SESSION_STATE_ERROR; } /** * @internal * * @brief Gets the banner from socket and saves it in session. * Updates the session state * * @param data pointer to the beginning of header * @param len size of the banner * @param user is a pointer to session * @returns Number of bytes processed, or zero if the banner is not complete. */ static int callback_receive_banner(const void *data, size_t len, void *user) { char *buffer = (char *) data; ssh_session session = (ssh_session) user; char *str = NULL; size_t i; int ret=0; for (i = 0; i < len; i++) { #ifdef WITH_PCAP if(session->pcap_ctx && buffer[i] == '\n') { ssh_pcap_context_write(session->pcap_ctx, SSH_PCAP_DIR_IN, buffer, i + 1, i + 1); } #endif if (buffer[i] == '\r') { buffer[i]='\0'; } if (buffer[i] == '\n') { buffer[i]='\0'; str = strdup(buffer); /* number of bytes read */ ret = i + 1; session->clientbanner = str; session->session_state = SSH_SESSION_STATE_BANNER_RECEIVED; SSH_LOG(SSH_LOG_PACKET, "Received banner: %s", str); session->ssh_connection_callback(session); return ret; } if(i > 127) { /* Too big banner */ session->session_state = SSH_SESSION_STATE_ERROR; ssh_set_error(session, SSH_FATAL, "Receiving banner: too large banner"); return 0; } } return ret; } /* returns 0 until the key exchange is not finished */ static int ssh_server_kex_termination(void *s){ ssh_session session = s; if (session->session_state != SSH_SESSION_STATE_ERROR && session->session_state != SSH_SESSION_STATE_AUTHENTICATING && session->session_state != SSH_SESSION_STATE_DISCONNECTED) return 0; else return 1; } /* FIXME: auth_methods should be unsigned */ void ssh_set_auth_methods(ssh_session session, int auth_methods) { /* accept only methods in range */ session->auth.supported_methods = (uint32_t)auth_methods & 0x3fU; } /* Do the banner and key exchange */ int ssh_handle_key_exchange(ssh_session session) { int rc; if (session->session_state != SSH_SESSION_STATE_NONE) goto pending; rc = ssh_send_banner(session, 1); if (rc < 0) { return SSH_ERROR; } session->alive = 1; session->ssh_connection_callback = ssh_server_connection_callback; session->session_state = SSH_SESSION_STATE_SOCKET_CONNECTED; ssh_socket_set_callbacks(session->socket,&session->socket_callbacks); session->socket_callbacks.data=callback_receive_banner; session->socket_callbacks.exception=ssh_socket_exception_callback; session->socket_callbacks.userdata=session; rc = server_set_kex(session); if (rc < 0) { return SSH_ERROR; } pending: rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER, ssh_server_kex_termination,session); SSH_LOG(SSH_LOG_PACKET, "ssh_handle_key_exchange: current state : %d", session->session_state); if (rc != SSH_OK) return rc; if (session->session_state == SSH_SESSION_STATE_ERROR || session->session_state == SSH_SESSION_STATE_DISCONNECTED) { return SSH_ERROR; } return SSH_OK; } /* messages */ /** @internal * replies to an SSH_AUTH packet with a default (denied) response. */ int ssh_auth_reply_default(ssh_session session,int partial) { char methods_c[128] = {0}; int rc = SSH_ERROR; if (session->auth.supported_methods == 0) { session->auth.supported_methods = SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD; } if (session->auth.supported_methods & SSH_AUTH_METHOD_PUBLICKEY) { strncat(methods_c, "publickey,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth.supported_methods & SSH_AUTH_METHOD_GSSAPI_MIC){ strncat(methods_c,"gssapi-with-mic,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth.supported_methods & SSH_AUTH_METHOD_INTERACTIVE) { strncat(methods_c, "keyboard-interactive,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth.supported_methods & SSH_AUTH_METHOD_PASSWORD) { strncat(methods_c, "password,", sizeof(methods_c) - strlen(methods_c) - 1); } if (session->auth.supported_methods & SSH_AUTH_METHOD_HOSTBASED) { strncat(methods_c, "hostbased,", sizeof(methods_c) - strlen(methods_c) - 1); } if (methods_c[0] == '\0' || methods_c[strlen(methods_c)-1] != ',') { return SSH_ERROR; } /* Strip the comma. */ methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure there is at SSH_LOG(SSH_LOG_PACKET, "Sending a auth failure. methods that can continue: %s", methods_c); rc = ssh_buffer_pack(session->out_buffer, "bsb", SSH2_MSG_USERAUTH_FAILURE, methods_c, partial ? 1 : 0); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } rc = ssh_packet_send(session); return rc; } static int ssh_message_channel_request_open_reply_default(ssh_message msg) { int rc; SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a channel"); rc = ssh_buffer_pack(msg->session->out_buffer, "bdddd", SSH2_MSG_CHANNEL_OPEN_FAILURE, msg->channel_request_open.sender, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, /* reason is empty string */ 0); /* language string */ if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } rc = ssh_packet_send(msg->session); return rc; } static int ssh_message_channel_request_reply_default(ssh_message msg) { uint32_t channel; int rc; if (msg->channel_request.want_reply) { channel = msg->channel_request.channel->remote_channel; SSH_LOG(SSH_LOG_PACKET, "Sending a default channel_request denied to channel %d", channel); rc = ssh_buffer_pack(msg->session->out_buffer, "bd", SSH2_MSG_CHANNEL_FAILURE, channel); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } return ssh_packet_send(msg->session); } SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the request failed!"); return SSH_OK; } static int ssh_message_service_request_reply_default(ssh_message msg) { /* The only return code accepted by specifications are success or disconnect */ return ssh_message_service_reply_success(msg); } int ssh_message_service_reply_success(ssh_message msg) { ssh_session session; int rc; if (msg == NULL) { return SSH_ERROR; } session = msg->session; SSH_LOG(SSH_LOG_PACKET, "Sending a SERVICE_ACCEPT for service %s", msg->service_request.service); rc = ssh_buffer_pack(session->out_buffer, "bs", SSH2_MSG_SERVICE_ACCEPT, msg->service_request.service); if (rc != SSH_OK){ ssh_set_error_oom(session); return SSH_ERROR; } rc = ssh_packet_send(msg->session); return rc; } int ssh_message_global_request_reply_success(ssh_message msg, uint16_t bound_port) { int rc; SSH_LOG(SSH_LOG_FUNCTIONS, "Accepting a global request"); if (msg->global_request.want_reply) { if (ssh_buffer_add_u8(msg->session->out_buffer , SSH2_MSG_REQUEST_SUCCESS) < 0) { goto error; } if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD && msg->global_request.bind_port == 0) { rc = ssh_buffer_pack(msg->session->out_buffer, "d", bound_port); if (rc != SSH_OK) { ssh_set_error_oom(msg->session); goto error; } } return ssh_packet_send(msg->session); } if(msg->global_request.type == SSH_GLOBAL_REQUEST_TCPIP_FORWARD && msg->global_request.bind_port == 0) { SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the remote port!"); } return SSH_OK; error: return SSH_ERROR; } static int ssh_message_global_request_reply_default(ssh_message msg) { SSH_LOG(SSH_LOG_FUNCTIONS, "Refusing a global request"); if (msg->global_request.want_reply) { if (ssh_buffer_add_u8(msg->session->out_buffer , SSH2_MSG_REQUEST_FAILURE) < 0) { goto error; } return ssh_packet_send(msg->session); } SSH_LOG(SSH_LOG_PACKET, "The client doesn't want to know the request failed!"); return SSH_OK; error: return SSH_ERROR; } int ssh_message_reply_default(ssh_message msg) { if (msg == NULL) { return -1; } switch(msg->type) { case SSH_REQUEST_AUTH: return ssh_auth_reply_default(msg->session, 0); case SSH_REQUEST_CHANNEL_OPEN: return ssh_message_channel_request_open_reply_default(msg); case SSH_REQUEST_CHANNEL: return ssh_message_channel_request_reply_default(msg); case SSH_REQUEST_SERVICE: return ssh_message_service_request_reply_default(msg); case SSH_REQUEST_GLOBAL: return ssh_message_global_request_reply_default(msg); default: SSH_LOG(SSH_LOG_PACKET, "Don't know what to default reply to %d type", msg->type); break; } return -1; } const char *ssh_message_service_service(ssh_message msg){ if (msg == NULL) { return NULL; } return msg->service_request.service; } const char *ssh_message_auth_user(ssh_message msg) { if (msg == NULL) { return NULL; } return msg->auth_request.username; } const char *ssh_message_auth_password(ssh_message msg){ if (msg == NULL) { return NULL; } return msg->auth_request.password; } ssh_key ssh_message_auth_pubkey(ssh_message msg) { if (msg == NULL) { return NULL; } return msg->auth_request.pubkey; } /* Get the publickey of an auth request */ ssh_public_key ssh_message_auth_publickey(ssh_message msg){ if (msg == NULL) { return NULL; } return ssh_pki_convert_key_to_publickey(msg->auth_request.pubkey); } enum ssh_publickey_state_e ssh_message_auth_publickey_state(ssh_message msg){ if (msg == NULL) { return -1; } return msg->auth_request.signature_state; } int ssh_message_auth_kbdint_is_response(ssh_message msg) { if (msg == NULL) { return -1; } return msg->auth_request.kbdint_response != 0; } /* FIXME: methods should be unsigned */ int ssh_message_auth_set_methods(ssh_message msg, int methods) { if (msg == NULL || msg->session == NULL) { return -1; } if (methods < 0) { return -1; } msg->session->auth.supported_methods = (uint32_t)methods; return 0; } int ssh_message_auth_interactive_request(ssh_message msg, const char *name, const char *instruction, unsigned int num_prompts, const char **prompts, char *echo) { int rc; unsigned int i = 0; if(name == NULL || instruction == NULL) { return SSH_ERROR; } if(num_prompts > 0 && (prompts == NULL || echo == NULL)) { return SSH_ERROR; } rc = ssh_buffer_pack(msg->session->out_buffer, "bsssd", SSH2_MSG_USERAUTH_INFO_REQUEST, name, instruction, "", /* language tag */ num_prompts); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } for(i = 0; i < num_prompts; i++) { rc = ssh_buffer_pack(msg->session->out_buffer, "sb", prompts[i], echo[i] ? 1 : 0); if (rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } } rc = ssh_packet_send(msg->session); /* fill in the kbdint structure */ if (msg->session->kbdint == NULL) { SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a " "keyboard-interactive response but it " "seems we didn't send the request."); msg->session->kbdint = ssh_kbdint_new(); if (msg->session->kbdint == NULL) { ssh_set_error_oom(msg->session); return SSH_ERROR; } } else { ssh_kbdint_clean(msg->session->kbdint); } msg->session->kbdint->name = strdup(name); if(msg->session->kbdint->name == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->instruction = strdup(instruction); if(msg->session->kbdint->instruction == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } msg->session->kbdint->nprompts = num_prompts; if(num_prompts > 0) { msg->session->kbdint->prompts = calloc(num_prompts, sizeof(char *)); if (msg->session->kbdint->prompts == NULL) { msg->session->kbdint->nprompts = 0; ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } msg->session->kbdint->echo = calloc(num_prompts, sizeof(unsigned char)); if (msg->session->kbdint->echo == NULL) { ssh_set_error_oom(msg->session); ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_ERROR; } for (i = 0; i < num_prompts; i++) { msg->session->kbdint->echo[i] = echo[i]; msg->session->kbdint->prompts[i] = strdup(prompts[i]); if (msg->session->kbdint->prompts[i] == NULL) { ssh_set_error_oom(msg->session); msg->session->kbdint->nprompts = i; ssh_kbdint_free(msg->session->kbdint); msg->session->kbdint = NULL; return SSH_PACKET_USED; } } } else { msg->session->kbdint->prompts = NULL; msg->session->kbdint->echo = NULL; } msg->session->auth.state = SSH_AUTH_STATE_INFO; return rc; } int ssh_auth_reply_success(ssh_session session, int partial) { struct ssh_crypto_struct *crypto = NULL; int r; if (session == NULL) { return SSH_ERROR; } if (partial) { return ssh_auth_reply_default(session, partial); } r = ssh_buffer_add_u8(session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS); if (r < 0) { return SSH_ERROR; } r = ssh_packet_send(session); /* * Consider the session as having been authenticated only after sending * the USERAUTH_SUCCESS message. Setting these flags after ssh_packet_send * ensures that a rekey is not triggered prematurely, causing the message * to be queued. */ session->session_state = SSH_SESSION_STATE_AUTHENTICATED; session->flags |= SSH_SESSION_FLAG_AUTHENTICATED; crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_OUT); if (crypto != NULL && crypto->delayed_compress_out) { SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression OUT"); crypto->do_compress_out = 1; } crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN); if (crypto != NULL && crypto->delayed_compress_in) { SSH_LOG(SSH_LOG_PROTOCOL, "Enabling delayed compression IN"); crypto->do_compress_in = 1; } return r; } int ssh_message_auth_reply_success(ssh_message msg, int partial) { if(msg == NULL) return SSH_ERROR; return ssh_auth_reply_success(msg->session, partial); } /* Answer OK to a pubkey auth request */ int ssh_message_auth_reply_pk_ok(ssh_message msg, ssh_string algo, ssh_string pubkey) { int rc; if (msg == NULL) { return SSH_ERROR; } rc = ssh_buffer_pack(msg->session->out_buffer, "bSS", SSH2_MSG_USERAUTH_PK_OK, algo, pubkey); if(rc != SSH_OK){ ssh_set_error_oom(msg->session); return SSH_ERROR; } rc = ssh_packet_send(msg->session); return rc; } int ssh_message_auth_reply_pk_ok_simple(ssh_message msg) { ssh_string algo; ssh_string pubkey_blob = NULL; int ret; algo = ssh_string_from_char(msg->auth_request.pubkey->type_c); if (algo == NULL) { return SSH_ERROR; } ret = ssh_pki_export_pubkey_blob(msg->auth_request.pubkey, &pubkey_blob); if (ret < 0) { SSH_STRING_FREE(algo); return SSH_ERROR; } ret = ssh_message_auth_reply_pk_ok(msg, algo, pubkey_blob); SSH_STRING_FREE(algo); SSH_STRING_FREE(pubkey_blob); return ret; } const char *ssh_message_channel_request_open_originator(ssh_message msg){ return msg->channel_request_open.originator; } int ssh_message_channel_request_open_originator_port(ssh_message msg){ return msg->channel_request_open.originator_port; } const char *ssh_message_channel_request_open_destination(ssh_message msg){ return msg->channel_request_open.destination; } int ssh_message_channel_request_open_destination_port(ssh_message msg){ return msg->channel_request_open.destination_port; } ssh_channel ssh_message_channel_request_channel(ssh_message msg){ return msg->channel_request.channel; } const char *ssh_message_channel_request_pty_term(ssh_message msg){ return msg->channel_request.TERM; } int ssh_message_channel_request_pty_width(ssh_message msg){ return msg->channel_request.width; } int ssh_message_channel_request_pty_height(ssh_message msg){ return msg->channel_request.height; } int ssh_message_channel_request_pty_pxwidth(ssh_message msg){ return msg->channel_request.pxwidth; } int ssh_message_channel_request_pty_pxheight(ssh_message msg){ return msg->channel_request.pxheight; } const char *ssh_message_channel_request_env_name(ssh_message msg){ return msg->channel_request.var_name; } const char *ssh_message_channel_request_env_value(ssh_message msg){ return msg->channel_request.var_value; } const char *ssh_message_channel_request_command(ssh_message msg){ return msg->channel_request.command; } const char *ssh_message_channel_request_subsystem(ssh_message msg){ return msg->channel_request.subsystem; } int ssh_message_channel_request_x11_single_connection(ssh_message msg){ return msg->channel_request.x11_single_connection ? 1 : 0; } const char *ssh_message_channel_request_x11_auth_protocol(ssh_message msg){ return msg->channel_request.x11_auth_protocol; } const char *ssh_message_channel_request_x11_auth_cookie(ssh_message msg){ return msg->channel_request.x11_auth_cookie; } int ssh_message_channel_request_x11_screen_number(ssh_message msg){ return msg->channel_request.x11_screen_number; } const char *ssh_message_global_request_address(ssh_message msg){ return msg->global_request.bind_address; } int ssh_message_global_request_port(ssh_message msg){ return msg->global_request.bind_port; } /** @brief defines the ssh_message callback * @param session the current ssh session * @param[in] ssh_bind_message_callback a function pointer to a callback taking the * current ssh session and received message as parameters. the function returns * 0 if the message has been parsed and treated successfully, 1 otherwise (libssh * must take care of the response). * @param[in] data void pointer to be passed to callback functions */ void ssh_set_message_callback(ssh_session session, int(*ssh_bind_message_callback)(ssh_session session, ssh_message msg, void *data), void *data) { session->ssh_message_callback = ssh_bind_message_callback; session->ssh_message_callback_data = data; } int ssh_execute_message_callbacks(ssh_session session){ ssh_message msg=NULL; int ret; ssh_handle_packets(session, SSH_TIMEOUT_NONBLOCKING); if(!session->ssh_message_list) return SSH_OK; if(session->ssh_message_callback){ while((msg=ssh_message_pop_head(session)) != NULL) { ret=session->ssh_message_callback(session,msg, session->ssh_message_callback_data); if(ret==1){ ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } else { ssh_message_free(msg); } } } else { while((msg=ssh_message_pop_head(session)) != NULL) { ret = ssh_message_reply_default(msg); ssh_message_free(msg); if(ret != SSH_OK) return ret; } } return SSH_OK; } int ssh_send_keepalive(ssh_session session) { /* Client denies the request, so the error code is not meaningful */ (void)ssh_global_request(session, "keepalive@openssh.com", NULL, 1); return SSH_OK; } /** @} */ ================================================ FILE: src/libssh/src/session.c ================================================ /* * session.c - non-networking functions * * This file is part of the SSH Library * * Copyright (c) 2005-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include "libssh/priv.h" #include "libssh/libssh.h" #include "libssh/crypto.h" #include "libssh/server.h" #include "libssh/socket.h" #include "libssh/ssh2.h" #include "libssh/agent.h" #include "libssh/packet.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/buffer.h" #include "libssh/poll.h" #include "libssh/pki.h" #define FIRST_CHANNEL 42 // why not ? it helps to find bugs. /** * @defgroup libssh_session The SSH session functions. * @ingroup libssh * * Functions that manage a session. * * @{ */ /** * @brief Create a new ssh session. * * @returns A new ssh_session pointer, NULL on error. */ ssh_session ssh_new(void) { ssh_session session; char *id = NULL; int rc; session = calloc(1, sizeof (struct ssh_session_struct)); if (session == NULL) { return NULL; } session->next_crypto = crypto_new(); if (session->next_crypto == NULL) { goto err; } session->socket = ssh_socket_new(session); if (session->socket == NULL) { goto err; } session->out_buffer = ssh_buffer_new(); if (session->out_buffer == NULL) { goto err; } session->in_buffer = ssh_buffer_new(); if (session->in_buffer == NULL) { goto err; } session->out_queue = ssh_list_new(); if (session->out_queue == NULL) { goto err; } session->alive = 0; session->auth.supported_methods = 0; ssh_set_blocking(session, 1); session->maxchannel = FIRST_CHANNEL; session->agent = ssh_agent_new(session); if (session->agent == NULL) { goto err; } /* OPTIONS */ session->opts.StrictHostKeyChecking = 1; session->opts.port = 0; session->opts.fd = -1; session->opts.compressionlevel = 7; session->opts.nodelay = 0; session->opts.flags = SSH_OPT_FLAG_PASSWORD_AUTH | SSH_OPT_FLAG_PUBKEY_AUTH | SSH_OPT_FLAG_KBDINT_AUTH | SSH_OPT_FLAG_GSSAPI_AUTH; session->opts.identity = ssh_list_new(); if (session->opts.identity == NULL) { goto err; } id = strdup("%d/id_ed25519"); if (id == NULL) { goto err; } rc = ssh_list_append(session->opts.identity, id); if (rc == SSH_ERROR) { goto err; } #ifdef HAVE_ECC id = strdup("%d/id_ecdsa"); if (id == NULL) { goto err; } rc = ssh_list_append(session->opts.identity, id); if (rc == SSH_ERROR) { goto err; } #endif id = strdup("%d/id_rsa"); if (id == NULL) { goto err; } rc = ssh_list_append(session->opts.identity, id); if (rc == SSH_ERROR) { goto err; } #ifdef HAVE_DSA id = strdup("%d/id_dsa"); if (id == NULL) { goto err; } rc = ssh_list_append(session->opts.identity, id); if (rc == SSH_ERROR) { goto err; } #endif /* Explicitly initialize states */ session->session_state = SSH_SESSION_STATE_NONE; session->pending_call_state = SSH_PENDING_CALL_NONE; session->packet_state = PACKET_STATE_INIT; session->dh_handshake_state = DH_STATE_INIT; session->global_req_state = SSH_CHANNEL_REQ_STATE_NONE; session->auth.state = SSH_AUTH_STATE_NONE; session->auth.service_state = SSH_AUTH_SERVICE_NONE; return session; err: free(id); ssh_free(session); return NULL; } /** * @brief Deallocate a SSH session handle. * * @param[in] session The SSH session to free. * * @see ssh_disconnect() * @see ssh_new() */ void ssh_free(ssh_session session) { int i; struct ssh_iterator *it = NULL; struct ssh_buffer_struct *b = NULL; if (session == NULL) { return; } /* * Delete all channels * * This needs the first thing we clean up cause if there is still an open * channel we call ssh_channel_close() first. So we need a working socket * and poll context for it. */ for (it = ssh_list_get_iterator(session->channels); it != NULL; it = ssh_list_get_iterator(session->channels)) { ssh_channel_do_free(ssh_iterator_value(ssh_channel,it)); ssh_list_remove(session->channels, it); } ssh_list_free(session->channels); session->channels = NULL; #ifdef WITH_PCAP if (session->pcap_ctx) { ssh_pcap_context_free(session->pcap_ctx); session->pcap_ctx = NULL; } #endif ssh_socket_free(session->socket); session->socket = NULL; if (session->default_poll_ctx) { ssh_poll_ctx_free(session->default_poll_ctx); } SSH_BUFFER_FREE(session->in_buffer); SSH_BUFFER_FREE(session->out_buffer); session->in_buffer = session->out_buffer = NULL; if (session->in_hashbuf != NULL) { SSH_BUFFER_FREE(session->in_hashbuf); } if (session->out_hashbuf != NULL) { SSH_BUFFER_FREE(session->out_hashbuf); } crypto_free(session->current_crypto); crypto_free(session->next_crypto); ssh_agent_free(session->agent); ssh_key_free(session->srv.dsa_key); session->srv.dsa_key = NULL; ssh_key_free(session->srv.rsa_key); session->srv.rsa_key = NULL; ssh_key_free(session->srv.ecdsa_key); session->srv.ecdsa_key = NULL; ssh_key_free(session->srv.ed25519_key); session->srv.ed25519_key = NULL; if (session->ssh_message_list) { ssh_message msg; for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list); msg != NULL; msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) { ssh_message_free(msg); } ssh_list_free(session->ssh_message_list); } if (session->kbdint != NULL) { ssh_kbdint_free(session->kbdint); } if (session->packet_callbacks) { ssh_list_free(session->packet_callbacks); } /* options */ if (session->opts.identity) { char *id; for (id = ssh_list_pop_head(char *, session->opts.identity); id != NULL; id = ssh_list_pop_head(char *, session->opts.identity)) { SAFE_FREE(id); } ssh_list_free(session->opts.identity); } while ((b = ssh_list_pop_head(struct ssh_buffer_struct *, session->out_queue)) != NULL) { SSH_BUFFER_FREE(b); } ssh_list_free(session->out_queue); ssh_agent_state_free (session->agent_state); session->agent_state = NULL; SAFE_FREE(session->auth.auto_state); SAFE_FREE(session->serverbanner); SAFE_FREE(session->clientbanner); SAFE_FREE(session->banner); SAFE_FREE(session->opts.bindaddr); SAFE_FREE(session->opts.custombanner); SAFE_FREE(session->opts.username); SAFE_FREE(session->opts.host); SAFE_FREE(session->opts.proxy_host); SAFE_FREE(session->opts.sshdir); SAFE_FREE(session->opts.knownhosts); SAFE_FREE(session->opts.global_knownhosts); SAFE_FREE(session->opts.ProxyCommand); SAFE_FREE(session->opts.gss_server_identity); SAFE_FREE(session->opts.gss_client_identity); SAFE_FREE(session->opts.pubkey_accepted_types); for (i = 0; i < SSH_KEX_METHODS; i++) { if (session->opts.wanted_methods[i]) { SAFE_FREE(session->opts.wanted_methods[i]); } } /* burn connection, it could contain sensitive data */ explicit_bzero(session, sizeof(struct ssh_session_struct)); SAFE_FREE(session); } /** * @brief get the client banner * * @param[in] session The SSH session * * @return Returns the client banner string or NULL. */ const char* ssh_get_clientbanner(ssh_session session) { if (session == NULL) { return NULL; } return session->clientbanner; } /** * @brief get the server banner * * @param[in] session The SSH session * * @return Returns the server banner string or NULL. */ const char* ssh_get_serverbanner(ssh_session session) { if(!session) { return NULL; } return session->serverbanner; } /** * @brief get the name of the current key exchange algorithm. * * @param[in] session The SSH session * * @return Returns the key exchange algorithm string or NULL. */ const char* ssh_get_kex_algo(ssh_session session) { if ((session == NULL) || (session->current_crypto == NULL)) { return NULL; } switch (session->current_crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: return "diffie-hellman-group1-sha1"; case SSH_KEX_DH_GROUP14_SHA1: return "diffie-hellman-group14-sha1"; case SSH_KEX_DH_GROUP14_SHA256: return "diffie-hellman-group14-sha256"; case SSH_KEX_DH_GROUP16_SHA512: return "diffie-hellman-group16-sha512"; case SSH_KEX_DH_GROUP18_SHA512: return "diffie-hellman-group18-sha512"; case SSH_KEX_ECDH_SHA2_NISTP256: return "ecdh-sha2-nistp256"; case SSH_KEX_ECDH_SHA2_NISTP384: return "ecdh-sha2-nistp384"; case SSH_KEX_ECDH_SHA2_NISTP521: return "ecdh-sha2-nistp521"; case SSH_KEX_CURVE25519_SHA256: return "curve25519-sha256"; case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: return "curve25519-sha256@libssh.org"; default: break; } return NULL; } /** * @brief get the name of the input cipher for the given session. * * @param[in] session The SSH session. * * @return Returns cipher name or NULL. */ const char* ssh_get_cipher_in(ssh_session session) { if ((session != NULL) && (session->current_crypto != NULL) && (session->current_crypto->in_cipher != NULL)) { return session->current_crypto->in_cipher->name; } return NULL; } /** * @brief get the name of the output cipher for the given session. * * @param[in] session The SSH session. * * @return Returns cipher name or NULL. */ const char* ssh_get_cipher_out(ssh_session session) { if ((session != NULL) && (session->current_crypto != NULL) && (session->current_crypto->out_cipher != NULL)) { return session->current_crypto->out_cipher->name; } return NULL; } /** * @brief get the name of the input HMAC algorithm for the given session. * * @param[in] session The SSH session. * * @return Returns HMAC algorithm name or NULL if unknown. */ const char* ssh_get_hmac_in(ssh_session session) { if ((session != NULL) && (session->current_crypto != NULL)) { return ssh_hmac_type_to_string(session->current_crypto->in_hmac, session->current_crypto->in_hmac_etm); } return NULL; } /** * @brief get the name of the output HMAC algorithm for the given session. * * @param[in] session The SSH session. * * @return Returns HMAC algorithm name or NULL if unknown. */ const char* ssh_get_hmac_out(ssh_session session) { if ((session != NULL) && (session->current_crypto != NULL)) { return ssh_hmac_type_to_string(session->current_crypto->out_hmac, session->current_crypto->out_hmac_etm); } return NULL; } /** * @brief Disconnect impolitely from a remote host by closing the socket. * * Suitable if you forked and want to destroy this session. * * @param[in] session The SSH session to disconnect. */ void ssh_silent_disconnect(ssh_session session) { if (session == NULL) { return; } ssh_socket_close(session->socket); session->alive = 0; ssh_disconnect(session); } /** * @brief Set the session in blocking/nonblocking mode. * * @param[in] session The ssh session to change. * * @param[in] blocking Zero for nonblocking mode. */ void ssh_set_blocking(ssh_session session, int blocking) { if (session == NULL) { return; } session->flags &= ~SSH_SESSION_FLAG_BLOCKING; session->flags |= blocking ? SSH_SESSION_FLAG_BLOCKING : 0; } /** * @brief Return the blocking mode of libssh * @param[in] session The SSH session * @returns 0 if the session is nonblocking, * @returns 1 if the functions may block. */ int ssh_is_blocking(ssh_session session) { return (session->flags & SSH_SESSION_FLAG_BLOCKING) ? 1 : 0; } /* Waits until the output socket is empty */ static int ssh_flush_termination(void *c){ ssh_session session = c; if (ssh_socket_buffered_write_bytes(session->socket) == 0 || session->session_state == SSH_SESSION_STATE_ERROR) return 1; else return 0; } /** * @brief Blocking flush of the outgoing buffer * @param[in] session The SSH session * @param[in] timeout Set an upper limit on the time for which this function * will block, in milliseconds. Specifying -1 * means an infinite timeout. This parameter is passed to * the poll() function. * @returns SSH_OK on success, SSH_AGAIN if timeout occurred, * SSH_ERROR otherwise. */ int ssh_blocking_flush(ssh_session session, int timeout){ int rc; if (session == NULL) { return SSH_ERROR; } rc = ssh_handle_packets_termination(session, timeout, ssh_flush_termination, session); if (rc == SSH_ERROR) { return rc; } if (!ssh_flush_termination(session)) { rc = SSH_AGAIN; } return rc; } /** * @brief Check if we are connected. * * @param[in] session The session to check if it is connected. * * @return 1 if we are connected, 0 if not. */ int ssh_is_connected(ssh_session session) { if (session == NULL) { return 0; } return session->alive; } /** * @brief Get the fd of a connection. * * In case you'd need the file descriptor of the connection to the server/client. * * @param[in] session The ssh session to use. * * @return The file descriptor of the connection, or -1 if it is * not connected */ socket_t ssh_get_fd(ssh_session session) { if (session == NULL) { return -1; } return ssh_socket_get_fd(session->socket); } /** * @brief Tell the session it has data to read on the file descriptor without * blocking. * * @param[in] session The ssh session to use. */ void ssh_set_fd_toread(ssh_session session) { if (session == NULL) { return; } ssh_socket_set_read_wontblock(session->socket); } /** * @brief Tell the session it may write to the file descriptor without blocking. * * @param[in] session The ssh session to use. */ void ssh_set_fd_towrite(ssh_session session) { if (session == NULL) { return; } ssh_socket_set_write_wontblock(session->socket); } /** * @brief Tell the session it has an exception to catch on the file descriptor. * * \param[in] session The ssh session to use. */ void ssh_set_fd_except(ssh_session session) { if (session == NULL) { return; } ssh_socket_set_except(session->socket); } /** * @internal * * @brief Poll the current session for an event and call the appropriate * callbacks. This function will not loop until the timeout is expired. * * This will block until one event happens. * * @param[in] session The session handle to use. * * @param[in] timeout Set an upper limit on the time for which this function * will block, in milliseconds. Specifying SSH_TIMEOUT_INFINITE * (-1) means an infinite timeout. * Specifying SSH_TIMEOUT_USER means to use the timeout * specified in options. 0 means poll will return immediately. * This parameter is passed to the poll() function. * * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_handle_packets(ssh_session session, int timeout) { ssh_poll_handle spoll; ssh_poll_ctx ctx; int tm = timeout; int rc; if (session == NULL || session->socket == NULL) { return SSH_ERROR; } spoll = ssh_socket_get_poll_handle(session->socket); ssh_poll_add_events(spoll, POLLIN); ctx = ssh_poll_get_ctx(spoll); if (!ctx) { ctx = ssh_poll_get_default_ctx(session); ssh_poll_ctx_add(ctx, spoll); } if (timeout == SSH_TIMEOUT_USER) { if (ssh_is_blocking(session)) tm = ssh_make_milliseconds(session->opts.timeout, session->opts.timeout_usec); else tm = 0; } rc = ssh_poll_ctx_dopoll(ctx, tm); if (rc == SSH_ERROR) { session->session_state = SSH_SESSION_STATE_ERROR; } return rc; } /** * @internal * * @brief Poll the current session for an event and call the appropriate * callbacks. * * This will block until termination function returns true, or timeout expired. * * @param[in] session The session handle to use. * * @param[in] timeout Set an upper limit on the time for which this function * will block, in milliseconds. Specifying * SSH_TIMEOUT_INFINITE (-1) means an infinite timeout. * Specifying SSH_TIMEOUT_USER means to use the timeout * specified in options. 0 means poll will return * immediately. * SSH_TIMEOUT_DEFAULT uses the session timeout if set or * uses blocking parameters of the session. * This parameter is passed to the poll() function. * * @param[in] fct Termination function to be used to determine if it is * possible to stop polling. * @param[in] user User parameter to be passed to fct termination function. * @returns SSH_OK on success, SSH_AGAIN if timeout occurred, * SSH_ERROR otherwise. */ int ssh_handle_packets_termination(ssh_session session, long timeout, ssh_termination_function fct, void *user) { struct ssh_timestamp ts; long timeout_ms = SSH_TIMEOUT_INFINITE; long tm; int ret = SSH_OK; /* If a timeout has been provided, use it */ if (timeout >= 0) { timeout_ms = timeout; } else { if (ssh_is_blocking(session)) { if (timeout == SSH_TIMEOUT_USER || timeout == SSH_TIMEOUT_DEFAULT) { if (session->opts.timeout > 0 || session->opts.timeout_usec > 0) { timeout_ms = ssh_make_milliseconds(session->opts.timeout, session->opts.timeout_usec); } } } else { timeout_ms = SSH_TIMEOUT_NONBLOCKING; } } /* avoid unnecessary syscall for the SSH_TIMEOUT_NONBLOCKING case */ if (timeout_ms != SSH_TIMEOUT_NONBLOCKING) { ssh_timestamp_init(&ts); } tm = timeout_ms; while(!fct(user)) { ret = ssh_handle_packets(session, tm); if (ret == SSH_ERROR) { break; } if (ssh_timeout_elapsed(&ts, timeout_ms)) { ret = fct(user) ? SSH_OK : SSH_AGAIN; break; } tm = ssh_timeout_update(&ts, timeout_ms); } return ret; } /** * @brief Get session status * * @param session The ssh session to use. * * @returns A bitmask including SSH_CLOSED, SSH_READ_PENDING, SSH_WRITE_PENDING * or SSH_CLOSED_ERROR which respectively means the session is closed, * has data to read on the connection socket and session was closed * due to an error. */ int ssh_get_status(ssh_session session) { int socketstate; int r = 0; if (session == NULL) { return 0; } socketstate = ssh_socket_get_status(session->socket); if (session->session_state == SSH_SESSION_STATE_DISCONNECTED) { r |= SSH_CLOSED; } if (socketstate & SSH_READ_PENDING) { r |= SSH_READ_PENDING; } if (socketstate & SSH_WRITE_PENDING) { r |= SSH_WRITE_PENDING; } if ((session->session_state == SSH_SESSION_STATE_DISCONNECTED && (socketstate & SSH_CLOSED_ERROR)) || session->session_state == SSH_SESSION_STATE_ERROR) { r |= SSH_CLOSED_ERROR; } return r; } /** * @brief Get poll flags for an external mainloop * * @param session The ssh session to use. * * @returns A bitmask including SSH_READ_PENDING or SSH_WRITE_PENDING. * For SSH_READ_PENDING, your invocation of poll() should include * POLLIN. For SSH_WRITE_PENDING, your invocation of poll() should * include POLLOUT. */ int ssh_get_poll_flags(ssh_session session) { if (session == NULL) { return 0; } return ssh_socket_get_poll_flags (session->socket); } /** * @brief Get the disconnect message from the server. * * @param[in] session The ssh session to use. * * @return The message sent by the server along with the * disconnect, or NULL in which case the reason of the * disconnect may be found with ssh_get_error. * * @see ssh_get_error() */ const char *ssh_get_disconnect_message(ssh_session session) { if (session == NULL) { return NULL; } if (session->session_state != SSH_SESSION_STATE_DISCONNECTED) { ssh_set_error(session, SSH_REQUEST_DENIED, "Connection not closed yet"); } else if(!session->discon_msg) { ssh_set_error(session, SSH_FATAL, "Connection correctly closed but no disconnect message"); } else { return session->discon_msg; } return NULL; } /** * @brief Get the protocol version of the session. * * @param session The ssh session to use. * * @return The SSH version as integer, < 0 on error. */ int ssh_get_version(ssh_session session) { if (session == NULL) { return -1; } return 2; } /** * @internal * @brief Callback to be called when the socket received an exception code. * @param user is a pointer to session */ void ssh_socket_exception_callback(int code, int errno_code, void *user){ ssh_session session=(ssh_session)user; SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code); session->session_state = SSH_SESSION_STATE_ERROR; if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) { ssh_set_error(session, SSH_FATAL, "Socket error: disconnected"); } else { ssh_set_error(session, SSH_FATAL, "Socket error: %s", strerror(errno_code)); } session->ssh_connection_callback(session); } /** * @brief Send a message that should be ignored * * @param[in] session The SSH session * @param[in] data Data to be sent * * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_send_ignore (ssh_session session, const char *data) { const int type = SSH2_MSG_IGNORE; int rc; if (ssh_socket_is_open(session->socket)) { rc = ssh_buffer_pack(session->out_buffer, "bs", type, data); if (rc != SSH_OK){ ssh_set_error_oom(session); goto error; } ssh_packet_send(session); ssh_handle_packets(session, 0); } return SSH_OK; error: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; } /** * @brief Send a debug message * * @param[in] session The SSH session * @param[in] message Data to be sent * @param[in] always_display Message SHOULD be displayed by the server. It * SHOULD NOT be displayed unless debugging * information has been explicitly requested. * * @return SSH_OK on success, SSH_ERROR otherwise. */ int ssh_send_debug (ssh_session session, const char *message, int always_display) { int rc; if (ssh_socket_is_open(session->socket)) { rc = ssh_buffer_pack(session->out_buffer, "bbsd", SSH2_MSG_DEBUG, always_display != 0 ? 1 : 0, message, 0); /* empty language tag */ if (rc != SSH_OK) { ssh_set_error_oom(session); goto error; } ssh_packet_send(session); ssh_handle_packets(session, 0); } return SSH_OK; error: ssh_buffer_reinit(session->out_buffer); return SSH_ERROR; } /** * @brief Set the session data counters. * * This functions sets the counter structures to be used to calculate data * which comes in and goes out through the session at different levels. * * @code * struct ssh_counter_struct scounter = { * .in_bytes = 0, * .out_bytes = 0, * .in_packets = 0, * .out_packets = 0 * }; * * struct ssh_counter_struct rcounter = { * .in_bytes = 0, * .out_bytes = 0, * .in_packets = 0, * .out_packets = 0 * }; * * ssh_set_counters(session, &scounter, &rcounter); * @endcode * * @param[in] session The SSH session. * * @param[in] scounter Counter for byte data handled by the session sockets. * * @param[in] rcounter Counter for byte and packet data handled by the session, * prior compression and SSH overhead. */ void ssh_set_counters(ssh_session session, ssh_counter scounter, ssh_counter rcounter) { if (session != NULL) { session->socket_counter = scounter; session->raw_counter = rcounter; } } /** * @deprecated Use ssh_get_publickey_hash() */ int ssh_get_pubkey_hash(ssh_session session, unsigned char **hash) { ssh_key pubkey = NULL; ssh_string pubkey_blob = NULL; MD5CTX ctx; unsigned char *h; int rc; if (session == NULL || hash == NULL) { return SSH_ERROR; } /* In FIPS mode, we cannot use MD5 */ if (ssh_fips_mode()) { ssh_set_error(session, SSH_FATAL, "In FIPS mode MD5 is not allowed." "Try ssh_get_publickey_hash() with" "SSH_PUBLICKEY_HASH_SHA256"); return SSH_ERROR; } *hash = NULL; if (session->current_crypto == NULL || session->current_crypto->server_pubkey == NULL) { ssh_set_error(session,SSH_FATAL,"No current cryptographic context"); return SSH_ERROR; } h = calloc(MD5_DIGEST_LEN, sizeof(unsigned char)); if (h == NULL) { return SSH_ERROR; } ctx = md5_init(); if (ctx == NULL) { SAFE_FREE(h); return SSH_ERROR; } rc = ssh_get_server_publickey(session, &pubkey); if (rc != SSH_OK) { md5_final(h, ctx); SAFE_FREE(h); return SSH_ERROR; } rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); ssh_key_free(pubkey); if (rc != SSH_OK) { md5_final(h, ctx); SAFE_FREE(h); return SSH_ERROR; } md5_update(ctx, ssh_string_data(pubkey_blob), ssh_string_len(pubkey_blob)); SSH_STRING_FREE(pubkey_blob); md5_final(h, ctx); *hash = h; return MD5_DIGEST_LEN; } /** * @brief Deallocate the hash obtained by ssh_get_pubkey_hash. * * This is required under Microsoft platform as this library might use a * different C library than your software, hence a different heap. * * @param[in] hash The buffer to deallocate. * * @see ssh_get_pubkey_hash() */ void ssh_clean_pubkey_hash(unsigned char **hash) { SAFE_FREE(*hash); } /** * @brief Get the server public key from a session. * * @param[in] session The session to get the key from. * * @param[out] key A pointer to store the allocated key. You need to free * the key. * * @return SSH_OK on success, SSH_ERROR on errror. * * @see ssh_key_free() */ int ssh_get_server_publickey(ssh_session session, ssh_key *key) { ssh_key pubkey = NULL; if (session == NULL || session->current_crypto == NULL || session->current_crypto->server_pubkey == NULL) { return SSH_ERROR; } pubkey = ssh_key_dup(session->current_crypto->server_pubkey); if (pubkey == NULL) { return SSH_ERROR; } *key = pubkey; return SSH_OK; } /** * @deprecated Use ssh_get_server_publickey() */ int ssh_get_publickey(ssh_session session, ssh_key *key) { return ssh_get_server_publickey(session, key); } /** * @brief Allocates a buffer with the hash of the public key. * * This function allows you to get a hash of the public key. You can then * print this hash in a human-readable form to the user so that he is able to * verify it. Use ssh_get_hexa() or ssh_print_hash() to display it. * * @param[in] key The public key to create the hash for. * * @param[in] type The type of the hash you want. * * @param[in] hash A pointer to store the allocated buffer. It can be * freed using ssh_clean_pubkey_hash(). * * @param[in] hlen The length of the hash. * * @return 0 on success, -1 if an error occured. * * @warning It is very important that you verify at some moment that the hash * matches a known server. If you don't do it, cryptography wont help * you at making things secure. * OpenSSH uses SHA256 to print public key digests. * * @see ssh_session_update_known_hosts() * @see ssh_get_hexa() * @see ssh_print_hash() * @see ssh_clean_pubkey_hash() */ int ssh_get_publickey_hash(const ssh_key key, enum ssh_publickey_hash_type type, unsigned char **hash, size_t *hlen) { ssh_string blob; unsigned char *h; int rc; rc = ssh_pki_export_pubkey_blob(key, &blob); if (rc < 0) { return rc; } switch (type) { case SSH_PUBLICKEY_HASH_SHA1: { SHACTX ctx; h = calloc(1, SHA_DIGEST_LEN); if (h == NULL) { rc = -1; goto out; } ctx = sha1_init(); if (ctx == NULL) { free(h); rc = -1; goto out; } sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); sha1_final(h, ctx); *hlen = SHA_DIGEST_LEN; } break; case SSH_PUBLICKEY_HASH_SHA256: { SHA256CTX ctx; h = calloc(1, SHA256_DIGEST_LEN); if (h == NULL) { rc = -1; goto out; } ctx = sha256_init(); if (ctx == NULL) { free(h); rc = -1; goto out; } sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); sha256_final(h, ctx); *hlen = SHA256_DIGEST_LEN; } break; case SSH_PUBLICKEY_HASH_MD5: { MD5CTX ctx; /* In FIPS mode, we cannot use MD5 */ if (ssh_fips_mode()) { SSH_LOG(SSH_LOG_WARN, "In FIPS mode MD5 is not allowed." "Try using SSH_PUBLICKEY_HASH_SHA256"); rc = SSH_ERROR; goto out; } h = calloc(1, MD5_DIGEST_LEN); if (h == NULL) { rc = -1; goto out; } ctx = md5_init(); if (ctx == NULL) { free(h); rc = -1; goto out; } md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob)); md5_final(h, ctx); *hlen = MD5_DIGEST_LEN; } break; default: rc = -1; goto out; } *hash = h; rc = 0; out: SSH_STRING_FREE(blob); return rc; } /** @} */ ================================================ FILE: src/libssh/src/sftp.c ================================================ /* * sftp.c - Secure FTP functions * * This file is part of the SSH Library * * Copyright (c) 2005-2008 by Aris Adamantiadis * Copyright (c) 2008-2018 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* This file contains code written by Nick Zitzmann */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/ssh2.h" #include "libssh/sftp.h" #include "libssh/sftp_priv.h" #include "libssh/buffer.h" #include "libssh/channels.h" #include "libssh/session.h" #include "libssh/misc.h" #include "libssh/bytearray.h" #ifdef WITH_SFTP /* Buffer size maximum is 256M */ #define SFTP_PACKET_SIZE_MAX 0x10000000 #define SFTP_BUFFER_SIZE_MAX 16384 struct sftp_ext_struct { uint32_t count; char **name; char **data; }; /* functions */ static int sftp_enqueue(sftp_session session, sftp_message msg); static void sftp_message_free(sftp_message msg); static void sftp_set_error(sftp_session sftp, int errnum); static void status_msg_free(sftp_status_message status); static sftp_ext sftp_ext_new(void) { sftp_ext ext; ext = calloc(1, sizeof(struct sftp_ext_struct)); if (ext == NULL) { return NULL; } return ext; } static void sftp_ext_free(sftp_ext ext) { size_t i; if (ext == NULL) { return; } if (ext->count > 0) { if (ext->name != NULL) { for (i = 0; i < ext->count; i++) { SAFE_FREE(ext->name[i]); } SAFE_FREE(ext->name); } if (ext->data != NULL) { for (i = 0; i < ext->count; i++) { SAFE_FREE(ext->data[i]); } SAFE_FREE(ext->data); } } SAFE_FREE(ext); } sftp_session sftp_new(ssh_session session) { sftp_session sftp; if (session == NULL) { return NULL; } sftp = calloc(1, sizeof(struct sftp_session_struct)); if (sftp == NULL) { ssh_set_error_oom(session); return NULL; } sftp->ext = sftp_ext_new(); if (sftp->ext == NULL) { ssh_set_error_oom(session); goto error; } sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct)); if (sftp->read_packet == NULL) { ssh_set_error_oom(session); goto error; } sftp->read_packet->payload = ssh_buffer_new(); if (sftp->read_packet->payload == NULL) { ssh_set_error_oom(session); goto error; } sftp->session = session; sftp->channel = ssh_channel_new(session); if (sftp->channel == NULL) { ssh_set_error_oom(session); goto error; } if (ssh_channel_open_session(sftp->channel)) { goto error; } if (ssh_channel_request_sftp(sftp->channel)) { goto error; } return sftp; error: if (sftp->ext != NULL) { sftp_ext_free(sftp->ext); } if (sftp->channel != NULL) { ssh_channel_free(sftp->channel); } if (sftp->read_packet != NULL) { if (sftp->read_packet->payload != NULL) { SSH_BUFFER_FREE(sftp->read_packet->payload); } SAFE_FREE(sftp->read_packet); } SAFE_FREE(sftp); return NULL; } sftp_session sftp_new_channel(ssh_session session, ssh_channel channel){ sftp_session sftp; if (session == NULL) { return NULL; } sftp = calloc(1, sizeof(struct sftp_session_struct)); if (sftp == NULL) { ssh_set_error_oom(session); return NULL; } sftp->ext = sftp_ext_new(); if (sftp->ext == NULL) { ssh_set_error_oom(session); SAFE_FREE(sftp); return NULL; } sftp->session = session; sftp->channel = channel; return sftp; } #ifdef WITH_SERVER sftp_session sftp_server_new(ssh_session session, ssh_channel chan){ sftp_session sftp = NULL; sftp = calloc(1, sizeof(struct sftp_session_struct)); if (sftp == NULL) { ssh_set_error_oom(session); return NULL; } sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct)); if (sftp->read_packet == NULL) { goto error; } sftp->read_packet->payload = ssh_buffer_new(); if (sftp->read_packet->payload == NULL) { goto error; } sftp->session = session; sftp->channel = chan; return sftp; error: ssh_set_error_oom(session); if (sftp->read_packet != NULL) { if (sftp->read_packet->payload != NULL) { SSH_BUFFER_FREE(sftp->read_packet->payload); } SAFE_FREE(sftp->read_packet); } SAFE_FREE(sftp); return NULL; } int sftp_server_init(sftp_session sftp){ ssh_session session = sftp->session; sftp_packet packet = NULL; ssh_buffer reply = NULL; uint32_t version; int rc; packet = sftp_packet_read(sftp); if (packet == NULL) { return -1; } if (packet->type != SSH_FXP_INIT) { ssh_set_error(session, SSH_FATAL, "Packet read of type %d instead of SSH_FXP_INIT", packet->type); return -1; } SSH_LOG(SSH_LOG_PACKET, "Received SSH_FXP_INIT"); ssh_buffer_get_u32(packet->payload, &version); version = ntohl(version); SSH_LOG(SSH_LOG_PACKET, "Client version: %d", version); sftp->client_version = (int)version; reply = ssh_buffer_new(); if (reply == NULL) { ssh_set_error_oom(session); return -1; } rc = ssh_buffer_pack(reply, "dssss", LIBSFTP_VERSION, "posix-rename@openssh.com", "1", "hardlink@openssh.com", "1"); if (rc != SSH_OK) { ssh_set_error_oom(session); SSH_BUFFER_FREE(reply); return -1; } if (sftp_packet_write(sftp, SSH_FXP_VERSION, reply) < 0) { SSH_BUFFER_FREE(reply); return -1; } SSH_BUFFER_FREE(reply); SSH_LOG(SSH_LOG_PROTOCOL, "Server version sent"); if (version > LIBSFTP_VERSION) { sftp->version = LIBSFTP_VERSION; } else { sftp->version = (int)version; } return 0; } void sftp_server_free(sftp_session sftp) { sftp_request_queue ptr; if (sftp == NULL) { return; } ptr = sftp->queue; while(ptr) { sftp_request_queue old; sftp_message_free(ptr->message); old = ptr->next; SAFE_FREE(ptr); ptr = old; } SAFE_FREE(sftp->handles); SSH_BUFFER_FREE(sftp->read_packet->payload); SAFE_FREE(sftp->read_packet); sftp_ext_free(sftp->ext); SAFE_FREE(sftp); } #endif /* WITH_SERVER */ void sftp_free(sftp_session sftp) { sftp_request_queue ptr; if (sftp == NULL) { return; } if (sftp->channel != NULL) { ssh_channel_send_eof(sftp->channel); ptr = sftp->queue; while(ptr) { sftp_request_queue old; sftp_message_free(ptr->message); old = ptr->next; SAFE_FREE(ptr); ptr = old; } ssh_channel_free(sftp->channel); sftp->channel = NULL; } SAFE_FREE(sftp->handles); SSH_BUFFER_FREE(sftp->read_packet->payload); SAFE_FREE(sftp->read_packet); sftp_ext_free(sftp->ext); SAFE_FREE(sftp); } ssize_t sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload) { uint8_t header[5] = {0}; uint32_t payload_size; ssize_t size; int rc; /* Add size of type */ payload_size = ssh_buffer_get_len(payload) + sizeof(uint8_t); PUSH_BE_U32(header, 0, payload_size); PUSH_BE_U8(header, 4, type); rc = ssh_buffer_prepend_data(payload, header, sizeof(header)); if (rc < 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } size = ssh_channel_write(sftp->channel, ssh_buffer_get(payload), ssh_buffer_get_len(payload)); if (size < 0) { sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if ((uint32_t)size != ssh_buffer_get_len(payload)) { SSH_LOG(SSH_LOG_PACKET, "Had to write %d bytes, wrote only %zd", ssh_buffer_get_len(payload), size); } return size; } sftp_packet sftp_packet_read(sftp_session sftp) { uint8_t buffer[SFTP_BUFFER_SIZE_MAX]; sftp_packet packet = sftp->read_packet; uint32_t size; int nread; bool is_eof; int rc; packet->sftp = sftp; /* * If the packet has a payload, then just reinit the buffer, otherwise * allocate a new one. */ if (packet->payload != NULL) { rc = ssh_buffer_reinit(packet->payload); if (rc != 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } } else { packet->payload = ssh_buffer_new(); if (packet->payload == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } } nread = 0; do { int s; // read from channel until 4 bytes have been read or an error occurs s = ssh_channel_read(sftp->channel, buffer + nread, 4 - nread, 0); if (s < 0) { goto error; } else if (s == 0) { is_eof = ssh_channel_is_eof(sftp->channel); if (is_eof) { ssh_set_error(sftp->session, SSH_FATAL, "Received EOF while reading sftp packet size"); sftp_set_error(sftp, SSH_FX_EOF); goto error; } } else { nread += s; } } while (nread < 4); size = PULL_BE_U32(buffer, 0); if (size == 0 || size > SFTP_PACKET_SIZE_MAX) { ssh_set_error(sftp->session, SSH_FATAL, "Invalid sftp packet size!"); sftp_set_error(sftp, SSH_FX_FAILURE); goto error; } do { nread = ssh_channel_read(sftp->channel, buffer, 1, 0); if (nread < 0) { goto error; } else if (nread == 0) { is_eof = ssh_channel_is_eof(sftp->channel); if (is_eof) { ssh_set_error(sftp->session, SSH_FATAL, "Received EOF while reading sftp packet type"); sftp_set_error(sftp, SSH_FX_EOF); goto error; } } } while (nread < 1); packet->type = buffer[0]; /* Remove the packet type size */ size -= sizeof(uint8_t); nread = ssh_buffer_allocate_size(packet->payload, size); if (nread < 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); goto error; } while (size > 0 && size < SFTP_PACKET_SIZE_MAX) { nread = ssh_channel_read(sftp->channel, buffer, sizeof(buffer) > size ? size : sizeof(buffer), 0); if (nread < 0) { /* TODO: check if there are cases where an error needs to be set here */ goto error; } if (nread > 0) { rc = ssh_buffer_add_data(packet->payload, buffer, nread); if (rc != 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); goto error; } } else { /* nread == 0 */ /* Retry the reading unless the remote was closed */ is_eof = ssh_channel_is_eof(sftp->channel); if (is_eof) { ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "Received EOF while reading sftp packet"); sftp_set_error(sftp, SSH_FX_EOF); goto error; } } size -= nread; } return packet; error: ssh_buffer_reinit(packet->payload); return NULL; } static void sftp_set_error(sftp_session sftp, int errnum) { if (sftp != NULL) { sftp->errnum = errnum; } } /* Get the last sftp error */ int sftp_get_error(sftp_session sftp) { if (sftp == NULL) { return -1; } return sftp->errnum; } static void sftp_message_free(sftp_message msg) { if (msg == NULL) { return; } SSH_BUFFER_FREE(msg->payload); SAFE_FREE(msg); } static sftp_message sftp_get_message(sftp_packet packet) { sftp_session sftp = packet->sftp; sftp_message msg = NULL; int rc; switch(packet->type) { case SSH_FXP_STATUS: case SSH_FXP_HANDLE: case SSH_FXP_DATA: case SSH_FXP_ATTRS: case SSH_FXP_NAME: case SSH_FXP_EXTENDED_REPLY: break; default: ssh_set_error(packet->sftp->session, SSH_FATAL, "Unknown packet type %d", packet->type); sftp_set_error(packet->sftp, SSH_FX_FAILURE); return NULL; } msg = calloc(1, sizeof(struct sftp_message_struct)); if (msg == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(packet->sftp, SSH_FX_FAILURE); return NULL; } msg->sftp = packet->sftp; msg->packet_type = packet->type; /* Move the payload from the packet to the message */ msg->payload = packet->payload; packet->payload = NULL; rc = ssh_buffer_unpack(msg->payload, "d", &msg->id); if (rc != SSH_OK) { ssh_set_error(packet->sftp->session, SSH_FATAL, "Invalid packet %d: no ID", packet->type); sftp_message_free(msg); sftp_set_error(packet->sftp, SSH_FX_FAILURE); return NULL; } SSH_LOG(SSH_LOG_PACKET, "Packet with id %d type %d", msg->id, msg->packet_type); return msg; } static int sftp_read_and_dispatch(sftp_session sftp) { sftp_packet packet = NULL; sftp_message msg = NULL; packet = sftp_packet_read(sftp); if (packet == NULL) { /* something nasty happened reading the packet */ return -1; } msg = sftp_get_message(packet); if (msg == NULL) { return -1; } if (sftp_enqueue(sftp, msg) < 0) { sftp_message_free(msg); return -1; } return 0; } void sftp_packet_free(sftp_packet packet) { if (packet == NULL) { return; } SSH_BUFFER_FREE(packet->payload); free(packet); } /* Initialize the sftp session with the server. */ int sftp_init(sftp_session sftp) { sftp_packet packet = NULL; ssh_buffer buffer = NULL; char *ext_name = NULL; char *ext_data = NULL; uint32_t version; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = ssh_buffer_pack(buffer, "d", LIBSFTP_VERSION); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(sftp, SSH_FXP_INIT, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); packet = sftp_packet_read(sftp); if (packet == NULL) { return -1; } if (packet->type != SSH_FXP_VERSION) { ssh_set_error(sftp->session, SSH_FATAL, "Received a %d messages instead of SSH_FXP_VERSION", packet->type); return -1; } /* TODO: are we sure there are 4 bytes ready? */ rc = ssh_buffer_unpack(packet->payload, "d", &version); if (rc != SSH_OK){ sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } SSH_LOG(SSH_LOG_PROTOCOL, "SFTP server version %d", version); rc = ssh_buffer_unpack(packet->payload, "s", &ext_name); while (rc == SSH_OK) { uint32_t count = sftp->ext->count; char **tmp; rc = ssh_buffer_unpack(packet->payload, "s", &ext_data); if (rc == SSH_ERROR) { break; } SSH_LOG(SSH_LOG_PROTOCOL, "SFTP server extension: %s, version: %s", ext_name, ext_data); count++; tmp = realloc(sftp->ext->name, count * sizeof(char *)); if (tmp == NULL) { ssh_set_error_oom(sftp->session); SAFE_FREE(ext_name); SAFE_FREE(ext_data); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } tmp[count - 1] = ext_name; sftp->ext->name = tmp; tmp = realloc(sftp->ext->data, count * sizeof(char *)); if (tmp == NULL) { ssh_set_error_oom(sftp->session); SAFE_FREE(ext_name); SAFE_FREE(ext_data); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } tmp[count - 1] = ext_data; sftp->ext->data = tmp; sftp->ext->count = count; rc = ssh_buffer_unpack(packet->payload, "s", &ext_name); } sftp->version = sftp->server_version = (int)version; return 0; } unsigned int sftp_extensions_get_count(sftp_session sftp) { if (sftp == NULL || sftp->ext == NULL) { return 0; } return sftp->ext->count; } const char *sftp_extensions_get_name(sftp_session sftp, unsigned int idx) { if (sftp == NULL) return NULL; if (sftp->ext == NULL || sftp->ext->name == NULL) { ssh_set_error_invalid(sftp->session); return NULL; } if (idx > sftp->ext->count) { ssh_set_error_invalid(sftp->session); return NULL; } return sftp->ext->name[idx]; } const char *sftp_extensions_get_data(sftp_session sftp, unsigned int idx) { if (sftp == NULL) return NULL; if (sftp->ext == NULL || sftp->ext->name == NULL) { ssh_set_error_invalid(sftp->session); return NULL; } if (idx > sftp->ext->count) { ssh_set_error_invalid(sftp->session); return NULL; } return sftp->ext->data[idx]; } int sftp_extension_supported(sftp_session sftp, const char *name, const char *data) { size_t i, n; if (sftp == NULL || name == NULL || data == NULL) { return 0; } n = sftp_extensions_get_count(sftp); for (i = 0; i < n; i++) { const char *ext_name = sftp_extensions_get_name(sftp, i); const char *ext_data = sftp_extensions_get_data(sftp, i); if (ext_name != NULL && ext_data != NULL && strcmp(ext_name, name) == 0 && strcmp(ext_data, data) == 0) { return 1; } } return 0; } static sftp_request_queue request_queue_new(sftp_message msg) { sftp_request_queue queue = NULL; queue = calloc(1, sizeof(struct sftp_request_queue_struct)); if (queue == NULL) { ssh_set_error_oom(msg->sftp->session); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } queue->message = msg; return queue; } static void request_queue_free(sftp_request_queue queue) { if (queue == NULL) { return; } ZERO_STRUCTP(queue); SAFE_FREE(queue); } static int sftp_enqueue(sftp_session sftp, sftp_message msg) { sftp_request_queue queue = NULL; sftp_request_queue ptr; queue = request_queue_new(msg); if (queue == NULL) { return -1; } SSH_LOG(SSH_LOG_PACKET, "Queued msg id %d type %d", msg->id, msg->packet_type); if(sftp->queue == NULL) { sftp->queue = queue; } else { ptr = sftp->queue; while(ptr->next) { ptr=ptr->next; /* find end of linked list */ } ptr->next = queue; /* add it on bottom */ } return 0; } /* * Pulls of a message from the queue based on the ID. * Returns NULL if no message has been found. */ static sftp_message sftp_dequeue(sftp_session sftp, uint32_t id){ sftp_request_queue prev = NULL; sftp_request_queue queue; sftp_message msg; if(sftp->queue == NULL) { return NULL; } queue = sftp->queue; while (queue) { if(queue->message->id == id) { /* remove from queue */ if (prev == NULL) { sftp->queue = queue->next; } else { prev->next = queue->next; } msg = queue->message; request_queue_free(queue); SSH_LOG(SSH_LOG_PACKET, "Dequeued msg id %d type %d", msg->id, msg->packet_type); return msg; } prev = queue; queue = queue->next; } return NULL; } /* * Assigns a new SFTP ID for new requests and assures there is no collision * between them. * Returns a new ID ready to use in a request */ static inline uint32_t sftp_get_new_id(sftp_session session) { return ++session->id_counter; } static sftp_status_message parse_status_msg(sftp_message msg){ sftp_status_message status; int rc; if (msg->packet_type != SSH_FXP_STATUS) { ssh_set_error(msg->sftp->session, SSH_FATAL, "Not a ssh_fxp_status message passed in!"); sftp_set_error(msg->sftp, SSH_FX_BAD_MESSAGE); return NULL; } status = calloc(1, sizeof(struct sftp_status_message_struct)); if (status == NULL) { ssh_set_error_oom(msg->sftp->session); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } status->id = msg->id; rc = ssh_buffer_unpack(msg->payload, "d", &status->status); if (rc != SSH_OK){ SAFE_FREE(status); ssh_set_error(msg->sftp->session, SSH_FATAL, "Invalid SSH_FXP_STATUS message"); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } rc = ssh_buffer_unpack(msg->payload, "ss", &status->errormsg, &status->langmsg); if(rc != SSH_OK && msg->sftp->version >=3){ /* These are mandatory from version 3 */ SAFE_FREE(status); ssh_set_error(msg->sftp->session, SSH_FATAL, "Invalid SSH_FXP_STATUS message"); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } if (status->errormsg == NULL) status->errormsg = strdup("No error message in packet"); if (status->langmsg == NULL) status->langmsg = strdup(""); if (status->errormsg == NULL || status->langmsg == NULL) { ssh_set_error_oom(msg->sftp->session); sftp_set_error(msg->sftp, SSH_FX_FAILURE); status_msg_free(status); return NULL; } return status; } static void status_msg_free(sftp_status_message status){ if (status == NULL) { return; } SAFE_FREE(status->errormsg); SAFE_FREE(status->langmsg); SAFE_FREE(status); } static sftp_file parse_handle_msg(sftp_message msg){ sftp_file file; if(msg->packet_type != SSH_FXP_HANDLE) { ssh_set_error(msg->sftp->session, SSH_FATAL, "Not a ssh_fxp_handle message passed in!"); return NULL; } file = calloc(1, sizeof(struct sftp_file_struct)); if (file == NULL) { ssh_set_error_oom(msg->sftp->session); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } file->handle = ssh_buffer_get_ssh_string(msg->payload); if (file->handle == NULL) { ssh_set_error(msg->sftp->session, SSH_FATAL, "Invalid SSH_FXP_HANDLE message"); SAFE_FREE(file); sftp_set_error(msg->sftp, SSH_FX_FAILURE); return NULL; } file->sftp = msg->sftp; file->offset = 0; file->eof = 0; return file; } /* Open a directory */ sftp_dir sftp_opendir(sftp_session sftp, const char *path) { sftp_message msg = NULL; sftp_file file = NULL; sftp_dir dir = NULL; sftp_status_message status; ssh_buffer payload; uint32_t id; int rc; if (sftp == NULL) { return NULL; } payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(payload, "ds", id, path); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(payload); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_OPENDIR, payload); SSH_BUFFER_FREE(payload); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { /* something nasty has happened */ return NULL; } msg = sftp_dequeue(sftp, id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return NULL; case SSH_FXP_HANDLE: file = parse_handle_msg(msg); sftp_message_free(msg); if (file != NULL) { dir = calloc(1, sizeof(struct sftp_dir_struct)); if (dir == NULL) { ssh_set_error_oom(sftp->session); free(file); return NULL; } dir->sftp = sftp; dir->name = strdup(path); if (dir->name == NULL) { SAFE_FREE(dir); SAFE_FREE(file); return NULL; } dir->handle = file->handle; SAFE_FREE(file); } return dir; default: ssh_set_error(sftp->session, SSH_FATAL, "Received message %d during opendir!", msg->packet_type); sftp_message_free(msg); } return NULL; } /* * Parse the attributes from a payload from some messages. It is coded on * baselines from the protocol version 4. * This code is more or less dead but maybe we need it in future. */ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf, int expectnames) { sftp_attributes attr; ssh_string owner = NULL; ssh_string group = NULL; uint32_t flags = 0; int ok = 0; /* unused member variable */ (void) expectnames; attr = calloc(1, sizeof(struct sftp_attributes_struct)); if (attr == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } /* This isn't really a loop, but it is like a try..catch.. */ do { if (ssh_buffer_get_u32(buf, &flags) != 4) { break; } flags = ntohl(flags); attr->flags = flags; if (flags & SSH_FILEXFER_ATTR_SIZE) { if (ssh_buffer_get_u64(buf, &attr->size) != 8) { break; } attr->size = ntohll(attr->size); } if (flags & SSH_FILEXFER_ATTR_OWNERGROUP) { owner = ssh_buffer_get_ssh_string(buf); if (owner == NULL) { break; } attr->owner = ssh_string_to_char(owner); SSH_STRING_FREE(owner); if (attr->owner == NULL) { break; } group = ssh_buffer_get_ssh_string(buf); if (group == NULL) { break; } attr->group = ssh_string_to_char(group); SSH_STRING_FREE(group); if (attr->group == NULL) { break; } } if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { if (ssh_buffer_get_u32(buf, &attr->permissions) != 4) { break; } attr->permissions = ntohl(attr->permissions); /* FIXME on windows! */ switch (attr->permissions & SSH_S_IFMT) { case SSH_S_IFSOCK: case SSH_S_IFBLK: case SSH_S_IFCHR: case SSH_S_IFIFO: attr->type = SSH_FILEXFER_TYPE_SPECIAL; break; case SSH_S_IFLNK: attr->type = SSH_FILEXFER_TYPE_SYMLINK; break; case SSH_S_IFREG: attr->type = SSH_FILEXFER_TYPE_REGULAR; break; case SSH_S_IFDIR: attr->type = SSH_FILEXFER_TYPE_DIRECTORY; break; default: attr->type = SSH_FILEXFER_TYPE_UNKNOWN; break; } } if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { if (ssh_buffer_get_u64(buf, &attr->atime64) != 8) { break; } attr->atime64 = ntohll(attr->atime64); if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) { if (ssh_buffer_get_u32(buf, &attr->atime_nseconds) != 4) { break; } attr->atime_nseconds = ntohl(attr->atime_nseconds); } } if (flags & SSH_FILEXFER_ATTR_CREATETIME) { if (ssh_buffer_get_u64(buf, &attr->createtime) != 8) { break; } attr->createtime = ntohll(attr->createtime); if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) { if (ssh_buffer_get_u32(buf, &attr->createtime_nseconds) != 4) { break; } attr->createtime_nseconds = ntohl(attr->createtime_nseconds); } } if (flags & SSH_FILEXFER_ATTR_MODIFYTIME) { if (ssh_buffer_get_u64(buf, &attr->mtime64) != 8) { break; } attr->mtime64 = ntohll(attr->mtime64); if (flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) { if (ssh_buffer_get_u32(buf, &attr->mtime_nseconds) != 4) { break; } attr->mtime_nseconds = ntohl(attr->mtime_nseconds); } } if (flags & SSH_FILEXFER_ATTR_ACL) { if ((attr->acl = ssh_buffer_get_ssh_string(buf)) == NULL) { break; } } if (flags & SSH_FILEXFER_ATTR_EXTENDED) { if (ssh_buffer_get_u32(buf,&attr->extended_count) != 4) { break; } attr->extended_count = ntohl(attr->extended_count); while(attr->extended_count && (attr->extended_type = ssh_buffer_get_ssh_string(buf)) && (attr->extended_data = ssh_buffer_get_ssh_string(buf))){ attr->extended_count--; } if (attr->extended_count) { break; } } ok = 1; } while (0); if (ok == 0) { /* break issued somewhere */ SSH_STRING_FREE(attr->acl); SSH_STRING_FREE(attr->extended_type); SSH_STRING_FREE(attr->extended_data); SAFE_FREE(attr->owner); SAFE_FREE(attr->group); SAFE_FREE(attr); ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); return NULL; } return attr; } enum sftp_longname_field_e { SFTP_LONGNAME_PERM = 0, SFTP_LONGNAME_FIXME, SFTP_LONGNAME_OWNER, SFTP_LONGNAME_GROUP, SFTP_LONGNAME_SIZE, SFTP_LONGNAME_DATE, SFTP_LONGNAME_TIME, SFTP_LONGNAME_NAME, }; static char *sftp_parse_longname(const char *longname, enum sftp_longname_field_e longname_field) { const char *p, *q; size_t len, field = 0; p = longname; /* Find the beginning of the field which is specified by sftp_longanme_field_e. */ while(field != longname_field) { if(isspace(*p)) { field++; p++; while(*p && isspace(*p)) { p++; } } else { p++; } } q = p; while (! isspace(*q)) { q++; } len = q - p; return strndup(p, len); } /* sftp version 0-3 code. It is different from the v4 */ /* maybe a paste of the draft is better than the code */ /* uint32 flags uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS uint32 atime present only if flag SSH_FILEXFER_ACMODTIME uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED string extended_type string extended_data ... more extended data (extended_type - extended_data pairs), so that number of pairs equals extended_count */ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf, int expectname) { sftp_attributes attr; int rc; attr = calloc(1, sizeof(struct sftp_attributes_struct)); if (attr == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } if (expectname) { rc = ssh_buffer_unpack(buf, "ss", &attr->name, &attr->longname); if (rc != SSH_OK){ goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "Name: %s", attr->name); /* Set owner and group if we talk to openssh and have the longname */ if (ssh_get_openssh_version(sftp->session)) { attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER); if (attr->owner == NULL) { goto error; } attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP); if (attr->group == NULL) { goto error; } } } rc = ssh_buffer_unpack(buf, "d", &attr->flags); if (rc != SSH_OK){ goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "Flags: %.8"PRIx32"\n", (uint32_t) attr->flags); if (attr->flags & SSH_FILEXFER_ATTR_SIZE) { rc = ssh_buffer_unpack(buf, "q", &attr->size); if(rc != SSH_OK) { goto error; } SSH_LOG(SSH_LOG_PROTOCOL, "Size: %"PRIu64"\n", (uint64_t) attr->size); } if (attr->flags & SSH_FILEXFER_ATTR_UIDGID) { rc = ssh_buffer_unpack(buf, "dd", &attr->uid, &attr->gid); if (rc != SSH_OK){ goto error; } } if (attr->flags & SSH_FILEXFER_ATTR_PERMISSIONS) { rc = ssh_buffer_unpack(buf, "d", &attr->permissions); if (rc != SSH_OK){ goto error; } switch (attr->permissions & SSH_S_IFMT) { case SSH_S_IFSOCK: case SSH_S_IFBLK: case SSH_S_IFCHR: case SSH_S_IFIFO: attr->type = SSH_FILEXFER_TYPE_SPECIAL; break; case SSH_S_IFLNK: attr->type = SSH_FILEXFER_TYPE_SYMLINK; break; case SSH_S_IFREG: attr->type = SSH_FILEXFER_TYPE_REGULAR; break; case SSH_S_IFDIR: attr->type = SSH_FILEXFER_TYPE_DIRECTORY; break; default: attr->type = SSH_FILEXFER_TYPE_UNKNOWN; break; } } if (attr->flags & SSH_FILEXFER_ATTR_ACMODTIME) { rc = ssh_buffer_unpack(buf, "dd", &attr->atime, &attr->mtime); if (rc != SSH_OK){ goto error; } } if (attr->flags & SSH_FILEXFER_ATTR_EXTENDED) { rc = ssh_buffer_unpack(buf, "d", &attr->extended_count); if (rc != SSH_OK){ goto error; } if (attr->extended_count > 0){ rc = ssh_buffer_unpack(buf, "ss", &attr->extended_type, &attr->extended_data); if (rc != SSH_OK){ goto error; } attr->extended_count--; } /* just ignore the remaining extensions */ while (attr->extended_count > 0){ ssh_string tmp1,tmp2; rc = ssh_buffer_unpack(buf, "SS", &tmp1, &tmp2); if (rc != SSH_OK){ goto error; } SAFE_FREE(tmp1); SAFE_FREE(tmp2); attr->extended_count--; } } return attr; error: SSH_STRING_FREE(attr->extended_type); SSH_STRING_FREE(attr->extended_data); SAFE_FREE(attr->name); SAFE_FREE(attr->longname); SAFE_FREE(attr->owner); SAFE_FREE(attr->group); SAFE_FREE(attr); ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure"); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } int buffer_add_attributes(ssh_buffer buffer, sftp_attributes attr) { uint32_t flags = (attr ? attr->flags : 0); int rc; flags &= (SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME); rc = ssh_buffer_pack(buffer, "d", flags); if (rc != SSH_OK) { return -1; } if (attr != NULL) { if (flags & SSH_FILEXFER_ATTR_SIZE) { rc = ssh_buffer_pack(buffer, "q", attr->size); if (rc != SSH_OK) { return -1; } } if (flags & SSH_FILEXFER_ATTR_UIDGID) { rc = ssh_buffer_pack(buffer, "dd", attr->uid, attr->gid); if (rc != SSH_OK) { return -1; } } if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { rc = ssh_buffer_pack(buffer, "d", attr->permissions); if (rc != SSH_OK) { return -1; } } if (flags & SSH_FILEXFER_ATTR_ACMODTIME) { rc = ssh_buffer_pack(buffer, "dd", attr->atime, attr->mtime); if (rc != SSH_OK) { return -1; } } } return 0; } sftp_attributes sftp_parse_attr(sftp_session session, ssh_buffer buf, int expectname) { switch(session->version) { case 4: return sftp_parse_attr_4(session, buf, expectname); case 3: case 2: case 1: case 0: return sftp_parse_attr_3(session, buf, expectname); default: ssh_set_error(session->session, SSH_FATAL, "Version %d unsupported by client", session->server_version); return NULL; } return NULL; } /* Get the version of the SFTP protocol supported by the server */ int sftp_server_version(sftp_session sftp) { return sftp->server_version; } /* Get a single file attributes structure of a directory. */ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir) { sftp_message msg = NULL; sftp_status_message status; sftp_attributes attr; ssh_buffer payload; uint32_t id; int rc; if (dir->buffer == NULL) { payload = ssh_buffer_new(); if (payload == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(payload, "dS", id, dir->handle); if (rc != 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); SSH_BUFFER_FREE(payload); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_READDIR, payload); SSH_BUFFER_FREE(payload); if (rc < 0) { return NULL; } SSH_LOG(SSH_LOG_PACKET, "Sent a ssh_fxp_readdir with id %d", id); while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { /* something nasty has happened */ return NULL; } msg = sftp_dequeue(sftp, id); } switch (msg->packet_type){ case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_EOF: dir->eof = 1; status_msg_free(status); return NULL; default: break; } ssh_set_error(sftp->session, SSH_FATAL, "Unknown error status: %d", status->status); status_msg_free(status); return NULL; case SSH_FXP_NAME: ssh_buffer_get_u32(msg->payload, &dir->count); dir->count = ntohl(dir->count); dir->buffer = msg->payload; msg->payload = NULL; sftp_message_free(msg); break; default: ssh_set_error(sftp->session, SSH_FATAL, "Unsupported message back %d", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); return NULL; } } /* now dir->buffer contains a buffer and dir->count != 0 */ if (dir->count == 0) { ssh_set_error(sftp->session, SSH_FATAL, "Count of files sent by the server is zero, which is invalid, or " "libsftp bug"); return NULL; } SSH_LOG(SSH_LOG_PROTOCOL, "Count is %d", dir->count); attr = sftp_parse_attr(sftp, dir->buffer, 1); if (attr == NULL) { ssh_set_error(sftp->session, SSH_FATAL, "Couldn't parse the SFTP attributes"); return NULL; } dir->count--; if (dir->count == 0) { SSH_BUFFER_FREE(dir->buffer); dir->buffer = NULL; } return attr; } /* Tell if the directory has reached EOF (End Of File). */ int sftp_dir_eof(sftp_dir dir) { return dir->eof; } /* Free a SFTP_ATTRIBUTE handle */ void sftp_attributes_free(sftp_attributes file){ if (file == NULL) { return; } SSH_STRING_FREE(file->acl); SSH_STRING_FREE(file->extended_data); SSH_STRING_FREE(file->extended_type); SAFE_FREE(file->name); SAFE_FREE(file->longname); SAFE_FREE(file->group); SAFE_FREE(file->owner); SAFE_FREE(file); } static int sftp_handle_close(sftp_session sftp, ssh_string handle) { sftp_status_message status; sftp_message msg = NULL; ssh_buffer buffer = NULL; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dS", id, handle); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = sftp_packet_write(sftp, SSH_FXP_CLOSE, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return -1; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { /* something nasty has happened */ return -1; } msg = sftp_dequeue(sftp,id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if(status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; break; default: break; } ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; default: ssh_set_error(sftp->session, SSH_FATAL, "Received message %d during sftp_handle_close!", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* Close an open file handle. */ int sftp_close(sftp_file file){ int err = SSH_NO_ERROR; SAFE_FREE(file->name); if (file->handle){ err = sftp_handle_close(file->sftp,file->handle); SSH_STRING_FREE(file->handle); } /* FIXME: check server response and implement errno */ SAFE_FREE(file); return err; } /* Close an open directory. */ int sftp_closedir(sftp_dir dir){ int err = SSH_NO_ERROR; SAFE_FREE(dir->name); if (dir->handle) { err = sftp_handle_close(dir->sftp, dir->handle); SSH_STRING_FREE(dir->handle); } /* FIXME: check server response and implement errno */ SSH_BUFFER_FREE(dir->buffer); SAFE_FREE(dir); return err; } /* Open a file on the server. */ sftp_file sftp_open(sftp_session sftp, const char *file, int flags, mode_t mode) { sftp_message msg = NULL; sftp_status_message status; struct sftp_attributes_struct attr; sftp_file handle; ssh_buffer buffer; sftp_attributes stat_data; uint32_t sftp_flags = 0; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); return NULL; } ZERO_STRUCT(attr); attr.permissions = mode; attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; if ((flags & O_RDWR) == O_RDWR) { sftp_flags |= (SSH_FXF_WRITE | SSH_FXF_READ); } else if ((flags & O_WRONLY) == O_WRONLY) { sftp_flags |= SSH_FXF_WRITE; } else { sftp_flags |= SSH_FXF_READ; } if ((flags & O_CREAT) == O_CREAT) sftp_flags |= SSH_FXF_CREAT; if ((flags & O_TRUNC) == O_TRUNC) sftp_flags |= SSH_FXF_TRUNC; if ((flags & O_EXCL) == O_EXCL) sftp_flags |= SSH_FXF_EXCL; if ((flags & O_APPEND) == O_APPEND) { sftp_flags |= SSH_FXF_APPEND; } SSH_LOG(SSH_LOG_PACKET,"Opening file %s with sftp flags %x",file,sftp_flags); id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dsd", id, file, sftp_flags); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = buffer_add_attributes(buffer, &attr); if (rc < 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_OPEN, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { /* something nasty has happened */ return NULL; } msg = sftp_dequeue(sftp, id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return NULL; case SSH_FXP_HANDLE: handle = parse_handle_msg(msg); if (handle == NULL) { return NULL; } sftp_message_free(msg); if ((flags & O_APPEND) == O_APPEND) { stat_data = sftp_stat(sftp, file); if (stat_data == NULL) { sftp_close(handle); return NULL; } if ((stat_data->flags & SSH_FILEXFER_ATTR_SIZE) != SSH_FILEXFER_ATTR_SIZE) { ssh_set_error(sftp->session, SSH_FATAL, "Cannot open in append mode. Unknown file size."); sftp_close(handle); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } handle->offset = stat_data->size; } return handle; default: ssh_set_error(sftp->session, SSH_FATAL, "Received message %d during open!", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return NULL; } void sftp_file_set_nonblocking(sftp_file handle){ handle->nonblocking=1; } void sftp_file_set_blocking(sftp_file handle){ handle->nonblocking=0; } /* Read from a file using an opened sftp file handle. */ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) { sftp_session sftp = handle->sftp; sftp_message msg = NULL; sftp_status_message status; ssh_string datastring; size_t datalen; ssh_buffer buffer; uint32_t id; int rc; if (handle->eof) { return 0; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); return -1; } id = sftp_get_new_id(handle->sftp); rc = ssh_buffer_pack(buffer, "dSqd", id, handle->handle, handle->offset, count); if (rc != SSH_OK){ ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(handle->sftp, SSH_FXP_READ, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); while (msg == NULL) { if (handle->nonblocking) { if (ssh_channel_poll(handle->sftp->channel, 0) == 0) { /* we cannot block */ return 0; } } if (sftp_read_and_dispatch(handle->sftp) < 0) { /* something nasty has happened */ return -1; } msg = sftp_dequeue(handle->sftp, id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_EOF: handle->eof = 1; status_msg_free(status); return 0; default: break; } ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; case SSH_FXP_DATA: datastring = ssh_buffer_get_ssh_string(msg->payload); sftp_message_free(msg); if (datastring == NULL) { ssh_set_error(sftp->session, SSH_FATAL, "Received invalid DATA packet from sftp server"); return -1; } datalen = ssh_string_len(datastring); if (datalen > count) { ssh_set_error(sftp->session, SSH_FATAL, "Received a too big DATA packet from sftp server: " "%" PRIdS " and asked for %" PRIdS, datalen, count); SSH_STRING_FREE(datastring); return -1; } handle->offset += (uint64_t)datalen; memcpy(buf, ssh_string_data(datastring), datalen); SSH_STRING_FREE(datastring); return datalen; default: ssh_set_error(sftp->session, SSH_FATAL, "Received message %d during read!", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); return -1; } return -1; /* not reached */ } /* Start an asynchronous read from a file using an opened sftp file handle. */ int sftp_async_read_begin(sftp_file file, uint32_t len){ sftp_session sftp = file->sftp; ssh_buffer buffer; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dSqd", id, file->handle, file->offset, len); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(sftp, SSH_FXP_READ, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); file->offset += len; /* assume we'll read len bytes */ return id; } /* Wait for an asynchronous read to complete and save the data. */ int sftp_async_read(sftp_file file, void *data, uint32_t size, uint32_t id){ sftp_session sftp; sftp_message msg = NULL; sftp_status_message status; ssh_string datastring; int err = SSH_OK; uint32_t len; if (file == NULL) { return SSH_ERROR; } sftp = file->sftp; if (file->eof) { return 0; } /* handle an existing request */ while (msg == NULL) { if (file->nonblocking){ if (ssh_channel_poll(sftp->channel, 0) == 0) { /* we cannot block */ return SSH_AGAIN; } } if (sftp_read_and_dispatch(sftp) < 0) { /* something nasty has happened */ return SSH_ERROR; } msg = sftp_dequeue(sftp,id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); if (status->status != SSH_FX_EOF) { ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server : %s", status->errormsg); err = SSH_ERROR; } else { file->eof = 1; } status_msg_free(status); return err; case SSH_FXP_DATA: datastring = ssh_buffer_get_ssh_string(msg->payload); sftp_message_free(msg); if (datastring == NULL) { ssh_set_error(sftp->session, SSH_FATAL, "Received invalid DATA packet from sftp server"); return SSH_ERROR; } if (ssh_string_len(datastring) > size) { ssh_set_error(sftp->session, SSH_FATAL, "Received a too big DATA packet from sftp server: " "%" PRIdS " and asked for %u", ssh_string_len(datastring), size); SSH_STRING_FREE(datastring); return SSH_ERROR; } len = ssh_string_len(datastring); /* Update the offset with the correct value */ file->offset = file->offset - (size - len); memcpy(data, ssh_string_data(datastring), len); SSH_STRING_FREE(datastring); return len; default: ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during read!",msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); return SSH_ERROR; } return SSH_ERROR; } ssize_t sftp_write(sftp_file file, const void *buf, size_t count) { sftp_session sftp = file->sftp; sftp_message msg = NULL; sftp_status_message status; ssh_buffer buffer; uint32_t id; ssize_t len; size_t packetlen; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(file->sftp); rc = ssh_buffer_pack(buffer, "dSqdP", id, file->handle, file->offset, count, /* len of datastring */ (size_t)count, buf); if (rc != SSH_OK){ ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } packetlen=ssh_buffer_get_len(buffer); len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer); SSH_BUFFER_FREE(buffer); if (len < 0) { return -1; } else if ((size_t)len != packetlen) { SSH_LOG(SSH_LOG_PACKET, "Could not write as much data as expected"); } while (msg == NULL) { if (sftp_read_and_dispatch(file->sftp) < 0) { /* something nasty has happened */ return -1; } msg = sftp_dequeue(file->sftp, id); } switch (msg->packet_type) { case SSH_FXP_STATUS: status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: file->offset += count; status_msg_free(status); return count; default: break; } ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); file->offset += count; status_msg_free(status); return -1; default: ssh_set_error(sftp->session, SSH_FATAL, "Received message %d during write!", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); return -1; } return -1; /* not reached */ } /* Seek to a specific location in a file. */ int sftp_seek(sftp_file file, uint32_t new_offset) { if (file == NULL) { return -1; } file->offset = new_offset; file->eof = 0; return 0; } int sftp_seek64(sftp_file file, uint64_t new_offset) { if (file == NULL) { return -1; } file->offset = new_offset; file->eof = 0; return 0; } /* Report current byte position in file. */ unsigned long sftp_tell(sftp_file file) { return (unsigned long)file->offset; } /* Report current byte position in file. */ uint64_t sftp_tell64(sftp_file file) { return (uint64_t) file->offset; } /* Rewinds the position of the file pointer to the beginning of the file.*/ void sftp_rewind(sftp_file file) { file->offset = 0; file->eof = 0; } /* code written by Nick */ int sftp_unlink(sftp_session sftp, const char *file) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, file); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(sftp, SSH_FXP_REMOVE, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); while (msg == NULL) { if (sftp_read_and_dispatch(sftp)) { return -1; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_STATUS) { /* by specification, this command's only supposed to return SSH_FXP_STATUS */ status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; default: break; } /* * The status should be SSH_FX_OK if the command was successful, if it * didn't, then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session,SSH_FATAL, "Received message %d when attempting to remove file", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* code written by Nick */ int sftp_rmdir(sftp_session sftp, const char *directory) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, directory); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(sftp, SSH_FXP_RMDIR, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return -1; } msg = sftp_dequeue(sftp, id); } /* By specification, this command returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; default: break; } ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to remove directory", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* Code written by Nick */ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode) { sftp_status_message status = NULL; sftp_message msg = NULL; sftp_attributes errno_attr = NULL; struct sftp_attributes_struct attr; ssh_buffer buffer; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } ZERO_STRUCT(attr); attr.permissions = mode; attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, directory); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = buffer_add_attributes(buffer, &attr); if (rc < 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = sftp_packet_write(sftp, SSH_FXP_MKDIR, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return -1; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return -1; } msg = sftp_dequeue(sftp, id); } /* By specification, this command only returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_FAILURE: /* * mkdir always returns a failure, even if the path already exists. * To be POSIX conform and to be able to map it to EEXIST a stat * call is needed here. */ errno_attr = sftp_lstat(sftp, directory); if (errno_attr != NULL) { SAFE_FREE(errno_attr); sftp_set_error(sftp, SSH_FX_FILE_ALREADY_EXISTS); } break; case SSH_FX_OK: status_msg_free(status); return 0; default: break; } /* * The status should be SSH_FX_OK if the command was successful, if it * didn't, then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to make directory", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* code written by nick */ int sftp_rename(sftp_session sftp, const char *original, const char *newname) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dss", id, original, newname); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp->version >= 4){ /* POSIX rename atomically replaces newpath, we should do the same * only available on >=v4 */ ssh_buffer_add_u32(buffer, SSH_FXF_RENAME_OVERWRITE); } if (sftp_packet_write(sftp, SSH_FXP_RENAME, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return -1; } msg = sftp_dequeue(sftp, id); } /* By specification, this command only returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; default: break; } /* * Status should be SSH_FX_OK if the command was successful, if it didn't, * then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to rename", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* Code written by Nick */ /* Set file attributes on a file, directory or symbolic link. */ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr) { uint32_t id; ssh_buffer buffer; sftp_message msg = NULL; sftp_status_message status = NULL; int rc; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, file); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = buffer_add_attributes(buffer, attr); if (rc != 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } rc = sftp_packet_write(sftp, SSH_FXP_SETSTAT, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return -1; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return -1; } msg = sftp_dequeue(sftp, id); } /* By specification, this command only returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; default: break; } /* * The status should be SSH_FX_OK if the command was successful, if it * didn't, then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } /* Change the file owner and group */ int sftp_chown(sftp_session sftp, const char *file, uid_t owner, gid_t group) { struct sftp_attributes_struct attr; ZERO_STRUCT(attr); attr.uid = owner; attr.gid = group; attr.flags = SSH_FILEXFER_ATTR_UIDGID; return sftp_setstat(sftp, file, &attr); } /* Change permissions of a file */ int sftp_chmod(sftp_session sftp, const char *file, mode_t mode) { struct sftp_attributes_struct attr; ZERO_STRUCT(attr); attr.permissions = mode; attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS; return sftp_setstat(sftp, file, &attr); } /* Change the last modification and access time of a file. */ int sftp_utimes(sftp_session sftp, const char *file, const struct timeval *times) { struct sftp_attributes_struct attr; ZERO_STRUCT(attr); attr.atime = times[0].tv_sec; attr.atime_nseconds = times[0].tv_usec; attr.mtime = times[1].tv_sec; attr.mtime_nseconds = times[1].tv_usec; attr.flags |= SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME | SSH_FILEXFER_ATTR_SUBSECOND_TIMES; return sftp_setstat(sftp, file, &attr); } int sftp_symlink(sftp_session sftp, const char *target, const char *dest) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (sftp == NULL) return -1; if (target == NULL || dest == NULL) { ssh_set_error_invalid(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); /* TODO check for version number if they ever fix it. */ if (ssh_get_openssh_version(sftp->session)) { rc = ssh_buffer_pack(buffer, "dss", id, target, dest); } else { rc = ssh_buffer_pack(buffer, "dss", id, dest, target); } if (rc != SSH_OK){ ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) { SSH_BUFFER_FREE(buffer); return -1; } SSH_BUFFER_FREE(buffer); while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return -1; } msg = sftp_dequeue(sftp, id); } /* By specification, this command only returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return -1; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: status_msg_free(status); return 0; default: break; } /* * The status should be SSH_FX_OK if the command was successful, if it * didn't, then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return -1; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return -1; } char *sftp_readlink(sftp_session sftp, const char *path) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (sftp == NULL) { return NULL; } if (path == NULL) { ssh_set_error_invalid(sftp); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } if (sftp->version < 3){ ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_readlink",sftp->version); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, path); if (rc < 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_READLINK, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return NULL; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_NAME) { uint32_t ignored = 0; char *lnk = NULL; rc = ssh_buffer_unpack(msg->payload, "ds", &ignored, &lnk); sftp_message_free(msg); if (rc != SSH_OK) { ssh_set_error(sftp->session, SSH_ERROR, "Failed to retrieve link"); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } return lnk; } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); } else { /* this shouldn't happen */ ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return NULL; } static sftp_statvfs_t sftp_parse_statvfs(sftp_session sftp, ssh_buffer buf) { sftp_statvfs_t statvfs; int rc; statvfs = calloc(1, sizeof(struct sftp_statvfs_struct)); if (statvfs == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = ssh_buffer_unpack(buf, "qqqqqqqqqqq", &statvfs->f_bsize, /* file system block size */ &statvfs->f_frsize, /* fundamental fs block size */ &statvfs->f_blocks, /* number of blocks (unit f_frsize) */ &statvfs->f_bfree, /* free blocks in file system */ &statvfs->f_bavail, /* free blocks for non-root */ &statvfs->f_files, /* total file inodes */ &statvfs->f_ffree, /* free file inodes */ &statvfs->f_favail, /* free file inodes for to non-root */ &statvfs->f_fsid, /* file system id */ &statvfs->f_flag, /* bit mask of f_flag values */ &statvfs->f_namemax/* maximum filename length */ ); if (rc != SSH_OK) { SAFE_FREE(statvfs); ssh_set_error(sftp->session, SSH_FATAL, "Invalid statvfs structure"); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } return statvfs; } sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (sftp == NULL) return NULL; if (path == NULL) { ssh_set_error_invalid(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } if (sftp->version < 3){ ssh_set_error(sftp,SSH_REQUEST_DENIED,"sftp version %d does not support sftp_statvfs",sftp->version); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dss", id, "statvfs@openssh.com", path); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return NULL; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) { sftp_statvfs_t buf = sftp_parse_statvfs(sftp, msg->payload); sftp_message_free(msg); if (buf == NULL) { return NULL; } return buf; } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); } else { /* this shouldn't happen */ ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to get statvfs", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return NULL; } int sftp_fsync(sftp_file file) { sftp_session sftp; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (file == NULL) { return -1; } sftp = file->sftp; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return -1; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dsS", id, "fsync@openssh.com", file->handle); if (rc < 0) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); goto done; } rc = sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer); if (rc < 0) { ssh_set_error_oom(sftp->session); goto done; } do { rc = sftp_read_and_dispatch(sftp); if (rc < 0) { ssh_set_error_oom(sftp->session); rc = -1; goto done; } msg = sftp_dequeue(sftp, id); } while (msg == NULL); /* By specification, this command only returns SSH_FXP_STATUS */ if (msg->packet_type == SSH_FXP_STATUS) { sftp_status_message status; status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { rc = -1; goto done; } sftp_set_error(sftp, status->status); switch (status->status) { case SSH_FX_OK: /* SUCCESS, LEAVE */ status_msg_free(status); rc = 0; goto done; default: break; } /* * The status should be SSH_FX_OK if the command was successful, if it * didn't, then there was an error */ ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); rc = -1; goto done; } else { ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } rc = -1; done: SSH_BUFFER_FREE(buffer); return rc; } sftp_statvfs_t sftp_fstatvfs(sftp_file file) { sftp_status_message status = NULL; sftp_message msg = NULL; sftp_session sftp; ssh_buffer buffer; uint32_t id; int rc; if (file == NULL) { return NULL; } sftp = file->sftp; buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "dsS", id, "fstatvfs@openssh.com", file->handle); if (rc < 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return NULL; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) { sftp_statvfs_t buf = sftp_parse_statvfs(sftp, msg->payload); sftp_message_free(msg); if (buf == NULL) { return NULL; } return buf; } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); } else { /* this shouldn't happen */ ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return NULL; } void sftp_statvfs_free(sftp_statvfs_t statvfs) { if (statvfs == NULL) { return; } SAFE_FREE(statvfs); } /* another code written by Nick */ char *sftp_canonicalize_path(sftp_session sftp, const char *path) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (sftp == NULL) return NULL; if (path == NULL) { ssh_set_error_invalid(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, path); if (rc < 0) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, SSH_FXP_REALPATH, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return NULL; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_NAME) { uint32_t ignored = 0; char *cname = NULL; rc = ssh_buffer_unpack(msg->payload, "ds", &ignored, &cname); sftp_message_free(msg); if (rc != SSH_OK) { ssh_set_error(sftp->session, SSH_ERROR, "Failed to parse canonicalized path"); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } return cname; } else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */ status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); } else { /* this shouldn't happen */ ssh_set_error(sftp->session, SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); } return NULL; } static sftp_attributes sftp_xstat(sftp_session sftp, const char *path, int param) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (sftp == NULL) { return NULL; } if (path == NULL) { ssh_set_error_invalid(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(sftp->session); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(sftp); rc = ssh_buffer_pack(buffer, "ds", id, path); if (rc != SSH_OK) { ssh_set_error_oom(sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(sftp, param, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(sftp) < 0) { return NULL; } msg = sftp_dequeue(sftp, id); } if (msg->packet_type == SSH_FXP_ATTRS) { sftp_attributes attr = sftp_parse_attr(sftp, msg->payload, 0); sftp_message_free(msg); return attr; } else if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(sftp, status->status); ssh_set_error(sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return NULL; } ssh_set_error(sftp->session, SSH_FATAL, "Received mesg %d during stat()", msg->packet_type); sftp_message_free(msg); sftp_set_error(sftp, SSH_FX_BAD_MESSAGE); return NULL; } sftp_attributes sftp_stat(sftp_session session, const char *path) { return sftp_xstat(session, path, SSH_FXP_STAT); } sftp_attributes sftp_lstat(sftp_session session, const char *path) { return sftp_xstat(session, path, SSH_FXP_LSTAT); } sftp_attributes sftp_fstat(sftp_file file) { sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; uint32_t id; int rc; if (file == NULL) { return NULL; } buffer = ssh_buffer_new(); if (buffer == NULL) { ssh_set_error_oom(file->sftp->session); sftp_set_error(file->sftp, SSH_FX_FAILURE); return NULL; } id = sftp_get_new_id(file->sftp); rc = ssh_buffer_pack(buffer, "dS", id, file->handle); if (rc != SSH_OK) { ssh_set_error_oom(file->sftp->session); SSH_BUFFER_FREE(buffer); sftp_set_error(file->sftp, SSH_FX_FAILURE); return NULL; } rc = sftp_packet_write(file->sftp, SSH_FXP_FSTAT, buffer); SSH_BUFFER_FREE(buffer); if (rc < 0) { return NULL; } while (msg == NULL) { if (sftp_read_and_dispatch(file->sftp) < 0) { return NULL; } msg = sftp_dequeue(file->sftp, id); } if (msg->packet_type == SSH_FXP_ATTRS){ sftp_attributes attr = sftp_parse_attr(file->sftp, msg->payload, 0); sftp_message_free(msg); return attr; } else if (msg->packet_type == SSH_FXP_STATUS) { status = parse_status_msg(msg); sftp_message_free(msg); if (status == NULL) { return NULL; } sftp_set_error(file->sftp, status->status); ssh_set_error(file->sftp->session, SSH_REQUEST_DENIED, "SFTP server: %s", status->errormsg); status_msg_free(status); return NULL; } ssh_set_error(file->sftp->session, SSH_FATAL, "Received msg %d during fstat()", msg->packet_type); sftp_message_free(msg); sftp_set_error(file->sftp, SSH_FX_BAD_MESSAGE); return NULL; } #endif /* WITH_SFTP */ ================================================ FILE: src/libssh/src/sftpserver.c ================================================ /* * sftpserver.c - server based function for the sftp protocol * * This file is part of the SSH Library * * Copyright (c) 2005 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #ifndef _WIN32 #include #include #endif #include "libssh/libssh.h" #include "libssh/sftp.h" #include "libssh/sftp_priv.h" #include "libssh/ssh2.h" #include "libssh/priv.h" #include "libssh/buffer.h" #include "libssh/misc.h" #define SFTP_HANDLES 256 sftp_client_message sftp_get_client_message(sftp_session sftp) { ssh_session session = sftp->session; sftp_packet packet; sftp_client_message msg; ssh_buffer payload; int rc; msg = malloc(sizeof (struct sftp_client_message_struct)); if (msg == NULL) { ssh_set_error_oom(session); return NULL; } ZERO_STRUCTP(msg); packet = sftp_packet_read(sftp); if (packet == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } payload = packet->payload; msg->type = packet->type; msg->sftp = sftp; /* take a copy of the whole packet */ msg->complete_message = ssh_buffer_new(); if (msg->complete_message == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } rc = ssh_buffer_add_data(msg->complete_message, ssh_buffer_get(payload), ssh_buffer_get_len(payload)); if (rc < 0) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } ssh_buffer_get_u32(payload, &msg->id); switch(msg->type) { case SSH_FXP_CLOSE: case SSH_FXP_READDIR: msg->handle = ssh_buffer_get_ssh_string(payload); if (msg->handle == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_READ: rc = ssh_buffer_unpack(payload, "Sqd", &msg->handle, &msg->offset, &msg->len); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_WRITE: rc = ssh_buffer_unpack(payload, "SqS", &msg->handle, &msg->offset, &msg->data); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_REMOVE: case SSH_FXP_RMDIR: case SSH_FXP_OPENDIR: case SSH_FXP_READLINK: case SSH_FXP_REALPATH: rc = ssh_buffer_unpack(payload, "s", &msg->filename); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_RENAME: case SSH_FXP_SYMLINK: rc = ssh_buffer_unpack(payload, "sS", &msg->filename, &msg->data); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_MKDIR: case SSH_FXP_SETSTAT: rc = ssh_buffer_unpack(payload, "s", &msg->filename); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } msg->attr = sftp_parse_attr(sftp, payload, 0); if (msg->attr == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_FSETSTAT: msg->handle = ssh_buffer_get_ssh_string(payload); if (msg->handle == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } msg->attr = sftp_parse_attr(sftp, payload, 0); if (msg->attr == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_LSTAT: case SSH_FXP_STAT: rc = ssh_buffer_unpack(payload, "s", &msg->filename); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } if(sftp->version > 3) { ssh_buffer_unpack(payload, "d", &msg->flags); } break; case SSH_FXP_OPEN: rc = ssh_buffer_unpack(payload, "sd", &msg->filename, &msg->flags); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } msg->attr = sftp_parse_attr(sftp, payload, 0); if (msg->attr == NULL) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_FSTAT: rc = ssh_buffer_unpack(payload, "S", &msg->handle); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } break; case SSH_FXP_EXTENDED: rc = ssh_buffer_unpack(payload, "s", &msg->submessage); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } if (strcmp(msg->submessage, "hardlink@openssh.com") == 0 || strcmp(msg->submessage, "posix-rename@openssh.com") == 0) { rc = ssh_buffer_unpack(payload, "sS", &msg->filename, &msg->data); if (rc != SSH_OK) { ssh_set_error_oom(session); sftp_client_message_free(msg); return NULL; } } break; default: ssh_set_error(sftp->session, SSH_FATAL, "Received unhandled sftp message %d", msg->type); sftp_client_message_free(msg); return NULL; } return msg; } /* Send an sftp client message. Can be used in cas of proxying */ int sftp_send_client_message(sftp_session sftp, sftp_client_message msg){ return sftp_packet_write(sftp, msg->type, msg->complete_message); } uint8_t sftp_client_message_get_type(sftp_client_message msg){ return msg->type; } const char *sftp_client_message_get_filename(sftp_client_message msg){ return msg->filename; } void sftp_client_message_set_filename(sftp_client_message msg, const char *newname){ free(msg->filename); msg->filename = strdup(newname); } const char *sftp_client_message_get_data(sftp_client_message msg){ if (msg->str_data == NULL) msg->str_data = ssh_string_to_char(msg->data); return msg->str_data; } uint32_t sftp_client_message_get_flags(sftp_client_message msg){ return msg->flags; } const char *sftp_client_message_get_submessage(sftp_client_message msg){ return msg->submessage; } void sftp_client_message_free(sftp_client_message msg) { if (msg == NULL) { return; } SAFE_FREE(msg->filename); SAFE_FREE(msg->submessage); SSH_STRING_FREE(msg->data); SSH_STRING_FREE(msg->handle); sftp_attributes_free(msg->attr); SSH_BUFFER_FREE(msg->complete_message); SAFE_FREE(msg->str_data); ZERO_STRUCTP(msg); SAFE_FREE(msg); } int sftp_reply_name(sftp_client_message msg, const char *name, sftp_attributes attr) { ssh_buffer out; ssh_string file; out = ssh_buffer_new(); if (out == NULL) { return -1; } file = ssh_string_from_char(name); if (file == NULL) { SSH_BUFFER_FREE(out); return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, htonl(1)) < 0 || ssh_buffer_add_ssh_string(out, file) < 0 || ssh_buffer_add_ssh_string(out, file) < 0 || /* The protocol is broken here between 3 & 4 */ buffer_add_attributes(out, attr) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_NAME, out) < 0) { SSH_BUFFER_FREE(out); SSH_STRING_FREE(file); return -1; } SSH_BUFFER_FREE(out); SSH_STRING_FREE(file); return 0; } int sftp_reply_handle(sftp_client_message msg, ssh_string handle){ ssh_buffer out; out = ssh_buffer_new(); if (out == NULL) { return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_ssh_string(out, handle) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_HANDLE, out) < 0) { SSH_BUFFER_FREE(out); return -1; } SSH_BUFFER_FREE(out); return 0; } int sftp_reply_attr(sftp_client_message msg, sftp_attributes attr) { ssh_buffer out; out = ssh_buffer_new(); if (out == NULL) { return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || buffer_add_attributes(out, attr) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_ATTRS, out) < 0) { SSH_BUFFER_FREE(out); return -1; } SSH_BUFFER_FREE(out); return 0; } int sftp_reply_names_add(sftp_client_message msg, const char *file, const char *longname, sftp_attributes attr) { ssh_string name; name = ssh_string_from_char(file); if (name == NULL) { return -1; } if (msg->attrbuf == NULL) { msg->attrbuf = ssh_buffer_new(); if (msg->attrbuf == NULL) { SSH_STRING_FREE(name); return -1; } } if (ssh_buffer_add_ssh_string(msg->attrbuf, name) < 0) { SSH_STRING_FREE(name); return -1; } SSH_STRING_FREE(name); name = ssh_string_from_char(longname); if (name == NULL) { return -1; } if (ssh_buffer_add_ssh_string(msg->attrbuf,name) < 0 || buffer_add_attributes(msg->attrbuf,attr) < 0) { SSH_STRING_FREE(name); return -1; } SSH_STRING_FREE(name); msg->attr_num++; return 0; } int sftp_reply_names(sftp_client_message msg) { ssh_buffer out; out = ssh_buffer_new(); if (out == NULL) { SSH_BUFFER_FREE(msg->attrbuf); return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, htonl(msg->attr_num)) < 0 || ssh_buffer_add_data(out, ssh_buffer_get(msg->attrbuf), ssh_buffer_get_len(msg->attrbuf)) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_NAME, out) < 0) { SSH_BUFFER_FREE(out); SSH_BUFFER_FREE(msg->attrbuf); return -1; } SSH_BUFFER_FREE(out); SSH_BUFFER_FREE(msg->attrbuf); msg->attr_num = 0; msg->attrbuf = NULL; return 0; } int sftp_reply_status(sftp_client_message msg, uint32_t status, const char *message) { ssh_buffer out; ssh_string s; out = ssh_buffer_new(); if (out == NULL) { return -1; } s = ssh_string_from_char(message ? message : ""); if (s == NULL) { SSH_BUFFER_FREE(out); return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, htonl(status)) < 0 || ssh_buffer_add_ssh_string(out, s) < 0 || ssh_buffer_add_u32(out, 0) < 0 || /* language string */ sftp_packet_write(msg->sftp, SSH_FXP_STATUS, out) < 0) { SSH_BUFFER_FREE(out); SSH_STRING_FREE(s); return -1; } SSH_BUFFER_FREE(out); SSH_STRING_FREE(s); return 0; } int sftp_reply_data(sftp_client_message msg, const void *data, int len) { ssh_buffer out; out = ssh_buffer_new(); if (out == NULL) { return -1; } if (ssh_buffer_add_u32(out, msg->id) < 0 || ssh_buffer_add_u32(out, ntohl(len)) < 0 || ssh_buffer_add_data(out, data, len) < 0 || sftp_packet_write(msg->sftp, SSH_FXP_DATA, out) < 0) { SSH_BUFFER_FREE(out); return -1; } SSH_BUFFER_FREE(out); return 0; } /* * This function will return you a new handle to give the client. * the function accepts an info that can be retrieved later with * the handle. Care is given that a corrupted handle won't give a * valid info (or worse). */ ssh_string sftp_handle_alloc(sftp_session sftp, void *info) { ssh_string ret; uint32_t val; uint32_t i; if (sftp->handles == NULL) { sftp->handles = calloc(SFTP_HANDLES, sizeof(void *)); if (sftp->handles == NULL) { return NULL; } } for (i = 0; i < SFTP_HANDLES; i++) { if (sftp->handles[i] == NULL) { break; } } if (i == SFTP_HANDLES) { return NULL; /* no handle available */ } val = i; ret = ssh_string_new(4); if (ret == NULL) { return NULL; } memcpy(ssh_string_data(ret), &val, sizeof(uint32_t)); sftp->handles[i] = info; return ret; } void *sftp_handle(sftp_session sftp, ssh_string handle){ uint32_t val; if (sftp->handles == NULL) { return NULL; } if (ssh_string_len(handle) != sizeof(uint32_t)) { return NULL; } memcpy(&val, ssh_string_data(handle), sizeof(uint32_t)); if (val > SFTP_HANDLES) { return NULL; } return sftp->handles[val]; } void sftp_handle_remove(sftp_session sftp, void *handle) { int i; for (i = 0; i < SFTP_HANDLES; i++) { if (sftp->handles[i] == handle) { sftp->handles[i] = NULL; break; } } } ================================================ FILE: src/libssh/src/socket.c ================================================ /* * socket.c - socket functions for the library * * This file is part of the SSH Library * * Copyright (c) 2008-2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #ifdef _WIN32 #include #include #if _MSC_VER >= 1400 #include #undef open #define open _open #undef close #define close _close #undef read #define read _read #undef write #define write _write #endif /* _MSC_VER */ #else /* _WIN32 */ #include #include #include #include #include #include #endif /* _WIN32 */ #include "libssh/priv.h" #include "libssh/callbacks.h" #include "libssh/socket.h" #include "libssh/buffer.h" #include "libssh/poll.h" #include "libssh/session.h" /** * @internal * * @defgroup libssh_socket The SSH socket functions. * @ingroup libssh * * Functions for handling sockets. * * @{ */ enum ssh_socket_states_e { SSH_SOCKET_NONE, SSH_SOCKET_CONNECTING, SSH_SOCKET_CONNECTED, SSH_SOCKET_EOF, SSH_SOCKET_ERROR, SSH_SOCKET_CLOSED }; struct ssh_socket_struct { socket_t fd; int fd_is_socket; int last_errno; int read_wontblock; /* reading now on socket will not block */ int write_wontblock; int data_except; enum ssh_socket_states_e state; ssh_buffer out_buffer; ssh_buffer in_buffer; ssh_session session; ssh_socket_callbacks callbacks; ssh_socket_external_callbacks external_callbacks; ssh_poll_handle poll_handle; #ifndef _WIN32 pid_t proxy_pid; #endif }; static int sockets_initialized = 0; static ssize_t ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len); static ssize_t ssh_socket_unbuffered_write(ssh_socket s, const void *buffer, uint32_t len); /** * \internal * \brief inits the socket system (windows specific) */ int ssh_socket_init(void) { if (sockets_initialized == 0) { #ifdef _WIN32 struct WSAData wsaData; /* Initiates use of the Winsock DLL by a process. */ if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { return -1; } #endif ssh_poll_init(); sockets_initialized = 1; } return 0; } /** * @brief Cleanup the socket system. */ void ssh_socket_cleanup(void) { if (sockets_initialized == 1) { ssh_poll_cleanup(); #ifdef _WIN32 WSACleanup(); #endif sockets_initialized = 0; } } /** * \internal * \brief creates a new Socket object */ ssh_socket ssh_socket_new(ssh_session session) { ssh_socket s; s = calloc(1, sizeof(struct ssh_socket_struct)); if (s == NULL) { ssh_set_error_oom(session); return NULL; } s->fd = SSH_INVALID_SOCKET; s->last_errno = -1; s->fd_is_socket = 1; s->session = session; s->in_buffer = ssh_buffer_new(); if (s->in_buffer == NULL) { ssh_set_error_oom(session); SAFE_FREE(s); return NULL; } s->out_buffer=ssh_buffer_new(); if (s->out_buffer == NULL) { ssh_set_error_oom(session); SSH_BUFFER_FREE(s->in_buffer); SAFE_FREE(s); return NULL; } s->read_wontblock = 0; s->write_wontblock = 0; s->data_except = 0; s->poll_handle = NULL; s->state=SSH_SOCKET_NONE; return s; } /** * @internal * @brief Reset the state of a socket so it looks brand-new * @param[in] s socket to rest */ void ssh_socket_reset(ssh_socket s) { s->fd = SSH_INVALID_SOCKET; s->last_errno = -1; s->fd_is_socket = 1; ssh_buffer_reinit(s->in_buffer); ssh_buffer_reinit(s->out_buffer); s->read_wontblock = 0; s->write_wontblock = 0; s->data_except = 0; s->poll_handle = NULL; s->state=SSH_SOCKET_NONE; #ifndef _WIN32 s->proxy_pid = 0; #endif } /** * @internal * @brief the socket callbacks, i.e. callbacks to be called * upon a socket event. * @param s socket to set callbacks on. * @param callbacks a ssh_socket_callback object reference. */ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks) { s->callbacks = callbacks; } void ssh_socket_set_external_callbacks(ssh_socket s, ssh_socket_external_callbacks external_callbacks) { s->external_callbacks = external_callbacks; } /** * @brief SSH poll callback. This callback will be used when an event * caught on the socket. * * @param p Poll object this callback belongs to. * @param fd The raw socket. * @param revents The current poll events on the socket. * @param userdata Userdata to be passed to the callback function, * in this case the socket object. * * @return 0 on success, < 0 when the poll object has been removed * from its poll context. */ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s) { ssh_socket s = (ssh_socket)v_s; char buffer[MAX_BUF_SIZE]; ssize_t nread; int rc; int err = 0; socklen_t errlen = sizeof(err); /* Do not do anything if this socket was already closed */ if (!ssh_socket_is_open(s)) { return -1; } SSH_LOG(SSH_LOG_TRACE, "Poll callback on socket %d (%s%s%s), out buffer %d",fd, (revents & POLLIN) ? "POLLIN ":"", (revents & POLLOUT) ? "POLLOUT ":"", (revents & POLLERR) ? "POLLERR":"", ssh_buffer_get_len(s->out_buffer)); if ((revents & POLLERR) || (revents & POLLHUP)) { /* Check if we are in a connecting state */ if (s->state == SSH_SOCKET_CONNECTING) { s->state = SSH_SOCKET_ERROR; rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen); if (rc < 0) { err = errno; } ssh_socket_close(s); /* Overwrite ssh_socket_close() error with the real socket error */ s->last_errno = err; errno = err; if (s->callbacks != NULL && s->callbacks->connected != NULL) { s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR, err, s->callbacks->userdata); } return -1; } /* Then we are in a more standard kind of error */ /* force a read to get an explanation */ revents |= POLLIN; } if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) { s->read_wontblock = 1; nread = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer)); if (nread < 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks != NULL && s->callbacks->exception != NULL) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR, s->last_errno, s->callbacks->userdata); } return -2; } if (nread == 0) { if (p != NULL) { ssh_poll_remove_events(p, POLLIN); } if (s->callbacks != NULL && s->callbacks->exception != NULL) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF, 0, s->callbacks->userdata); } return -2; } if (s->session->socket_counter != NULL) { s->session->socket_counter->in_bytes += nread; } /* Bufferize the data and then call the callback */ rc = ssh_buffer_add_data(s->in_buffer, buffer, nread); if (rc < 0) { return -1; } if (s->callbacks != NULL && s->callbacks->data != NULL) { do { nread = s->callbacks->data(ssh_buffer_get(s->in_buffer), ssh_buffer_get_len(s->in_buffer), s->callbacks->userdata); ssh_buffer_pass_bytes(s->in_buffer, nread); } while ((nread > 0) && (s->state == SSH_SOCKET_CONNECTED)); /* p may have been freed, so don't use it * anymore in this function */ p = NULL; } } #ifdef _WIN32 if (revents & POLLOUT || revents & POLLWRNORM) { #else if (revents & POLLOUT) { #endif uint32_t len; /* First, POLLOUT is a sign we may be connected */ if (s->state == SSH_SOCKET_CONNECTING) { SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state"); s->state = SSH_SOCKET_CONNECTED; if (p != NULL) { ssh_poll_set_events(p, POLLOUT | POLLIN); } rc = ssh_socket_set_blocking(ssh_socket_get_fd(s)); if (rc < 0) { return -1; } if (s->callbacks != NULL && s->callbacks->connected != NULL) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0, s->callbacks->userdata); } return 0; } /* So, we can write data */ s->write_wontblock = 1; if (p != NULL) { ssh_poll_remove_events(p, POLLOUT); } /* If buffered data is pending, write it */ len = ssh_buffer_get_len(s->out_buffer); if (len > 0) { ssh_socket_nonblocking_flush(s); } else if (s->callbacks != NULL && s->callbacks->controlflow != NULL) { /* Otherwise advertise the upper level that write can be done */ SSH_LOG(SSH_LOG_TRACE,"sending control flow event"); s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK, s->callbacks->userdata); } /* TODO: Find a way to put back POLLOUT when buffering occurs */ } /* Return -1 if the poll handler disappeared */ if (s->poll_handle == NULL) { return -1; } return 0; } /** @internal * @brief returns the poll handle corresponding to the socket, * creates it if it does not exist. * @returns allocated and initialized ssh_poll_handle object */ ssh_poll_handle ssh_socket_get_poll_handle(ssh_socket s) { if (s->poll_handle) { return s->poll_handle; } s->poll_handle = ssh_poll_new(s->fd,0,ssh_socket_pollcallback,s); return s->poll_handle; } /** \internal * \brief Deletes a socket object */ void ssh_socket_free(ssh_socket s) { if (s == NULL) { return; } ssh_socket_close(s); SSH_BUFFER_FREE(s->in_buffer); SSH_BUFFER_FREE(s->out_buffer); SAFE_FREE(s); } #ifndef _WIN32 int ssh_socket_unix(ssh_socket s, const char *path) { struct sockaddr_un sunaddr; socket_t fd; sunaddr.sun_family = AF_UNIX; snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == SSH_INVALID_SOCKET) { ssh_set_error(s->session, SSH_FATAL, "Error from socket(AF_UNIX, SOCK_STREAM, 0): %s", strerror(errno)); return -1; } if (fcntl(fd, F_SETFD, 1) == -1) { ssh_set_error(s->session, SSH_FATAL, "Error from fcntl(fd, F_SETFD, 1): %s", strerror(errno)); close(fd); return -1; } if (connect(fd, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s", strerror(errno)); close(fd); return -1; } ssh_socket_set_fd(s,fd); return 0; } #endif /** \internal * \brief closes a socket */ void ssh_socket_close(ssh_socket s) { if (ssh_socket_is_open(s)) { #ifdef _WIN32 CLOSE_SOCKET(s->fd); s->last_errno = WSAGetLastError(); #else CLOSE_SOCKET(s->fd); s->last_errno = errno; #endif } if (s->poll_handle != NULL) { ssh_poll_free(s->poll_handle); s->poll_handle = NULL; } s->state = SSH_SOCKET_CLOSED; #ifndef _WIN32 /* If the proxy command still runs try to kill it */ if (s->proxy_pid != 0) { int status; pid_t pid = s->proxy_pid; s->proxy_pid = 0; kill(pid, SIGTERM); while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { SSH_LOG(SSH_LOG_WARN, "waitpid failed: %s", strerror(errno)); return; } } if (!WIFEXITED(status)) { SSH_LOG(SSH_LOG_WARN, "Proxy command exitted abnormally"); return; } SSH_LOG(SSH_LOG_TRACE, "Proxy command returned %d", WEXITSTATUS(status)); } #endif } /** * @internal * @brief sets the file descriptor of the socket. * @param[out] s ssh_socket to update * @param[in] fd file descriptor to set * @warning this function updates boths the input and output * file descriptors */ void ssh_socket_set_fd(ssh_socket s, socket_t fd) { s->fd = fd; if (s->poll_handle) { ssh_poll_set_fd(s->poll_handle,fd); } else { s->state = SSH_SOCKET_CONNECTING; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLOUT); #ifdef _WIN32 ssh_poll_add_events(ssh_socket_get_poll_handle(s), POLLWRNORM); #endif } } /** \internal * \brief returns the input file descriptor of the socket */ socket_t ssh_socket_get_fd(ssh_socket s) { return s->fd; } /** \internal * \brief returns nonzero if the socket is open */ int ssh_socket_is_open(ssh_socket s) { return s->fd != SSH_INVALID_SOCKET; } /** \internal * \brief read len bytes from socket into buffer */ static ssize_t ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len) { ssize_t rc = -1; if (s->data_except) { return -1; } if (s->fd_is_socket) { rc = recv(s->fd,buffer, len, 0); } else { rc = read(s->fd,buffer, len); } #ifdef _WIN32 s->last_errno = WSAGetLastError(); #else s->last_errno = errno; #endif s->read_wontblock = 0; if (rc < 0) { s->data_except = 1; } return rc; } /** \internal * \brief writes len bytes from buffer to socket */ static ssize_t ssh_socket_unbuffered_write(ssh_socket s, const void *buffer, uint32_t len) { ssize_t w = -1; int flags = 0; #ifdef MSG_NOSIGNAL flags |= MSG_NOSIGNAL; #endif if (s->data_except) { return -1; } if (s->fd_is_socket) { if (s->external_callbacks->send != NULL) { w = s->external_callbacks->send(buffer, len, s->external_callbacks->userdata); } else { w = send(s->fd, buffer, len, flags); } } else { w = write(s->fd, buffer, len); } #ifdef _WIN32 s->last_errno = WSAGetLastError(); #else s->last_errno = errno; #endif s->write_wontblock = 0; /* Reactive the POLLOUT detector in the poll multiplexer system */ if (s->poll_handle) { SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket"); ssh_poll_set_events(s->poll_handle,ssh_poll_get_events(s->poll_handle) | POLLOUT); } if (w < 0) { s->data_except = 1; } return w; } /** \internal * \brief returns nonzero if the current socket is in the fd_set */ int ssh_socket_fd_isset(ssh_socket s, fd_set *set) { if(s->fd == SSH_INVALID_SOCKET) { return 0; } return FD_ISSET(s->fd,set); } /** \internal * \brief sets the current fd in a fd_set and updates the max_fd */ void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd) { if (s->fd == SSH_INVALID_SOCKET) { return; } FD_SET(s->fd,set); if (s->fd >= 0 && s->fd >= *max_fd && s->fd != SSH_INVALID_SOCKET) { *max_fd = s->fd + 1; } } /** \internal * \brief buffered write of data * \returns SSH_OK, or SSH_ERROR * \warning has no effect on socket before a flush */ int ssh_socket_write(ssh_socket s, const void *buffer, int len) { if (len > 0) { if (ssh_buffer_add_data(s->out_buffer, buffer, len) < 0) { ssh_set_error_oom(s->session); return SSH_ERROR; } ssh_socket_nonblocking_flush(s); } return SSH_OK; } /** \internal * \brief starts a nonblocking flush of the output buffer * */ int ssh_socket_nonblocking_flush(ssh_socket s) { ssh_session session = s->session; uint32_t len; if (!ssh_socket_is_open(s)) { session->alive = 0; if (s->callbacks && s->callbacks->exception) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR, s->last_errno, s->callbacks->userdata); } else { ssh_set_error(session, SSH_FATAL, "Writing packet: error on socket (or connection " "closed): %s", strerror(s->last_errno)); } return SSH_ERROR; } len = ssh_buffer_get_len(s->out_buffer); if (!s->write_wontblock && s->poll_handle && len > 0) { /* force the poll system to catch pollout events */ ssh_poll_add_events(s->poll_handle, POLLOUT); return SSH_AGAIN; } if (s->write_wontblock && len > 0) { ssize_t bwritten; bwritten = ssh_socket_unbuffered_write(s, ssh_buffer_get(s->out_buffer), len); if (bwritten < 0) { session->alive = 0; ssh_socket_close(s); if (s->callbacks && s->callbacks->exception) { s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR, s->last_errno, s->callbacks->userdata); } else { ssh_set_error(session, SSH_FATAL, "Writing packet: error on socket (or connection " "closed): %s", strerror(s->last_errno)); } return SSH_ERROR; } ssh_buffer_pass_bytes(s->out_buffer, bwritten); if (s->session->socket_counter != NULL) { s->session->socket_counter->out_bytes += bwritten; } } /* Is there some data pending? */ len = ssh_buffer_get_len(s->out_buffer); if (s->poll_handle && len > 0) { /* force the poll system to catch pollout events */ ssh_poll_add_events(s->poll_handle, POLLOUT); return SSH_AGAIN; } /* all data written */ return SSH_OK; } void ssh_socket_set_write_wontblock(ssh_socket s) { s->write_wontblock = 1; } void ssh_socket_set_read_wontblock(ssh_socket s) { s->read_wontblock = 1; } void ssh_socket_set_except(ssh_socket s) { s->data_except = 1; } int ssh_socket_data_available(ssh_socket s) { return s->read_wontblock; } int ssh_socket_data_writable(ssh_socket s) { return s->write_wontblock; } /** @internal * @brief returns the number of outgoing bytes currently buffered * @param s the socket * @returns numbers of bytes buffered, or 0 if the socket isn't connected */ int ssh_socket_buffered_write_bytes(ssh_socket s) { if (s==NULL || s->out_buffer == NULL) { return 0; } return ssh_buffer_get_len(s->out_buffer); } int ssh_socket_get_status(ssh_socket s) { int r = 0; if (ssh_buffer_get_len(s->in_buffer) > 0) { r |= SSH_READ_PENDING; } if (ssh_buffer_get_len(s->out_buffer) > 0) { r |= SSH_WRITE_PENDING; } if (s->data_except) { r |= SSH_CLOSED_ERROR; } return r; } int ssh_socket_get_poll_flags(ssh_socket s) { int r = 0; if (s->poll_handle != NULL && (ssh_poll_get_events (s->poll_handle) & POLLIN) > 0) { r |= SSH_READ_PENDING; } if (s->poll_handle != NULL && (ssh_poll_get_events (s->poll_handle) & POLLOUT) > 0) { r |= SSH_WRITE_PENDING; } return r; } #ifdef _WIN32 int ssh_socket_set_nonblocking(socket_t fd) { u_long nonblocking = 1; return ioctlsocket(fd, FIONBIO, &nonblocking); } int ssh_socket_set_blocking(socket_t fd) { u_long nonblocking = 0; return ioctlsocket(fd, FIONBIO, &nonblocking); } #else /* _WIN32 */ int ssh_socket_set_nonblocking(socket_t fd) { return fcntl(fd, F_SETFL, O_NONBLOCK); } int ssh_socket_set_blocking(socket_t fd) { return fcntl(fd, F_SETFL, 0); } #endif /* _WIN32 */ /** * @internal * @brief Launches a socket connection * If a the socket connected callback has been defined and * a poll object exists, this call will be non blocking. * @param s socket to connect. * @param host hostname or ip address to connect to. * @param port port number to connect to. * @param bind_addr address to bind to, or NULL for default. * @returns SSH_OK socket is being connected. * @returns SSH_ERROR error while connecting to remote host. * @bug It only tries connecting to one of the available AI's * which is problematic for hosts having DNS fail-over. */ int ssh_socket_connect(ssh_socket s, const char *host, uint16_t port, const char *bind_addr) { socket_t fd; if (s->state != SSH_SOCKET_NONE) { ssh_set_error(s->session, SSH_FATAL, "ssh_socket_connect called on socket not unconnected"); return SSH_ERROR; } fd = ssh_connect_host_nonblocking(s->session, host, bind_addr, port); SSH_LOG(SSH_LOG_PROTOCOL, "Nonblocking connection socket: %d", fd); if (fd == SSH_INVALID_SOCKET) { return SSH_ERROR; } ssh_socket_set_fd(s,fd); return SSH_OK; } #ifndef _WIN32 /** * @internal * @brief executes a command and redirect input and outputs * @param command command to execute * @param in input file descriptor * @param out output file descriptor */ void ssh_execute_command(const char *command, socket_t in, socket_t out) { const char *args[] = {"/bin/sh", "-c", command, NULL}; /* Prepare /dev/null socket for the stderr redirection */ int devnull = open("/dev/null", O_WRONLY); if (devnull == -1) { SSH_LOG(SSH_LOG_WARNING, "Failed to open /dev/null"); exit(1); } /* redirect in and out to stdin, stdout */ dup2(in, 0); dup2(out, 1); /* Ignore anything on the stderr */ dup2(devnull, STDERR_FILENO); close(in); close(out); execv(args[0], (char * const *)args); exit(1); } /** * @internal * @brief Open a socket on a ProxyCommand * This call will always be nonblocking. * @param s socket to connect. * @param command Command to execute. * @returns SSH_OK socket is being connected. * @returns SSH_ERROR error while executing the command. */ int ssh_socket_connect_proxycommand(ssh_socket s, const char *command) { socket_t pair[2]; int pid; int rc; if (s->state != SSH_SOCKET_NONE) { return SSH_ERROR; } rc = socketpair(PF_UNIX, SOCK_STREAM, 0, pair); if (rc < 0) { return SSH_ERROR; } SSH_LOG(SSH_LOG_PROTOCOL, "Executing proxycommand '%s'", command); pid = fork(); if (pid == 0) { ssh_execute_command(command, pair[0], pair[0]); /* Does not return */ } s->proxy_pid = pid; close(pair[0]); SSH_LOG(SSH_LOG_PROTOCOL, "ProxyCommand connection pipe: [%d,%d]",pair[0],pair[1]); ssh_socket_set_fd(s, pair[1]); s->state=SSH_SOCKET_CONNECTED; s->fd_is_socket=0; /* POLLOUT is the event to wait for in a nonblocking connect */ ssh_poll_set_events(ssh_socket_get_poll_handle(s), POLLIN | POLLOUT); if (s->callbacks && s->callbacks->connected) { s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0, s->callbacks->userdata); } return SSH_OK; } #endif /* _WIN32 */ /** @} */ ================================================ FILE: src/libssh/src/string.c ================================================ /* * string.c - ssh string functions * * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #ifndef _WIN32 #include #include #endif #include "libssh/priv.h" #include "libssh/string.h" /* String maximum size is 256M */ #define STRING_SIZE_MAX 0x10000000 /** * @defgroup libssh_string The SSH string functions * @ingroup libssh * * @brief String manipulations used in libssh. * * @{ */ /** * @brief Create a new SSH String object. * * @param[in] size The size of the string. * * @return The newly allocated string, NULL on error. */ struct ssh_string_struct *ssh_string_new(size_t size) { struct ssh_string_struct *str = NULL; if (size > STRING_SIZE_MAX) { errno = EINVAL; return NULL; } str = malloc(sizeof(struct ssh_string_struct) + size); if (str == NULL) { return NULL; } str->size = htonl(size); str->data[0] = 0; return str; } /** * @brief Fill a string with given data. The string should be big enough. * * @param s An allocated string to fill with data. * * @param data The data to fill the string with. * * @param len Size of data. * * @return 0 on success, < 0 on error. */ int ssh_string_fill(struct ssh_string_struct *s, const void *data, size_t len) { if ((s == NULL) || (data == NULL) || (len == 0) || (len > ssh_string_len(s))) { return -1; } memcpy(s->data, data, len); return 0; } /** * @brief Create a ssh string using a C string * * @param[in] what The source 0-terminated C string. * * @return The newly allocated string, NULL on error with errno * set. * * @note The nul byte is not copied nor counted in the ouput string. */ struct ssh_string_struct *ssh_string_from_char(const char *what) { struct ssh_string_struct *ptr; size_t len; if(what == NULL) { errno = EINVAL; return NULL; } len = strlen(what); ptr = ssh_string_new(len); if (ptr == NULL) { return NULL; } memcpy(ptr->data, what, len); return ptr; } /** * @brief Return the size of a SSH string. * * @param[in] s The the input SSH string. * * @return The size of the content of the string, 0 on error. */ size_t ssh_string_len(struct ssh_string_struct *s) { size_t size; if (s == NULL) { return 0; } size = ntohl(s->size); if (size > 0 && size <= STRING_SIZE_MAX) { return size; } return 0; } /** * @brief Get the the string as a C nul-terminated string. * * This is only available as long as the SSH string exists. * * @param[in] s The SSH string to get the C string from. * * @return The char pointer, NULL on error. */ const char *ssh_string_get_char(struct ssh_string_struct *s) { if (s == NULL) { return NULL; } s->data[ssh_string_len(s)] = '\0'; return (const char *) s->data; } /** * @brief Convert a SSH string to a C nul-terminated string. * * @param[in] s The SSH input string. * * @return An allocated string pointer, NULL on error with errno * set. * * @note If the input SSH string contains zeroes, some parts of the output * string may not be readable with regular libc functions. */ char *ssh_string_to_char(struct ssh_string_struct *s) { size_t len; char *new; if (s == NULL) { return NULL; } len = ssh_string_len(s); if (len + 1 < len) { return NULL; } new = malloc(len + 1); if (new == NULL) { return NULL; } memcpy(new, s->data, len); new[len] = '\0'; return new; } /** * @brief Deallocate a char string object. * * @param[in] s The string to delete. */ void ssh_string_free_char(char *s) { SAFE_FREE(s); } /** * @brief Copy a string, return a newly allocated string. The caller has to * free the string. * * @param[in] s String to copy. * * @return Newly allocated copy of the string, NULL on error. */ struct ssh_string_struct *ssh_string_copy(struct ssh_string_struct *s) { struct ssh_string_struct *new; size_t len; if (s == NULL) { return NULL; } len = ssh_string_len(s); if (len == 0) { return NULL; } new = ssh_string_new(len); if (new == NULL) { return NULL; } memcpy(new->data, s->data, len); return new; } /** * @brief Destroy the data in a string so it couldn't appear in a core dump. * * @param[in] s The string to burn. */ void ssh_string_burn(struct ssh_string_struct *s) { if (s == NULL || s->size == 0) { return; } explicit_bzero(s->data, ssh_string_len(s)); } /** * @brief Get the payload of the string. * * @param s The string to get the data from. * * @return Return the data of the string or NULL on error. */ void *ssh_string_data(struct ssh_string_struct *s) { if (s == NULL) { return NULL; } return s->data; } /** * @brief Deallocate a SSH string object. * * \param[in] s The SSH string to delete. */ void ssh_string_free(struct ssh_string_struct *s) { SAFE_FREE(s); } /** @} */ ================================================ FILE: src/libssh/src/threads/libcrypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/crypto.h" #include "libssh/threads.h" #include #if (OPENSSL_VERSION_NUMBER >= 0x10100000) int crypto_thread_init(struct ssh_threads_callbacks_struct *cb) { (void) cb; return SSH_OK; } void crypto_thread_finalize(void) { return; } #else static struct ssh_threads_callbacks_struct *user_callbacks = NULL; static void **libcrypto_mutexes; void libcrypto_lock_callback(int mode, int i, const char *file, int line); void libcrypto_lock_callback(int mode, int i, const char *file, int line) { (void)file; (void)line; if (mode & CRYPTO_LOCK) { user_callbacks->mutex_lock(&libcrypto_mutexes[i]); } else { user_callbacks->mutex_unlock(&libcrypto_mutexes[i]); } } #ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK static void libcrypto_THREADID_callback(CRYPTO_THREADID *id) { unsigned long thread_id = (*user_callbacks->thread_id)(); CRYPTO_THREADID_set_numeric(id, thread_id); } #endif /* HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK */ int crypto_thread_init(struct ssh_threads_callbacks_struct *cb) { int n = CRYPTO_num_locks(); int cmp; int i; if (cb == NULL) { return SSH_OK; } if (user_callbacks != NULL) { crypto_thread_finalize(); } user_callbacks = cb; cmp = strcmp(user_callbacks->type, "threads_noop"); if (cmp == 0) { return SSH_OK; } libcrypto_mutexes = calloc(n, sizeof(void *)); if (libcrypto_mutexes == NULL) { return SSH_ERROR; } for (i = 0; i < n; ++i){ user_callbacks->mutex_init(&libcrypto_mutexes[i]); } #ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK CRYPTO_THREADID_set_callback(libcrypto_THREADID_callback); #else CRYPTO_set_id_callback(user_callbacks->thread_id); #endif CRYPTO_set_locking_callback(libcrypto_lock_callback); return SSH_OK; } void crypto_thread_finalize(void) { int n = CRYPTO_num_locks(); int i; if (libcrypto_mutexes == NULL) { return; } #ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK CRYPTO_THREADID_set_callback(NULL); #else CRYPTO_set_id_callback(NULL); #endif CRYPTO_set_locking_callback(NULL); for (i = 0; i < n; ++i) { user_callbacks->mutex_destroy(&libcrypto_mutexes[i]); } SAFE_FREE(libcrypto_mutexes); } #endif ================================================ FILE: src/libssh/src/threads/libgcrypt.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/crypto.h" #include "libssh/threads.h" #include #if (GCRYPT_VERSION_NUMBER >= 0x010600) /* libgcrypt >= 1.6 does not support custom callbacks */ GCRY_THREAD_OPTION_PTHREAD_IMPL; int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks) { (void) user_callbacks; return SSH_OK; } #else /* Libgcrypt < 1.6 specific way of handling thread callbacks */ static struct gcry_thread_cbs gcrypt_threads_callbacks; int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks) { int cmp; if (user_callbacks == NULL) { return SSH_OK; } cmp = strcmp(user_callbacks->type, "threads_noop"); if (cmp == 0) { gcrypt_threads_callbacks.option= GCRY_THREAD_OPTION_VERSION << 8 || GCRY_THREAD_OPTION_DEFAULT; } else { gcrypt_threads_callbacks.option= GCRY_THREAD_OPTION_VERSION << 8 || GCRY_THREAD_OPTION_USER; } gcrypt_threads_callbacks.mutex_init = user_callbacks->mutex_init; gcrypt_threads_callbacks.mutex_destroy = user_callbacks->mutex_destroy; gcrypt_threads_callbacks.mutex_lock = user_callbacks->mutex_lock; gcrypt_threads_callbacks.mutex_unlock = user_callbacks->mutex_unlock; gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks); return SSH_OK; } #endif /* GCRYPT_VERSION_NUMBER */ void crypto_thread_finalize(void) { return; } ================================================ FILE: src/libssh/src/threads/mbedtls.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/crypto.h" #include "libssh/threads.h" #include #include int crypto_thread_init(struct ssh_threads_callbacks_struct *user_callbacks) { int cmp; if (user_callbacks == NULL) { return SSH_OK; } cmp = strcmp(user_callbacks->type, "threads_noop"); if (cmp == 0) { return SSH_OK; } #ifdef MBEDTLS_THREADING_ALT else { if (user_callbacks != NULL) { crypto_thread_finalize(); } mbedtls_threading_set_alt(user_callbacks->mutex_init, user_callbacks->mutex_destroy, user_callbacks->mutex_lock, user_callbacks->mutex_unlock); } #elif defined MBEDTLS_THREADING_PTHREAD return SSH_OK; #else return SSH_ERROR; #endif } void crypto_thread_finalize(void) { #ifdef MBEDTLS_THREADING_ALT mbedtls_threading_free_alt(); #endif return; } ================================================ FILE: src/libssh/src/threads/noop.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/threads.h" #include static int threads_noop(void **lock) { (void)lock; return 0; } static unsigned long threads_id_noop (void) { return 1; } static struct ssh_threads_callbacks_struct ssh_threads_noop = { .type = "threads_noop", .mutex_init = threads_noop, .mutex_destroy = threads_noop, .mutex_lock = threads_noop, .mutex_unlock = threads_noop, .thread_id = threads_id_noop }; /* Threads interface implementation */ #if !(HAVE_PTHREAD) && !(defined _WIN32 || defined _WIN64) void ssh_mutex_lock(SSH_MUTEX *mutex) { (void) mutex; return; } void ssh_mutex_unlock(SSH_MUTEX *mutex) { (void) mutex; return; } struct ssh_threads_callbacks_struct *ssh_threads_get_default(void) { return &ssh_threads_noop; } #endif struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void) { return &ssh_threads_noop; } ================================================ FILE: src/libssh/src/threads/pthread.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/threads.h" #include #include #include #include static int ssh_pthread_mutex_init (void **mutex) { int rc = 0; if (mutex == NULL) { return EINVAL; } *mutex = malloc(sizeof(pthread_mutex_t)); if (*mutex == NULL) { return ENOMEM; } rc = pthread_mutex_init ((pthread_mutex_t *)*mutex, NULL); if (rc){ free (*mutex); *mutex = NULL; } return rc; } static int ssh_pthread_mutex_destroy (void **mutex) { int rc = 0; if (mutex == NULL) { return EINVAL; } rc = pthread_mutex_destroy ((pthread_mutex_t *)*mutex); free (*mutex); *mutex = NULL; return rc; } static int ssh_pthread_mutex_lock (void **mutex) { return pthread_mutex_lock((pthread_mutex_t *)*mutex); } static int ssh_pthread_mutex_unlock (void **mutex) { return pthread_mutex_unlock((pthread_mutex_t *)*mutex); } static unsigned long ssh_pthread_thread_id (void) { #if defined(_WIN32) && !defined(__WINPTHREADS_VERSION) return (unsigned long) pthread_self().p; #else return (unsigned long) pthread_self(); #endif } static struct ssh_threads_callbacks_struct ssh_threads_pthread = { .type = "threads_pthread", .mutex_init = ssh_pthread_mutex_init, .mutex_destroy = ssh_pthread_mutex_destroy, .mutex_lock = ssh_pthread_mutex_lock, .mutex_unlock = ssh_pthread_mutex_unlock, .thread_id = ssh_pthread_thread_id }; /* Threads interface implementation */ #if (HAVE_PTHREAD) void ssh_mutex_lock(SSH_MUTEX *mutex) { int rc; if (mutex == NULL) { exit(EINVAL); } rc = pthread_mutex_lock(mutex); if (rc) { exit(rc); } } void ssh_mutex_unlock(SSH_MUTEX *mutex) { int rc; if (mutex == NULL) { exit(EINVAL); } rc = pthread_mutex_unlock(mutex); if (rc) { exit(rc); } } struct ssh_threads_callbacks_struct *ssh_threads_get_default(void) { return &ssh_threads_pthread; } #endif struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void) { return &ssh_threads_pthread; } ================================================ FILE: src/libssh/src/threads/winlocks.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "libssh/threads.h" #include #include #include #include static int ssh_winlock_mutex_init (void **priv) { CRITICAL_SECTION *lock = malloc(sizeof(CRITICAL_SECTION)); if (lock == NULL) { return ENOMEM; } InitializeCriticalSection(lock); *priv = lock; return 0; } static int ssh_winlock_mutex_destroy (void **lock) { DeleteCriticalSection((CRITICAL_SECTION *) *lock); free(*lock); return 0; } static int ssh_winlock_mutex_lock (void **lock) { EnterCriticalSection((CRITICAL_SECTION *) *lock); return 0; } static int ssh_winlock_mutex_unlock (void **lock) { LeaveCriticalSection((CRITICAL_SECTION *) *lock); return 0; } static unsigned long ssh_winlock_thread_id (void) { return GetCurrentThreadId(); } static struct ssh_threads_callbacks_struct ssh_threads_winlock = { .type = "threads_winlock", .mutex_init = ssh_winlock_mutex_init, .mutex_destroy = ssh_winlock_mutex_destroy, .mutex_lock = ssh_winlock_mutex_lock, .mutex_unlock = ssh_winlock_mutex_unlock, .thread_id = ssh_winlock_thread_id }; /* Threads interface implementation */ void ssh_mutex_lock(SSH_MUTEX *mutex) { void *rc; CRITICAL_SECTION *mutex_tmp = NULL; if (*mutex == NULL) { mutex_tmp = malloc(sizeof(CRITICAL_SECTION)); if (mutex_tmp == NULL) { exit(ENOMEM); } InitializeCriticalSection(mutex_tmp); rc = InterlockedCompareExchangePointer((PVOID*)mutex, (PVOID)mutex_tmp, NULL); if (rc != NULL) { DeleteCriticalSection(mutex_tmp); free(mutex_tmp); exit(ENOMEM); } } EnterCriticalSection(*mutex); } void ssh_mutex_unlock(SSH_MUTEX *mutex) { LeaveCriticalSection(*mutex); } struct ssh_threads_callbacks_struct *ssh_threads_get_winlock(void) { return &ssh_threads_winlock; } struct ssh_threads_callbacks_struct *ssh_threads_get_default(void) { return &ssh_threads_winlock; } ================================================ FILE: src/libssh/src/threads.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /** * @defgroup libssh_threads The SSH threading functions. * @ingroup libssh * * Threading with libssh * @{ */ #include "config.h" #include "libssh/priv.h" #include "libssh/crypto.h" #include "libssh/threads.h" static struct ssh_threads_callbacks_struct *user_callbacks = NULL; /** @internal * @brief inits the threading with the backend cryptographic libraries */ int ssh_threads_init(void) { static int threads_initialized = 0; int rc; if (threads_initialized) { return SSH_OK; } /* first initialize the user_callbacks with our default handlers if not * already the case */ if (user_callbacks == NULL){ user_callbacks = ssh_threads_get_default(); } /* Then initialize the crypto libraries threading callbacks */ rc = crypto_thread_init(user_callbacks); if (rc == SSH_OK) { threads_initialized = 1; } return rc; } void ssh_threads_finalize(void) { crypto_thread_finalize(); } int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct *cb) { int rc; if (user_callbacks != NULL) { crypto_thread_finalize(); } user_callbacks = cb; rc = crypto_thread_init(user_callbacks); return rc; } const char *ssh_threads_get_type(void) { if (user_callbacks != NULL) { return user_callbacks->type; } return NULL; } /** * @} */ ================================================ FILE: src/libssh/src/token.c ================================================ /* * token.c - Token list handling functions * * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis * Copyright (c) 2019 by Anderson Toshiyuki Sasaki - Red Hat, Inc. * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include "libssh/priv.h" #include "libssh/token.h" /** * @internal * * @brief Free the given tokens list structure. The used buffer is overwritten * with zeroes before freed. * * @param[in] tokens The pointer to a structure to be freed; */ void ssh_tokens_free(struct ssh_tokens_st *tokens) { int i; if (tokens == NULL) { return; } if (tokens->tokens != NULL) { for (i = 0; tokens->tokens[i] != NULL; i++) { explicit_bzero(tokens->tokens[i], strlen(tokens->tokens[i])); } } SAFE_FREE(tokens->buffer); SAFE_FREE(tokens->tokens); SAFE_FREE(tokens); } /** * @internal * * @brief Split a given string on the given separator character. The returned * structure holds an array of pointers (tokens) pointing to the obtained * parts and a buffer where all the content of the list is stored. The last * element of the array will always be set as NULL. * * @param[in] chain The string to split * @param[in] separator The character used to separate the tokens. * * @return A newly allocated tokens list structure; NULL in case of error. */ struct ssh_tokens_st *ssh_tokenize(const char *chain, char separator) { struct ssh_tokens_st *tokens = NULL; size_t num_tokens = 1, i = 1; char *found, *c; if (chain == NULL) { return NULL; } tokens = calloc(1, sizeof(struct ssh_tokens_st)); if (tokens == NULL) { return NULL; } tokens->buffer= strdup(chain); if (tokens->buffer == NULL) { goto error; } c = tokens->buffer; do { found = strchr(c, separator); if (found != NULL) { c = found + 1; num_tokens++; } } while(found != NULL); /* Allocate tokens list */ tokens->tokens = calloc(num_tokens + 1, sizeof(char *)); if (tokens->tokens == NULL) { goto error; } /* First token starts in the beginning of the chain */ tokens->tokens[0] = tokens->buffer; c = tokens->buffer; for (i = 1; i < num_tokens; i++) { /* Find next separator */ found = strchr(c, separator); if (found == NULL) { break; } /* Replace it with a string terminator */ *found = '\0'; /* The next token starts in the next byte */ c = found + 1; /* If we did not reach the end of the chain yet, set the next token */ if (*c != '\0') { tokens->tokens[i] = c; } else { break; } } return tokens; error: ssh_tokens_free(tokens); return NULL; } /** * @internal * * @brief Given two strings, the first containing a list of available tokens and * the second containing a list of tokens to be searched ordered by preference, * returns a copy of the first preferred token present in the available list. * * @param[in] available_list The list of available tokens * @param[in] preferred_list The list of tokens to search, ordered by * preference * * @return A newly allocated copy of the token if found; NULL otherwise */ char *ssh_find_matching(const char *available_list, const char *preferred_list) { struct ssh_tokens_st *a_tok = NULL, *p_tok = NULL; int i, j; char *ret = NULL; if ((available_list == NULL) || (preferred_list == NULL)) { return NULL; } a_tok = ssh_tokenize(available_list, ','); if (a_tok == NULL) { return NULL; } p_tok = ssh_tokenize(preferred_list, ','); if (p_tok == NULL) { goto out; } for (i = 0; p_tok->tokens[i]; i++) { for (j = 0; a_tok->tokens[j]; j++) { if (strcmp(a_tok->tokens[j], p_tok->tokens[i]) == 0) { ret = strdup(a_tok->tokens[j]); goto out; } } } out: ssh_tokens_free(a_tok); ssh_tokens_free(p_tok); return ret; } /** * @internal * * @brief Given two strings, the first containing a list of available tokens and * the second containing a list of tokens to be searched ordered by preference, * returns a list of all matching tokens ordered by preference. * * @param[in] available_list The list of available tokens * @param[in] preferred_list The list of tokens to search, ordered by * preference * * @return A newly allocated string containing the list of all matching tokens; * NULL otherwise */ char *ssh_find_all_matching(const char *available_list, const char *preferred_list) { struct ssh_tokens_st *a_tok = NULL, *p_tok = NULL; int i, j; char *ret = NULL; size_t max, len, pos = 0; int match; if ((available_list == NULL) || (preferred_list == NULL)) { return NULL; } max = MAX(strlen(available_list), strlen(preferred_list)); ret = calloc(1, max + 1); if (ret == NULL) { return NULL; } a_tok = ssh_tokenize(available_list, ','); if (a_tok == NULL) { SAFE_FREE(ret); goto out; } p_tok = ssh_tokenize(preferred_list, ','); if (p_tok == NULL) { SAFE_FREE(ret); goto out; } for (i = 0; p_tok->tokens[i] ; i++) { for (j = 0; a_tok->tokens[j]; j++) { match = !strcmp(a_tok->tokens[j], p_tok->tokens[i]); if (match) { if (pos != 0) { ret[pos] = ','; pos++; } len = strlen(a_tok->tokens[j]); memcpy(&ret[pos], a_tok->tokens[j], len); pos += len; ret[pos] = '\0'; } } } if (ret[0] == '\0') { SAFE_FREE(ret); } out: ssh_tokens_free(a_tok); ssh_tokens_free(p_tok); return ret; } /** * @internal * * @brief Given a string containing a list of elements, remove all duplicates * and return in a newly allocated string. * * @param[in] list The list to be freed of duplicates * * @return A newly allocated copy of the string free of duplicates; NULL in * case of error. */ char *ssh_remove_duplicates(const char *list) { struct ssh_tokens_st *tok = NULL; size_t i, j, num_tokens, max_len; char *ret = NULL; bool *should_copy = NULL, need_comma = false; if (list == NULL) { return NULL; } /* The maximum number of tokens is the size of the list */ max_len = strlen(list); if (max_len == 0) { return NULL; } /* Add space for ending '\0' */ max_len++; tok = ssh_tokenize(list, ','); if ((tok == NULL) || (tok->tokens == NULL) || (tok->tokens[0] == NULL)) { goto out; } should_copy = calloc(1, max_len); if (should_copy == NULL) { goto out; } if (strlen(tok->tokens[0]) > 0) { should_copy[0] = true; } for (i = 1; tok->tokens[i]; i++) { for (j = 0; j < i; j++) { if (strcmp(tok->tokens[i], tok->tokens[j]) == 0) { /* Found a duplicate; do not copy */ should_copy[i] = false; break; } } /* No matching token before */ if (j == i) { /* Only copy if it is not an empty string */ if (strlen(tok->tokens[i]) > 0) { should_copy[i] = true; } else { should_copy[i] = false; } } } num_tokens = i; ret = calloc(1, max_len); if (ret == NULL) { goto out; } for (i = 0; i < num_tokens; i++) { if (should_copy[i]) { if (need_comma) { strncat(ret, ",", (max_len - strlen(ret) - 1)); } strncat(ret, tok->tokens[i], (max_len - strlen(ret) - 1)); need_comma = true; } } /* If no comma is needed, nothing was copied */ if (!need_comma) { SAFE_FREE(ret); } out: SAFE_FREE(should_copy); ssh_tokens_free(tok); return ret; } /** * @internal * * @brief Given two strings containing lists of tokens, return a newly * allocated string containing all the elements of the first list appended with * all the elements of the second list, without duplicates. The order of the * elements will be preserved. * * @param[in] list The first list * @param[in] appended_list The list to be appended * * @return A newly allocated copy list containing all the elements of the * kept_list appended with the elements of the appended_list without duplicates; * NULL in case of error. */ char *ssh_append_without_duplicates(const char *list, const char *appended_list) { size_t concat_len = 0; char *ret = NULL, *concat = NULL; if (list != NULL) { concat_len = strlen(list); } if (appended_list != NULL) { concat_len += strlen(appended_list); } if (concat_len == 0) { return NULL; } /* Add room for ending '\0' and for middle ',' */ concat_len += 2; concat = calloc(1, concat_len); if (concat == NULL) { return NULL; } if (list != NULL) { strcpy(concat, list); strncat(concat, ",", concat_len - strlen(concat) - 1); } if (appended_list != NULL) { strncat(concat, appended_list, concat_len - strlen(concat) - 1); } ret = ssh_remove_duplicates(concat); SAFE_FREE(concat); return ret; } ================================================ FILE: src/libssh/src/wrapper.c ================================================ /* * wrapper.c - wrapper for crytpo functions * * This file is part of the SSH Library * * Copyright (c) 2003-2013 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* * Why a wrapper? * * Let's say you want to port libssh from libcrypto of openssl to libfoo * you are going to spend hours to remove every references to SHA1_Update() * to libfoo_sha1_update after the work is finished, you're going to have * only this file to modify it's not needed to say that your modifications * are welcome. */ #include "config.h" #include #include #include #ifdef WITH_ZLIB #include #endif #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/wrapper.h" #include "libssh/pki.h" #include "libssh/poly1305.h" #include "libssh/dh.h" #ifdef WITH_GEX #include "libssh/dh-gex.h" #endif /* WITH_GEX */ #include "libssh/ecdh.h" #include "libssh/curve25519.h" #define SHA_96_DIGEST_LEN 12 #define MD5_96_DIGEST_LEN 12 static struct ssh_hmac_struct ssh_hmac_tab[] = { { "hmac-sha1", SSH_HMAC_SHA1, false }, { "hmac-sha1-96", SSH_HMAC_SHA1_96, false }, { "hmac-sha2-256", SSH_HMAC_SHA256, false }, { "hmac-sha2-512", SSH_HMAC_SHA512, false }, { "hmac-md5", SSH_HMAC_MD5, false }, { "hmac-md5-96", SSH_HMAC_MD5_96, false }, { "aead-poly1305", SSH_HMAC_AEAD_POLY1305, false }, { "aead-gcm", SSH_HMAC_AEAD_GCM, false }, { "hmac-sha1-etm@openssh.com", SSH_HMAC_SHA1, true }, { "hmac-sha1-96-etm@openssh.com", SSH_HMAC_SHA1_96, true }, { "hmac-sha2-256-etm@openssh.com", SSH_HMAC_SHA256, true }, { "hmac-sha2-512-etm@openssh.com", SSH_HMAC_SHA512, true }, { "hmac-md5-etm@openssh.com", SSH_HMAC_MD5, true }, { "hmac-md5-96-etm@openssh.com", SSH_HMAC_MD5_96, true }, { NULL, 0, false } }; struct ssh_hmac_struct *ssh_get_hmactab(void) { return ssh_hmac_tab; } size_t hmac_digest_len(enum ssh_hmac_e type) { switch(type) { case SSH_HMAC_SHA1: return SHA_DIGEST_LEN; case SSH_HMAC_SHA1_96: return SHA_96_DIGEST_LEN; case SSH_HMAC_SHA256: return SHA256_DIGEST_LEN; case SSH_HMAC_SHA512: return SHA512_DIGEST_LEN; case SSH_HMAC_MD5: return MD5_DIGEST_LEN; case SSH_HMAC_MD5_96: return MD5_96_DIGEST_LEN; case SSH_HMAC_AEAD_POLY1305: return POLY1305_TAGLEN; case SSH_HMAC_AEAD_GCM: return AES_GCM_TAGLEN; default: return 0; } } size_t hmac_key_len(enum ssh_hmac_e type) { switch (type) { case SSH_HMAC_SHA1: case SSH_HMAC_SHA1_96: return SHA_DIGEST_LEN; case SSH_HMAC_SHA256: return SHA256_DIGEST_LEN; case SSH_HMAC_SHA512: return SHA512_DIGEST_LEN; case SSH_HMAC_MD5: case SSH_HMAC_MD5_96: return MD5_DIGEST_LEN; case SSH_HMAC_AEAD_POLY1305: return POLY1305_TAGLEN; case SSH_HMAC_AEAD_GCM: return AES_GCM_TAGLEN; default: return 0; } } const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, bool etm) { int i = 0; struct ssh_hmac_struct *ssh_hmactab = ssh_get_hmactab(); while (ssh_hmactab[i].name && ((ssh_hmactab[i].hmac_type != hmac_type) || (ssh_hmactab[i].etm != etm))) { i++; } return ssh_hmactab[i].name; } /* it allocates a new cipher structure based on its offset into the global table */ static struct ssh_cipher_struct *cipher_new(int offset) { struct ssh_cipher_struct *cipher = NULL; cipher = malloc(sizeof(struct ssh_cipher_struct)); if (cipher == NULL) { return NULL; } /* note the memcpy will copy the pointers : so, you shouldn't free them */ memcpy(cipher, &ssh_get_ciphertab()[offset], sizeof(*cipher)); return cipher; } void ssh_cipher_clear(struct ssh_cipher_struct *cipher){ #ifdef HAVE_LIBGCRYPT unsigned int i; #endif if (cipher == NULL) { return; } #ifdef HAVE_LIBGCRYPT if (cipher->key) { for (i = 0; i < (cipher->keylen / sizeof(gcry_cipher_hd_t)); i++) { gcry_cipher_close(cipher->key[i]); } SAFE_FREE(cipher->key); } #endif if (cipher->cleanup != NULL) { cipher->cleanup(cipher); } } static void cipher_free(struct ssh_cipher_struct *cipher) { ssh_cipher_clear(cipher); SAFE_FREE(cipher); } struct ssh_crypto_struct *crypto_new(void) { struct ssh_crypto_struct *crypto; crypto = malloc(sizeof(struct ssh_crypto_struct)); if (crypto == NULL) { return NULL; } ZERO_STRUCTP(crypto); return crypto; } void crypto_free(struct ssh_crypto_struct *crypto) { size_t i; if (crypto == NULL) { return; } ssh_key_free(crypto->server_pubkey); ssh_dh_cleanup(crypto); bignum_safe_free(crypto->shared_secret); #ifdef HAVE_ECDH SAFE_FREE(crypto->ecdh_client_pubkey); SAFE_FREE(crypto->ecdh_server_pubkey); if(crypto->ecdh_privkey != NULL){ #ifdef HAVE_OPENSSL_ECC EC_KEY_free(crypto->ecdh_privkey); #elif defined HAVE_GCRYPT_ECC gcry_sexp_release(crypto->ecdh_privkey); #endif crypto->ecdh_privkey = NULL; } #endif if (crypto->session_id != NULL) { explicit_bzero(crypto->session_id, crypto->digest_len); SAFE_FREE(crypto->session_id); } if (crypto->secret_hash != NULL) { explicit_bzero(crypto->secret_hash, crypto->digest_len); SAFE_FREE(crypto->secret_hash); } #ifdef WITH_ZLIB if (crypto->compress_out_ctx && (deflateEnd(crypto->compress_out_ctx) != 0)) { inflateEnd(crypto->compress_out_ctx); } SAFE_FREE(crypto->compress_out_ctx); if (crypto->compress_in_ctx && (deflateEnd(crypto->compress_in_ctx) != 0)) { inflateEnd(crypto->compress_in_ctx); } SAFE_FREE(crypto->compress_in_ctx); #endif /* WITH_ZLIB */ SAFE_FREE(crypto->encryptIV); SAFE_FREE(crypto->decryptIV); SAFE_FREE(crypto->encryptMAC); SAFE_FREE(crypto->decryptMAC); if (crypto->encryptkey != NULL) { explicit_bzero(crypto->encryptkey, crypto->out_cipher->keysize / 8); SAFE_FREE(crypto->encryptkey); } if (crypto->decryptkey != NULL) { explicit_bzero(crypto->decryptkey, crypto->in_cipher->keysize / 8); SAFE_FREE(crypto->decryptkey); } cipher_free(crypto->in_cipher); cipher_free(crypto->out_cipher); for (i = 0; i < SSH_KEX_METHODS; i++) { SAFE_FREE(crypto->client_kex.methods[i]); SAFE_FREE(crypto->server_kex.methods[i]); SAFE_FREE(crypto->kex_methods[i]); } explicit_bzero(crypto, sizeof(struct ssh_crypto_struct)); SAFE_FREE(crypto); } static int crypt_set_algorithms2(ssh_session session) { const char *wanted = NULL; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); size_t i = 0; int cmp; /* * We must scan the kex entries to find crypto algorithms and set their * appropriate structure. */ /* out */ wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S]; for (i = 0; i < 64 && ssh_ciphertab[i].name != NULL; ++i) { cmp = strcmp(wanted, ssh_ciphertab[i].name); if (cmp == 0) { break; } } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms2: no crypto algorithm function found for %s", wanted); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set output algorithm to %s", wanted); session->next_crypto->out_cipher = cipher_new(i); if (session->next_crypto->out_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } if (session->next_crypto->out_cipher->aead_encrypt != NULL) { /* this cipher has integrated MAC */ if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) { wanted = "aead-poly1305"; } else { wanted = "aead-gcm"; } } else { /* * We must scan the kex entries to find hmac algorithms and set their * appropriate structure. */ /* out */ wanted = session->next_crypto->kex_methods[SSH_MAC_C_S]; } for (i = 0; ssh_hmactab[i].name != NULL; i++) { cmp = strcmp(wanted, ssh_hmactab[i].name); if (cmp == 0) { break; } } if (ssh_hmactab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms2: no hmac algorithm function found for %s", wanted); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted); session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type; session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm; /* in */ wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C]; for (i = 0; ssh_ciphertab[i].name != NULL; i++) { cmp = strcmp(wanted, ssh_ciphertab[i].name); if (cmp == 0) { break; } } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "Crypt_set_algorithms: no crypto algorithm function found for %s", wanted); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set input algorithm to %s", wanted); session->next_crypto->in_cipher = cipher_new(i); if (session->next_crypto->in_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } if (session->next_crypto->in_cipher->aead_encrypt != NULL){ /* this cipher has integrated MAC */ if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) { wanted = "aead-poly1305"; } else { wanted = "aead-gcm"; } } else { /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */ wanted = session->next_crypto->kex_methods[SSH_MAC_S_C]; } for (i = 0; ssh_hmactab[i].name != NULL; i++) { cmp = strcmp(wanted, ssh_hmactab[i].name); if (cmp == 0) { break; } } if (ssh_hmactab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms2: no hmac algorithm function found for %s", wanted); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted); session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type; session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm; /* compression */ cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib"); if (cmp == 0) { session->next_crypto->do_compress_out = 1; } cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib"); if (cmp == 0) { session->next_crypto->do_compress_in = 1; } cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib@openssh.com"); if (cmp == 0) { session->next_crypto->delayed_compress_out = 1; } cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_S_C], "zlib@openssh.com"); if (cmp == 0) { session->next_crypto->delayed_compress_in = 1; } return SSH_OK; } int crypt_set_algorithms_client(ssh_session session) { return crypt_set_algorithms2(session); } #ifdef WITH_SERVER int crypt_set_algorithms_server(ssh_session session){ const char *method = NULL; size_t i = 0; struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab(); struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab(); int cmp; if (session == NULL) { return SSH_ERROR; } /* * We must scan the kex entries to find crypto algorithms and set their * appropriate structure */ /* out */ method = session->next_crypto->kex_methods[SSH_CRYPT_S_C]; for (i = 0; ssh_ciphertab[i].name != NULL; i++) { cmp = strcmp(method, ssh_ciphertab[i].name); if (cmp == 0) { break; } } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session,SSH_FATAL,"crypt_set_algorithms_server : " "no crypto algorithm function found for %s",method); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET,"Set output algorithm %s",method); session->next_crypto->out_cipher = cipher_new(i); if (session->next_crypto->out_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } if (session->next_crypto->out_cipher->aead_encrypt != NULL){ /* this cipher has integrated MAC */ if (session->next_crypto->out_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) { method = "aead-poly1305"; } else { method = "aead-gcm"; } } else { /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */ /* out */ method = session->next_crypto->kex_methods[SSH_MAC_S_C]; } /* HMAC algorithm selection */ for (i = 0; ssh_hmactab[i].name != NULL; i++) { cmp = strcmp(method, ssh_hmactab[i].name); if (cmp == 0) { break; } } if (ssh_hmactab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms_server: no hmac algorithm function found for %s", method); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", method); session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type; session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm; /* in */ method = session->next_crypto->kex_methods[SSH_CRYPT_C_S]; for (i = 0; ssh_ciphertab[i].name; i++) { cmp = strcmp(method, ssh_ciphertab[i].name); if (cmp == 0) { break; } } if (ssh_ciphertab[i].name == NULL) { ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server :" "no crypto algorithm function found for %s",method); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET,"Set input algorithm %s",method); session->next_crypto->in_cipher = cipher_new(i); if (session->next_crypto->in_cipher == NULL) { ssh_set_error_oom(session); return SSH_ERROR; } if (session->next_crypto->in_cipher->aead_encrypt != NULL){ /* this cipher has integrated MAC */ if (session->next_crypto->in_cipher->ciphertype == SSH_AEAD_CHACHA20_POLY1305) { method = "aead-poly1305"; } else { method = "aead-gcm"; } } else { /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */ method = session->next_crypto->kex_methods[SSH_MAC_C_S]; } for (i = 0; ssh_hmactab[i].name != NULL; i++) { cmp = strcmp(method, ssh_hmactab[i].name); if (cmp == 0) { break; } } if (ssh_hmactab[i].name == NULL) { ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms_server: no hmac algorithm function found for %s", method); return SSH_ERROR; } SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method); session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type; session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm; /* compression */ method = session->next_crypto->kex_methods[SSH_COMP_C_S]; if(strcmp(method,"zlib") == 0){ SSH_LOG(SSH_LOG_PACKET,"enabling C->S compression"); session->next_crypto->do_compress_in=1; } if(strcmp(method,"zlib@openssh.com") == 0){ SSH_LOG(SSH_LOG_PACKET,"enabling C->S delayed compression"); if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { session->next_crypto->do_compress_in = 1; } else { session->next_crypto->delayed_compress_in = 1; } } method = session->next_crypto->kex_methods[SSH_COMP_S_C]; if(strcmp(method,"zlib") == 0){ SSH_LOG(SSH_LOG_PACKET, "enabling S->C compression"); session->next_crypto->do_compress_out=1; } if(strcmp(method,"zlib@openssh.com") == 0){ SSH_LOG(SSH_LOG_PACKET,"enabling S->C delayed compression"); if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { session->next_crypto->do_compress_out = 1; } else { session->next_crypto->delayed_compress_out = 1; } } method = session->next_crypto->kex_methods[SSH_HOSTKEYS]; session->srv.hostkey = ssh_key_type_from_signature_name(method); session->srv.hostkey_digest = ssh_key_hash_from_name(method); /* setup DH key exchange type */ switch (session->next_crypto->kex_type) { case SSH_KEX_DH_GROUP1_SHA1: case SSH_KEX_DH_GROUP14_SHA1: case SSH_KEX_DH_GROUP14_SHA256: case SSH_KEX_DH_GROUP16_SHA512: case SSH_KEX_DH_GROUP18_SHA512: ssh_server_dh_init(session); break; #ifdef WITH_GEX case SSH_KEX_DH_GEX_SHA1: case SSH_KEX_DH_GEX_SHA256: ssh_server_dhgex_init(session); break; #endif /* WITH_GEX */ #ifdef HAVE_ECDH case SSH_KEX_ECDH_SHA2_NISTP256: case SSH_KEX_ECDH_SHA2_NISTP384: case SSH_KEX_ECDH_SHA2_NISTP521: ssh_server_ecdh_init(session); break; #endif #ifdef HAVE_CURVE25519 case SSH_KEX_CURVE25519_SHA256: case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG: ssh_server_curve25519_init(session); break; #endif default: ssh_set_error(session, SSH_FATAL, "crypt_set_algorithms_server: could not find init " "handler for kex type %d", session->next_crypto->kex_type); return SSH_ERROR; } return SSH_OK; } #endif /* WITH_SERVER */ ================================================ FILE: src/libssh/tests/CMakeLists.txt ================================================ project(libssh-tests C) if (BSD OR SOLARIS OR OSX) find_package(Argp) endif (BSD OR SOLARIS OR OSX) set(TORTURE_LIBRARY torture) include_directories(${OPENSSL_INCLUDE_DIR} ${CMOCKA_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR} ${libssh_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/tests) set(TORTURE_LINK_LIBRARIES ${CMOCKA_LIBRARY} ssh::static) # create test library add_library(${TORTURE_LIBRARY} STATIC cmdline.c torture.c torture_key.c torture_pki.c torture_cmocka.c) target_link_libraries(${TORTURE_LIBRARY} ${TORTURE_LINK_LIBRARIES}) target_compile_options(${TORTURE_LIBRARY} PRIVATE -DSSH_PING_EXECUTABLE="${CMAKE_CURRENT_BINARY_DIR}/ssh_ping" ) if (ARGP_LIBRARY) target_link_libraries(${TORTURE_LIBRARY} ${ARGP_LIBRARY} ) endif() set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY} ${TORTURE_LINK_LIBRARIES} ) add_subdirectory(unittests) # OpenSSH Capabilities are required for all unit tests find_program(SSH_EXECUTABLE NAMES ssh) if (SSH_EXECUTABLE) execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR) string(REGEX REPLACE "^.*OpenSSH_([0-9]).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}") string(REGEX REPLACE "^.*OpenSSH_[0-9].([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}") set(OPENSSH_VERSION "${OPENSSH_VERSION_MAJOR}.${OPENSSH_VERSION_MINOR}") if("${OPENSSH_VERSION}" VERSION_LESS "6.3") # ssh - Q was introduced in 6.3 message("Version less than 6.3, hardcoding cipher list") set(OPENSSH_CIPHERS "aes128-ctr\naes192-ctr\naes256-ctr\narcfour256\narcfour128\naes128-gcm@openssh.com\naes256-gcm@openssh.com\naes128-cbc\n3des-cbc\nblowfish-cbc\ncast128-cbc\naes192-cbc\naes256-cbc\narcfour\nrijndael-cbc@lysator.liu.se\n") set(OPENSSH_MACS "hmac-md5-etm@openssh.com\nhmac-sha1-etm@openssh.com\numac-64-etm@openssh.com\numac-128-etm@openssh.com\nhmac-sha2-256-etm@openssh.com\nhmac-sha2-512-etm@openssh.com\nhmac-ripemd160-etm@openssh.com\nhmac-sha1-96-etm@openssh.com\nhmac-md5-96-etm@openssh.com\nhmac-md5\nhmac-sha1\numac-64@openssh.com\numac-128@openssh.com\nhmac-sha2-256\nhmac-sha2-512\nhmac-ripemd160\nhmac-ripemd160@openssh.com\nhmac-sha1-96\nhmac-md5-96\n") set(OPENSSH_KEX "ecdh-sha2-nistp256\necdh-sha2-nistp384\necdh-sha2-nistp521\ndiffie-hellman-group-exchange-sha256\ndiffie-hellman-group-exchange-sha1\ndiffie-hellman-group14-sha1\ndiffie-hellman-group1-sha1\n") set(OPENSSH_KEYS "ssh-rsa\nssh-dss\necdsa-sha2-nistp256\n") else() execute_process(COMMAND ${SSH_EXECUTABLE} -Q cipher OUTPUT_VARIABLE OPENSSH_CIPHERS) execute_process(COMMAND ${SSH_EXECUTABLE} -Q mac OUTPUT_VARIABLE OPENSSH_MACS) execute_process(COMMAND ${SSH_EXECUTABLE} -Q kex OUTPUT_VARIABLE OPENSSH_KEX) execute_process(COMMAND ${SSH_EXECUTABLE} -Q key OUTPUT_VARIABLE OPENSSH_KEYS) execute_process(COMMAND ${SSH_EXECUTABLE} -Q sig OUTPUT_VARIABLE OPENSSH_SIGS ERROR_QUIET) # We need both of them, but lets get rid of duplicate items presented in both lists # to avoid processing too long arguments in pkd set(OPENSSH_KEYS "${OPENSSH_KEYS}${OPENSSH_SIGS}") string(REPLACE "\n" ";" OPENSSH_KEYS "${OPENSSH_KEYS}") list(REMOVE_DUPLICATES OPENSSH_KEYS) string(REPLACE ";" "\n" OPENSSH_KEYS "${OPENSSH_KEYS}") endif() set(SSH_ALGORITHMS 3des-cbc aes128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com hmac-sha1 hmac-sha1-96 hmac-sha2-256 hmac-sha2-512 hmac-md5 hmac-md5-96 umac-64@openssh.com umac-128@openssh.com hmac-sha1-etm@openssh.com hmac-sha1-96-etm@openssh.com hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com hmac-md5-etm@openssh.com hmac-md5-96-etm@openssh.com umac-64-etm@openssh.com umac-128-etm@openssh.com diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group14-sha256 diffie-hellman-group16-sha512 diffie-hellman-group18-sha512 diffie-hellman-group-exchange-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 curve25519-sha256 curve25519-sha256@libssh.org ssh-ed25519 ssh-ed25519-cert-v01@openssh.com ssh-rsa ssh-dss ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 ssh-rsa-cert-v01@openssh.com ssh-dss-cert-v01@openssh.com ecdsa-sha2-nistp256-cert-v01@openssh.com ecdsa-sha2-nistp384-cert-v01@openssh.com ecdsa-sha2-nistp521-cert-v01@openssh.com ) foreach(ALGORITHM ${SSH_ALGORITHMS}) string(TOUPPER ${ALGORITHM} VARNAME) string(REGEX REPLACE "[-@.]" "_" VARNAME "OPENSSH_${VARNAME}") # Match the current algorithm into the complete list of OpenSSH supported algorithms. # If matching, create an OPENSSH_CIPHER_NAME variable. string(REGEX MATCH ".*${ALGORITHM}\n" "${VARNAME}" "${OPENSSH_CIPHERS}${OPENSSH_MACS}${OPENSSH_KEX}${OPENSSH_KEYS}") endforeach(ALGORITHM) string(STRIP "${OPENSSH_CIPHERS}" OPENSSH_CIPHERS) string(STRIP "${OPENSSH_MACS}" OPENSSH_MACS) string(STRIP "${OPENSSH_KEX}" OPENSSH_KEX) string(STRIP "${OPENSSH_KEYS}" OPENSSH_KEYS) string(REPLACE "\n" "," OPENSSH_CIPHERS "${OPENSSH_CIPHERS}") string(REPLACE "\n" "," OPENSSH_MACS "${OPENSSH_MACS}") string(REPLACE "\n" "," OPENSSH_KEX "${OPENSSH_KEX}") string(REPLACE "\n" "," OPENSSH_KEYS "${OPENSSH_KEYS}") endif() find_program(SSHD_EXECUTABLE NAME sshd PATHS /sbin /usr/sbin /usr/local/sbin) if (CLIENT_TESTING OR SERVER_TESTING) find_package(socket_wrapper 1.1.5 REQUIRED) find_package(nss_wrapper 1.1.2 REQUIRED) find_package(uid_wrapper 1.2.0 REQUIRED) find_package(pam_wrapper 1.0.1 REQUIRED) if (NOT SSHD_EXECUTABLE) message(SEND_ERROR "Could not find sshd which is required for client testing") endif() find_program(NC_EXECUTABLE NAME nc PATHS /bin /usr/bin /usr/local/bin) find_program(SSH_EXECUTABLE NAMES ssh) if (SSH_EXECUTABLE) execute_process(COMMAND ${SSH_EXECUTABLE} -V ERROR_VARIABLE OPENSSH_VERSION_STR) string(REGEX REPLACE "^.*OpenSSH_([0-9]).[0-9].*$" "\\1" OPENSSH_VERSION_MAJOR "${OPENSSH_VERSION_STR}") string(REGEX REPLACE "^.*OpenSSH_[0-9].([0-9]).*$" "\\1" OPENSSH_VERSION_MINOR "${OPENSSH_VERSION_STR}") add_definitions(-DOPENSSH_VERSION_MAJOR=${OPENSSH_VERSION_MAJOR} -DOPENSSH_VERSION_MINOR=${OPENSSH_VERSION_MINOR}) endif() set(LOCAL_USER "nobody") set(LOCAL_UID "65533") find_program(ID_EXECUTABLE NAMES id) find_program(WHO_EXECUTABLE NAMES whoami) if (ID_EXECUTABLE AND WHO_EXECUTABLE) execute_process(COMMAND ${WHO_EXECUTABLE} OUTPUT_VARIABLE LOCAL_USER OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND ${ID_EXECUTABLE} -u OUTPUT_VARIABLE LOCAL_UID OUTPUT_STRIP_TRAILING_WHITESPACE) endif() # chroot_wrapper add_library(chroot_wrapper SHARED chroot_wrapper.c) set(CHROOT_WRAPPER_LIBRARY ${libssh_BINARY_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}chroot_wrapper${CMAKE_SHARED_LIBRARY_SUFFIX}) set(TEST_TARGET_LIBRARIES ${TEST_TARGET_LIBRARIES} chroot_wrapper ) # ssh_ping add_executable(ssh_ping ssh_ping.c) target_compile_options(ssh_ping PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(ssh_ping ssh::ssh) # homedir will be used in passwd set(HOMEDIR ${CMAKE_CURRENT_BINARY_DIR}/home) ### Setup nss_wrapper configure_file(etc/passwd.in ${CMAKE_CURRENT_BINARY_DIR}/etc/passwd @ONLY) configure_file(etc/shadow.in ${CMAKE_CURRENT_BINARY_DIR}/etc/shadow @ONLY) configure_file(etc/group.in ${CMAKE_CURRENT_BINARY_DIR}/etc/group @ONLY) configure_file(etc/hosts.in ${CMAKE_CURRENT_BINARY_DIR}/etc/hosts @ONLY) ### Setup pam_wrapper configure_file(etc/pam_matrix_passdb.in ${CMAKE_CURRENT_BINARY_DIR}/etc/pam_matrix_passdb @ONLY) configure_file(etc/pam.d/sshd.in ${CMAKE_CURRENT_BINARY_DIR}/etc/pam.d/sshd @ONLY) set(TORTURE_ENVIRONMENT "LD_PRELOAD=${SOCKET_WRAPPER_LIBRARY}:${NSS_WRAPPER_LIBRARY}:${UID_WRAPPER_LIBRARY}:${PAM_WRAPPER_LIBRARY}:${CHROOT_WRAPPER_LIBRARY}") list(APPEND TORTURE_ENVIRONMENT UID_WRAPPER=1 UID_WRAPPER_ROOT=1) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_PASSWD=${CMAKE_CURRENT_BINARY_DIR}/etc/passwd) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_SHADOW=${CMAKE_CURRENT_BINARY_DIR}/etc/shadow) list(APPEND TORTURE_ENVIRONMENT NSS_WRAPPER_GROUP=${CMAKE_CURRENT_BINARY_DIR}/etc/group) list(APPEND TORTURE_ENVIRONMENT PAM_WRAPPER_SERVICE_DIR=${CMAKE_CURRENT_BINARY_DIR}/etc/pam.d) # Give bob some keys file(COPY keys/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/id_ecdsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/id_ecdsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/id_ed25519 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/id_ed25519.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) # Allow to auth with bob's public keys on alice account configure_file(keys/id_rsa.pub ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys @ONLY) # append ECDSA public key file(READ keys/id_ecdsa.pub CONTENTS) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}") # append ed25519 public key file(READ keys/id_ed25519.pub CONTENTS) file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/home/alice/.ssh/authorized_keys "${CONTENTS}") # Copy the signed key to an alternative directory in bob's homedir. file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/certauth/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) file(COPY keys/certauth/id_rsa-cert.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}") endif () configure_file(tests_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/tests_config.h) if (WITH_BENCHMARKS) add_subdirectory(benchmarks) endif () if (CLIENT_TESTING) add_subdirectory(client) endif () if (WITH_SERVER AND SERVER_TESTING) add_subdirectory(pkd) add_subdirectory(server) endif () if (FUZZ_TESTING) add_subdirectory(fuzz) endif() ================================================ FILE: src/libssh/tests/authentication.c ================================================ /* This file is distributed in public domain. You can do whatever you want with its content. */ #include #include #include #include #include #include "tests.h" static int auth_kbdint(SSH_SESSION *session){ int err=ssh_userauth_kbdint(session,NULL,NULL); char *name,*instruction,*prompt,*ptr; char buffer[128]; int i,n; char echo; while (err==SSH_AUTH_INFO){ name=ssh_userauth_kbdint_getname(session); instruction=ssh_userauth_kbdint_getinstruction(session); n=ssh_userauth_kbdint_getnprompts(session); if(strlen(name)>0) printf("%s\n",name); if(strlen(instruction)>0) printf("%s\n",instruction); for(i=0;i&1`" echo "Ping latency to $DEST": ping -q -c 1 -n $DEST echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`" echo "ssh login latency :`(time -f user:%U ssh $DEST 'id > /dev/null') 2>&1`" ./generate.py | dd bs=4096 count=100000 | time ssh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1 ================================================ FILE: src/libssh/tests/benchmarks/bench2.sh ================================================ export CIPHER=aes128-cbc export DEST=localhost echo "Upload raw SSH statistics" echo "local machine: `uname -a`" echo "Cipher : $CIPHER ; Destination : $DEST (`ssh $DEST uname -a`)" echo "Local ssh version: `samplessh -V 2>&1`" echo "Ping latency to $DEST": ping -q -c 1 -n $DEST echo "Destination $DEST SSHD vesion : `echo | nc $DEST 22 | head -n1`" echo "ssh login latency :`(time -f user:%U samplessh $DEST 'id > /dev/null') 2>&1`" ./generate.py | dd bs=4096 count=100000 | strace samplessh -c $CIPHER $DEST "dd bs=4096 of=/dev/null" 2>&1 ================================================ FILE: src/libssh/tests/benchmarks/bench_raw.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "benchmarks.h" #include #include #include #define PYTHON_PATH "/usr/bin/python" const char python_eater[]= "#!/usr/bin/python\n" "import sys\n" "print 'go'\n" "sys.stdout.flush()\n" "toread=XXXXXXXXXX\n" "read=0\n" "while(read < toread):\n" " buffersize=toread-read\n" " if(buffersize > 4096):\n" " buffersize=4096\n" " r=len(sys.stdin.read(buffersize))\n" " read+=r\n" " if(r<=0):\n" " print 'error'\n" " exit()\n" "print 'done'\n"; static char *get_python_eater(unsigned long bytes){ char *eater=malloc(sizeof(python_eater)); char *ptr; char buf[12]; memcpy(eater,python_eater,sizeof(python_eater)); ptr=strstr(eater,"XXXXXXXXXX"); if(!ptr){ free(eater); return NULL; } sprintf(buf,"0x%.8lx",bytes); memcpy(ptr,buf,10); return eater; } /** @internal * @brief uploads a script (python or other) at a specific path on the * remote host * @param[in] session an active SSH session * @param[in] path to copy the file * @param[in] content of the file to copy * @return 0 on success, -1 on error */ static int upload_script(ssh_session session, const char *path, const char *script){ ssh_channel channel; char cmd[128]; int err; channel=ssh_channel_new(session); if(!channel) goto error; if(ssh_channel_open_session(channel) == SSH_ERROR) goto error; snprintf(cmd,sizeof(cmd),"cat > %s",path); if(ssh_channel_request_exec(channel,cmd) == SSH_ERROR) goto error; err=ssh_channel_write(channel,script,strlen(script)); if(err == SSH_ERROR) goto error; if(ssh_channel_send_eof(channel) == SSH_ERROR) goto error; if(ssh_channel_close(channel) == SSH_ERROR) goto error; ssh_channel_free(channel); return 0; error: fprintf(stderr,"Error while copying script : %s\n",ssh_get_error(session)); return -1; } /** @internal * @brief benchmarks a raw upload (simple upload in a SSH channel) using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_raw_up (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; char *script; char cmd[128]; int err; ssh_channel channel; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; bytes = args->datasize * 1024 * 1024; script =get_python_eater(bytes); err=upload_script(session,"/tmp/eater.py",script); free(script); if(err<0) return err; channel=ssh_channel_new(session); if(channel == NULL) goto error; if(ssh_channel_open_session(channel)==SSH_ERROR) goto error; snprintf(cmd,sizeof(cmd),"%s /tmp/eater.py", PYTHON_PATH); if(ssh_channel_request_exec(channel,cmd)==SSH_ERROR) goto error; if((err=ssh_channel_read(channel,buffer,sizeof(buffer)-1,0))==SSH_ERROR) goto error; buffer[err]=0; if(!strstr(buffer,"go")){ fprintf(stderr,"parse error : %s\n",buffer); ssh_channel_close(channel); ssh_channel_free(channel); return -1; } if(args->verbose>0) fprintf(stdout,"Starting upload of %lu bytes now\n",bytes); timestamp_init(&ts); while(total < bytes){ unsigned long towrite = bytes - total; int w; if(towrite > args->chunksize) towrite = args->chunksize; w=ssh_channel_write(channel,buffer,towrite); if(w == SSH_ERROR) goto error; total += w; } if(args->verbose>0) fprintf(stdout,"Finished upload, now waiting the ack\n"); if((err=ssh_channel_read(channel,buffer,5,0))==SSH_ERROR) goto error; buffer[err]=0; if(!strstr(buffer,"done")){ fprintf(stderr,"parse error : %s\n",buffer); ssh_channel_close(channel); ssh_channel_free(channel); return -1; } ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); ssh_channel_close(channel); ssh_channel_free(channel); return 0; error: fprintf(stderr,"Error during raw upload : %s\n",ssh_get_error(session)); if(channel){ ssh_channel_close(channel); ssh_channel_free(channel); } return -1; } const char python_giver[] = "#!/usr/bin/python\n" "import sys\n" "r=sys.stdin.read(2)\n" "towrite=XXXXXXXXXX\n" "wrote=0\n" "mtu = 32786\n" "buf = 'A'*mtu\n" "while(wrote < towrite):\n" " buffersize=towrite-wrote\n" " if(buffersize > mtu):\n" " buffersize=mtu\n" " if(buffersize == mtu):\n" " sys.stdout.write(buf)\n" " else:\n" " sys.stdout.write('A'*buffersize)\n" " wrote+=buffersize\n" "sys.stdout.flush()\n"; static char *get_python_giver(unsigned long bytes){ char *giver=malloc(sizeof(python_giver)); char *ptr; char buf[12]; memcpy(giver,python_giver,sizeof(python_giver)); ptr=strstr(giver,"XXXXXXXXXX"); if(!ptr){ free(giver); return NULL; } sprintf(buf,"0x%.8lx",bytes); memcpy(ptr,buf,10); return giver; } /** @internal * @brief benchmarks a raw download (simple upload in a SSH channel) using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_raw_down (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; char *script; char cmd[128]; int err; ssh_channel channel; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; bytes = args->datasize * 1024 * 1024; script =get_python_giver(bytes); err=upload_script(session,"/tmp/giver.py",script); free(script); if(err<0) return err; channel=ssh_channel_new(session); if(channel == NULL) goto error; if(ssh_channel_open_session(channel)==SSH_ERROR) goto error; snprintf(cmd,sizeof(cmd),"%s /tmp/giver.py", PYTHON_PATH); if(ssh_channel_request_exec(channel,cmd)==SSH_ERROR) goto error; if((err=ssh_channel_write(channel,"go",2))==SSH_ERROR) goto error; if(args->verbose>0) fprintf(stdout,"Starting download of %lu bytes now\n",bytes); timestamp_init(&ts); while(total < bytes){ unsigned long toread = bytes - total; int r; if(toread > args->chunksize) toread = args->chunksize; r=ssh_channel_read(channel,buffer,toread,0); if(r == SSH_ERROR) goto error; total += r; } if(args->verbose>0) fprintf(stdout,"Finished download\n"); ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"Download took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); ssh_channel_close(channel); ssh_channel_free(channel); return 0; error: fprintf(stderr,"Error during raw upload : %s\n",ssh_get_error(session)); if(channel){ ssh_channel_close(channel); ssh_channel_free(channel); } return -1; } ================================================ FILE: src/libssh/tests/benchmarks/bench_scp.c ================================================ /* bench_scp.c * * This file is part of the SSH Library * * Copyright (c) 2011 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "benchmarks.h" #include #include #define SCPDIR "/tmp/" #define SCPFILE "scpbenchmark" /** @internal * @brief benchmarks a scp upload using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_scp_up (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; ssh_scp scp; bytes = args->datasize * 1024 * 1024; scp = ssh_scp_new(session,SSH_SCP_WRITE,SCPDIR); if(scp == NULL) goto error; if(ssh_scp_init(scp)==SSH_ERROR) goto error; if(ssh_scp_push_file(scp,SCPFILE,bytes,0777) != SSH_OK) goto error; if(args->verbose>0) fprintf(stdout,"Starting upload of %lu bytes now\n",bytes); timestamp_init(&ts); while(total < bytes){ unsigned long towrite = bytes - total; int w; if(towrite > args->chunksize) towrite = args->chunksize; w=ssh_scp_write(scp,buffer,towrite); if(w == SSH_ERROR) goto error; total += towrite; } ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); ssh_scp_close(scp); ssh_scp_free(scp); return 0; error: fprintf(stderr,"Error during scp upload : %s\n",ssh_get_error(session)); if(scp){ ssh_scp_close(scp); ssh_scp_free(scp); } return -1; } /** @internal * @brief benchmarks a scp download using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_scp_down (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; ssh_scp scp; int r; size_t size; bytes = args->datasize * 1024 * 1024; scp = ssh_scp_new(session,SSH_SCP_READ,SCPDIR SCPFILE); if(scp == NULL) goto error; if(ssh_scp_init(scp)==SSH_ERROR) goto error; r=ssh_scp_pull_request(scp); if(r == SSH_SCP_REQUEST_NEWFILE){ size=ssh_scp_request_get_size(scp); if(bytes > size){ printf("Only %zd bytes available (on %lu requested).\n",size,bytes); bytes = size; } if(size > bytes){ printf("File is %zd bytes (on %lu requested). Will cut the end\n",size,bytes); } if(args->verbose>0) fprintf(stdout,"Starting download of %lu bytes now\n",bytes); timestamp_init(&ts); ssh_scp_accept_request(scp); while(total < bytes){ unsigned long toread = bytes - total; if(toread > args->chunksize) toread = args->chunksize; r=ssh_scp_read(scp,buffer,toread); if(r == SSH_ERROR || r == 0) goto error; total += r; } ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); } else { fprintf(stderr,"Expected SSH_SCP_REQUEST_NEWFILE, got %d\n",r); goto error; } ssh_scp_close(scp); ssh_scp_free(scp); return 0; error: fprintf(stderr,"Error during scp download : %s\n",ssh_get_error(session)); if(scp){ ssh_scp_close(scp); ssh_scp_free(scp); } return -1; } ================================================ FILE: src/libssh/tests/benchmarks/bench_sftp.c ================================================ /* bench_sftp.c * * This file is part of the SSH Library * * Copyright (c) 2011 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "benchmarks.h" #include #include #include #include #include #define SFTPDIR "/tmp/" #define SFTPFILE "scpbenchmark" /** @internal * @brief benchmarks a synchronous sftp upload using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; sftp_session sftp; sftp_file file = NULL; bytes = args->datasize * 1024 * 1024; sftp = sftp_new(session); if(sftp == NULL) goto error; if(sftp_init(sftp)==SSH_ERROR) goto error; file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDWR | O_CREAT | O_TRUNC, 0777); if(!file) goto error; if(args->verbose>0) fprintf(stdout,"Starting upload of %lu bytes now\n",bytes); timestamp_init(&ts); while(total < bytes){ unsigned long towrite = bytes - total; int w; if(towrite > args->chunksize) towrite = args->chunksize; w=sftp_write(file,buffer,towrite); if(w == SSH_ERROR) goto error; total += w; } sftp_close(file); ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); sftp_free(sftp); return 0; error: fprintf(stderr,"Error during scp upload : %s\n",ssh_get_error(session)); if(file) sftp_close(file); if(sftp) sftp_free(sftp); return -1; } /** @internal * @brief benchmarks a synchronous sftp download using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; sftp_session sftp; sftp_file file = NULL; int r; bytes = args->datasize * 1024 * 1024; sftp = sftp_new(session); if(sftp == NULL) goto error; if(sftp_init(sftp)==SSH_ERROR) goto error; file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDONLY,0); if(!file) goto error; if(args->verbose>0) fprintf(stdout,"Starting download of %lu bytes now\n",bytes); timestamp_init(&ts); while(total < bytes){ unsigned long toread = bytes - total; if(toread > args->chunksize) toread = args->chunksize; r=sftp_read(file,buffer,toread); if(r == SSH_ERROR) goto error; total += r; /* we had a smaller file */ if(r==0){ fprintf(stdout,"File smaller than expected : %lu (expected %lu).\n",total,bytes); bytes = total; break; } } sftp_close(file); ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); sftp_free(sftp); return 0; error: fprintf(stderr,"Error during sftp download : %s\n",ssh_get_error(session)); if(file) sftp_close(file); if(sftp) sftp_free(sftp); return -1; } /** @internal * @brief benchmarks an asynchronous sftp download using an * existing SSH session. * @param[in] session Open SSH session * @param[in] args Parsed command line arguments * @param[out] bps The calculated bytes per second obtained via benchmark. * @return 0 on success, -1 on error. */ int benchmarks_async_sftp_down (ssh_session session, struct argument_s *args, float *bps){ unsigned long bytes; struct timestamp_struct ts; float ms=0.0; unsigned long total=0; sftp_session sftp; sftp_file file = NULL; int r,i; int warned = 0; unsigned long toread; int *ids=NULL; int concurrent_downloads = args->concurrent_requests; bytes = args->datasize * 1024 * 1024; sftp = sftp_new(session); if(sftp == NULL) goto error; if(sftp_init(sftp)==SSH_ERROR) goto error; file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDONLY,0); if(!file) goto error; ids = malloc(concurrent_downloads * sizeof(int)); if(args->verbose>0) fprintf(stdout,"Starting download of %lu bytes now, using %d concurrent downloads\n",bytes, concurrent_downloads); timestamp_init(&ts); for (i=0;ichunksize); if(ids[i]==SSH_ERROR) goto error; } i=0; while(total < bytes){ r = sftp_async_read(file, buffer, args->chunksize, ids[i]); if(r == SSH_ERROR) goto error; total += r; if(r != (int)args->chunksize && total != bytes && !warned){ fprintf(stderr,"async_sftp_download : receiving short reads (%d, requested %d) " "the received file will be corrupted and shorted. Adapt chunksize to %d\n", r, args->chunksize,r); warned = 1; } /* we had a smaller file */ if(r==0){ fprintf(stdout,"File smaller than expected : %lu (expected %lu).\n",total,bytes); bytes = total; break; } toread = bytes - total; if(toread < args->chunksize * concurrent_downloads){ /* we've got enough launched downloads */ ids[i]=-1; } if(toread > args->chunksize) toread = args->chunksize; ids[i]=sftp_async_read_begin(file,toread); if(ids[i] == SSH_ERROR) goto error; i = (i+1) % concurrent_downloads; } sftp_close(file); ms=elapsed_time(&ts); *bps=8000 * (float)bytes / ms; if(args->verbose > 0) fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms, bytes,*bps); sftp_free(sftp); free(ids); return 0; error: fprintf(stderr,"Error during sftp download : %s\n",ssh_get_error(session)); if(file) sftp_close(file); if(sftp) sftp_free(sftp); free(ids); return -1; } ================================================ FILE: src/libssh/tests/benchmarks/benchmarks.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "benchmarks.h" #include #include #include #include struct benchmark benchmarks[]= { { .name="benchmark_raw_upload", .fct=benchmarks_raw_up, .enabled=0 }, { .name="benchmark_raw_download", .fct=benchmarks_raw_down, .enabled=0 }, { .name="benchmark_scp_upload", .fct=benchmarks_scp_up, .enabled=0 }, { .name="benchmark_scp_download", .fct=benchmarks_scp_down, .enabled=0 }, { .name="benchmark_sync_sftp_upload", .fct=benchmarks_sync_sftp_up, .enabled=0 }, { .name="benchmark_sync_sftp_download", .fct=benchmarks_sync_sftp_down, .enabled=0 }, { .name="benchmark_async_sftp_download", .fct=benchmarks_async_sftp_down, .enabled=0 } }; #ifdef HAVE_ARGP_H #include const char *argp_program_version = "libssh benchmarks 2011-08-28"; const char *argp_program_bug_address = "Aris Adamantiadis "; static char **cmdline; /* Program documentation. */ static char doc[] = "libssh benchmarks"; /* The options we understand. */ static struct argp_option options[] = { { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Make libssh benchmark more verbose", .group = 0 }, { .name = "raw-upload", .key = '1', .arg = NULL, .flags = 0, .doc = "Upload raw data using channel", .group = 0 }, { .name = "raw-download", .key = '2', .arg = NULL, .flags = 0, .doc = "Download raw data using channel", .group = 0 }, { .name = "scp-upload", .key = '3', .arg = NULL, .flags = 0, .doc = "Upload data using SCP", .group = 0 }, { .name = "scp-download", .key = '4', .arg = NULL, .flags = 0, .doc = "Download data using SCP", .group = 0 }, { .name = "sync-sftp-upload", .key = '5', .arg = NULL, .flags = 0, .doc = "Upload data using synchronous SFTP", .group = 0 }, { .name = "sync-sftp-download", .key = '6', .arg = NULL, .flags = 0, .doc = "Download data using synchronous SFTP (slow)", .group = 0 }, { .name = "async-sftp-download", .key = '7', .arg = NULL, .flags = 0, .doc = "Download data using asynchronous SFTP (fast)", .group = 0 }, { .name = "host", .key = 'h', .arg = "HOST", .flags = 0, .doc = "Add a host to connect for benchmark (format user@hostname)", .group = 0 }, { .name = "size", .key = 's', .arg = "MBYTES", .flags = 0, .doc = "MBytes of data to send/receive per test", .group = 0 }, { .name = "chunk", .key = 'c', .arg = "bytes", .flags = 0, .doc = "size of data chunks to send/receive", .group = 0 }, { .name = "prequests", .key = 'p', .arg = "number [20]", .flags = 0, .doc = "[async SFTP] number of concurrent requests", .group = 0 }, { .name = "cipher", .key = 'C', .arg = "cipher", .flags = 0, .doc = "Cryptographic cipher to be used", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ struct argument_s *arguments = state->input; /* arg is currently not used */ (void) arg; switch (key) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': benchmarks[key - '1'].enabled = 1; arguments->ntests ++; break; case 'v': arguments->verbose++; break; case 's': arguments->datasize = atoi(arg); break; case 'p': arguments->concurrent_requests = atoi(arg); break; case 'c': arguments->chunksize = atoi(arg); break; case 'C': arguments->cipher = arg; break; case 'h': if(arguments->nhosts >= MAX_HOSTS_CONNECT){ fprintf(stderr, "Too much hosts\n"); return ARGP_ERR_UNKNOWN; } arguments->hosts[arguments->nhosts]=arg; arguments->nhosts++; break; case ARGP_KEY_ARG: /* End processing here. */ cmdline = &state->argv [state->next - 1]; state->next = state->argc; break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ static void cmdline_parse(int argc, char **argv, struct argument_s *arguments) { /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ #ifdef HAVE_ARGP_H argp_parse(&argp, argc, argv, 0, 0, arguments); #else /* HAVE_ARGP_H */ (void) argc; (void) argv; arguments->hosts[0]="localhost"; arguments->nhosts=1; #endif /* HAVE_ARGP_H */ } static void arguments_init(struct argument_s *arguments){ memset(arguments,0,sizeof(*arguments)); arguments->chunksize=32758; arguments->concurrent_requests=20; arguments->datasize = 10; } static ssh_session connect_host(const char *host, int verbose, char *cipher){ ssh_session session=ssh_new(); if(session==NULL) goto error; if(ssh_options_set(session,SSH_OPTIONS_HOST, host)<0) goto error; ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbose); if(cipher != NULL){ if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) || ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher)){ goto error; } } ssh_options_parse_config(session, NULL); if(ssh_connect(session)==SSH_ERROR) goto error; if(ssh_userauth_autopubkey(session,NULL) != SSH_AUTH_SUCCESS) goto error; return session; error: fprintf(stderr,"Error connecting to \"%s\": %s\n",host,ssh_get_error(session)); ssh_free(session); return NULL; } static char *network_speed(float bps){ static char buf[128]; if(bps > 1000*1000*1000){ /* Gbps */ snprintf(buf,sizeof(buf),"%f Gbps",bps/(1000*1000*1000)); } else if(bps > 1000*1000){ /* Mbps */ snprintf(buf,sizeof(buf),"%f Mbps",bps/(1000*1000)); } else if(bps > 1000){ snprintf(buf,sizeof(buf),"%f Kbps",bps/1000); } else { snprintf(buf,sizeof(buf),"%f bps",bps); } return buf; } static void do_benchmarks(ssh_session session, struct argument_s *arguments, const char *hostname){ float ping_rtt=0.0; float ssh_rtt=0.0; float bps=0.0; int i; int err; struct benchmark *b; if(arguments->verbose>0) fprintf(stdout,"Testing ICMP RTT\n"); err=benchmarks_ping_latency(hostname, &ping_rtt); if(err == 0){ fprintf(stdout,"ping RTT : %f ms\n",ping_rtt); } err=benchmarks_ssh_latency(session, &ssh_rtt); if(err==0){ fprintf(stdout, "SSH RTT : %f ms. Theoretical max BW (win=128K) : %s\n",ssh_rtt,network_speed(128000.0/(ssh_rtt / 1000.0))); } for (i=0 ; ienabled){ err=b->fct(session,arguments,&bps); if(err==0){ fprintf(stdout, "%s : %s : %s\n",hostname, b->name, network_speed(bps)); } } } } char *buffer; int main(int argc, char **argv){ struct argument_s arguments; ssh_session session; int i; arguments_init(&arguments); cmdline_parse(argc, argv, &arguments); if (arguments.nhosts==0){ fprintf(stderr,"At least one host (-h) must be specified\n"); return EXIT_FAILURE; } if (arguments.ntests==0){ for(i=0; i < BENCHMARK_NUMBER ; ++i){ benchmarks[i].enabled=1; } arguments.ntests=BENCHMARK_NUMBER; } buffer=malloc(arguments.chunksize > 1024 ? arguments.chunksize : 1024); if(buffer == NULL){ fprintf(stderr,"Allocation of chunk buffer failed\n"); return EXIT_FAILURE; } if (arguments.verbose > 0){ fprintf(stdout, "Will try hosts "); for(i=0;i 0) fprintf(stdout,"Connecting to \"%s\"...\n",arguments.hosts[i]); session=connect_host(arguments.hosts[i], arguments.verbose, arguments.cipher); if(session != NULL && arguments.verbose > 0) fprintf(stdout,"Success\n"); if(session == NULL){ fprintf(stderr,"Errors occurred, stopping\n"); return EXIT_FAILURE; } do_benchmarks(session, &arguments, arguments.hosts[i]); ssh_disconnect(session); ssh_free(session); } return EXIT_SUCCESS; } ================================================ FILE: src/libssh/tests/benchmarks/benchmarks.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef BENCHMARKS_H_ #define BENCHMARKS_H_ #include /* benchmarks.c */ /* maximum number of parallel hosts that may be checked */ #define MAX_HOSTS_CONNECT 20 enum libssh_benchmarks { BENCHMARK_RAW_UPLOAD=0, BENCHMARK_RAW_DOWNLOAD, BENCHMARK_SCP_UPLOAD, BENCHMARK_SCP_DOWNLOAD, BENCHMARK_SYNC_SFTP_UPLOAD, BENCHMARK_SYNC_SFTP_DOWNLOAD, BENCHMARK_ASYNC_SFTP_DOWNLOAD, BENCHMARK_NUMBER }; struct argument_s { const char *hosts[MAX_HOSTS_CONNECT]; int verbose; int nhosts; int ntests; unsigned int datasize; unsigned int chunksize; int concurrent_requests; char *cipher; }; extern char *buffer; typedef int (*bench_fct)(ssh_session session, struct argument_s *args, float *bps); struct benchmark { const char *name; bench_fct fct; int enabled; }; /* latency.c */ struct timestamp_struct { struct timeval timestamp; }; int benchmarks_ping_latency (const char *host, float *average); int benchmarks_ssh_latency (ssh_session session, float *average); void timestamp_init(struct timestamp_struct *ts); float elapsed_time(struct timestamp_struct *ts); /* bench_raw.c */ int benchmarks_raw_up (ssh_session session, struct argument_s *args, float *bps); int benchmarks_raw_down (ssh_session session, struct argument_s *args, float *bps); /* bench_scp.c */ int benchmarks_scp_up (ssh_session session, struct argument_s *args, float *bps); int benchmarks_scp_down (ssh_session session, struct argument_s *args, float *bps); /* bench_sftp.c */ int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args, float *bps); int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args, float *bps); int benchmarks_async_sftp_down (ssh_session session, struct argument_s *args, float *bps); #endif /* BENCHMARKS_H_ */ ================================================ FILE: src/libssh/tests/benchmarks/latency.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "benchmarks.h" #include #include #include #include #include #include #define PING_PROGRAM "/bin/ping" /** @internal * @brief Calculates the RTT of the host with ICMP ping, and returns the * average of the calculated RTT. * @param[in] host hostname to ping. * @param[out] average average RTT in milliseconds. * @returns 0 on success, -1 if there is an error. * @warning relies on an external ping program which may not exist on * certain OS. */ int benchmarks_ping_latency (const char *host, float *average){ const char *ptr; char cmd[256]; char line[1024]; FILE *fd; int found=0; /* strip out the hostname */ ptr=strchr(host,'@'); if(ptr) ptr++; else ptr=host; snprintf(cmd,sizeof(cmd),"%s -n -q -c3 %s",PING_PROGRAM, ptr); fd=popen(cmd,"r"); if(fd==NULL){ fprintf(stderr,"Error executing command : %s\n", strerror(errno)); return -1; } while(!found && fgets(line,sizeof(line),fd)!=NULL){ if(strstr(line,"rtt")){ ptr=strchr(line,'='); if(ptr==NULL) goto parseerror; ptr=strchr(ptr,'/'); if(ptr==NULL) goto parseerror; *average=strtof(ptr+1,NULL); found=1; break; } } if(!found) goto parseerror; pclose(fd); return 0; parseerror: fprintf(stderr,"Parse error : couldn't locate average in %s",line); pclose(fd); return -1; } /** @internal * @brief initialize a timestamp to the current time. * @param[out] ts A timestamp_struct pointer. */ void timestamp_init(struct timestamp_struct *ts){ gettimeofday(&ts->timestamp,NULL); } /** @internal * @brief return the elapsed time since now and the moment ts was initialized. * @param[in] ts An initialized timestamp_struct pointer. * @return Elapsed time in milliseconds. */ float elapsed_time(struct timestamp_struct *ts){ struct timeval now; time_t secdiff; long usecdiff; /* may be negative */ gettimeofday(&now,NULL); secdiff=now.tv_sec - ts->timestamp.tv_sec; usecdiff=now.tv_usec - ts->timestamp.tv_usec; //printf("%d sec diff, %d usec diff\n",secdiff, usecdiff); return (float) (secdiff*1000) + ((float)usecdiff)/1000; } /** @internal * @brief Calculates the RTT of the host with SSH channel operations, and * returns the average of the calculated RTT. * @param[in] session active SSH session to test. * @param[out] average average RTT in milliseconds. * @returns 0 on success, -1 if there is an error. */ int benchmarks_ssh_latency(ssh_session session, float *average){ float times[3]; struct timestamp_struct ts; int i; ssh_channel channel; channel=ssh_channel_new(session); if(channel==NULL) goto error; if(ssh_channel_open_session(channel)==SSH_ERROR) goto error; for(i=0;i<3;++i){ timestamp_init(&ts); if(ssh_channel_request_env(channel,"TEST","test")==SSH_ERROR && ssh_get_error_code(session)==SSH_FATAL) goto error; times[i]=elapsed_time(&ts); } ssh_channel_close(channel); ssh_channel_free(channel); channel=NULL; printf("SSH request times : %f ms ; %f ms ; %f ms\n", times[0], times[1], times[2]); *average=(times[0]+times[1]+times[2])/3; return 0; error: fprintf(stderr,"Error calculating SSH latency : %s\n",ssh_get_error(session)); if(channel) ssh_channel_free(channel); return -1; } ================================================ FILE: src/libssh/tests/chmodtest.c ================================================ #include #include #include "examples_common.h" #include int main(void) { ssh_session session; sftp_session sftp; char buffer[1024*1024]; int rc; session = connect_ssh("localhost", NULL, 0); if (session == NULL) { return 1; } sftp=sftp_new(session); sftp_init(sftp); rc=sftp_rename(sftp,"/tmp/test","/tmp/test"); rc=sftp_rename(sftp,"/tmp/test","/tmp/test"); rc=sftp_chmod(sftp,"/tmp/test",0644); if (rc < 0) { printf("error : %s\n",ssh_get_error(sftp)); ssh_disconnect(session); return 1; } ssh_disconnect(session); return 0; } ================================================ FILE: src/libssh/tests/chroot_wrapper.c ================================================ /* silent gcc */ int chroot(const char *); int chroot(const char *path) { (void)path; return 0; } ================================================ FILE: src/libssh/tests/client/CMakeLists.txt ================================================ project(clienttests C) find_package(socket_wrapper) set(LIBSSH_CLIENT_TESTS torture_algorithms torture_client_config torture_connect torture_hostkey torture_auth torture_rekey torture_forward torture_knownhosts torture_knownhosts_verify torture_proxycommand torture_session torture_request_env torture_client_global_requests) find_program(SCP_EXECUTABLE NAMES scp) if (SCP_EXECUTABLE) set(LIBSSH_CLIENT_TESTS ${LIBSSH_CLIENT_TESTS} torture_scp) endif() if (DEFAULT_C_NO_DEPRECATION_FLAGS) set_source_files_properties(torture_knownhosts.c PROPERTIES COMPILE_FLAGS ${DEFAULT_C_NO_DEPRECATION_FLAGS}) endif() if (WITH_SFTP) if (WITH_BENCHMARKS) set(SFTP_BENCHMARK_TESTS torture_sftp_benchmark) endif() set(LIBSSH_CLIENT_TESTS ${LIBSSH_CLIENT_TESTS} torture_sftp_ext torture_sftp_canonicalize_path torture_sftp_dir torture_sftp_read torture_sftp_fsync ${SFTP_BENCHMARK_TESTS}) endif (WITH_SFTP) foreach(_CLI_TEST ${LIBSSH_CLIENT_TESTS}) add_cmocka_test(${_CLI_TEST} SOURCES ${_CLI_TEST}.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TORTURE_LIBRARY} ) if (OSX) set_property( TEST ${_CLI_TEST} PROPERTY ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${SOCKET_WRAPPER_LIBRARY}) else () set_property( TEST ${_CLI_TEST} PROPERTY ENVIRONMENT ${TORTURE_ENVIRONMENT}) endif() endforeach() ================================================ FILE: src/libssh/tests/client/torture_algorithms.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool false_v = false; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); /* Prevent parsing configuration files that can introduce different * algorithms then we want to test */ ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &false_v); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void test_algorithm(ssh_session session, const char *kex, const char *cipher, const char *hmac) { int rc; char data[256]; size_t len_to_test[] = { 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 15, 16, 20, 31, 32, 33, 63, 64, 65, 100, 127, 128 }; unsigned int i; if (kex != NULL) { rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, kex); assert_ssh_return_code(session, rc); } if (cipher != NULL) { rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher); assert_ssh_return_code(session, rc); } if (hmac != NULL) { rc = ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, hmac); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, hmac); assert_ssh_return_code(session, rc); } rc = ssh_connect(session); assert_ssh_return_code(session, rc); /* send ignore packets of all sizes */ memset(data, 0, sizeof(data)); for (i = 0; i < (sizeof(len_to_test) / sizeof(size_t)); i++) { memset(data, 'A', len_to_test[i]); ssh_send_ignore(session, data); ssh_handle_packets(session, 50); } rc = ssh_userauth_none(session, NULL); if (rc != SSH_OK) { rc = ssh_get_error_code(session); assert_int_equal(rc, SSH_REQUEST_DENIED); } ssh_disconnect(session); } static void torture_algorithms_aes128_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha1"); } static void torture_algorithms_aes128_cbc_hmac_sha2_256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha2-256"); } static void torture_algorithms_aes128_cbc_hmac_sha2_512(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha2-512"); } static void torture_algorithms_aes128_cbc_hmac_sha1_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes128_cbc_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes128_cbc_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-cbc", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes192_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha1"); } static void torture_algorithms_aes192_cbc_hmac_sha2_256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha2-256"); } static void torture_algorithms_aes192_cbc_hmac_sha2_512(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha2-512"); } static void torture_algorithms_aes192_cbc_hmac_sha1_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes192_cbc_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes192_cbc_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-cbc", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes256_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha1"); } static void torture_algorithms_aes256_cbc_hmac_sha2_256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha2-256"); } static void torture_algorithms_aes256_cbc_hmac_sha2_512(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha2-512"); } static void torture_algorithms_aes256_cbc_hmac_sha1_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes256_cbc_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes256_cbc_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-cbc", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes128_ctr_hmac_sha1(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha1"); } static void torture_algorithms_aes128_ctr_hmac_sha2_256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha2-256"); } static void torture_algorithms_aes128_ctr_hmac_sha2_512(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha2-512"); } static void torture_algorithms_aes128_ctr_hmac_sha1_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes128_ctr_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes128_ctr_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-ctr", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes192_ctr_hmac_sha1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha1"); } static void torture_algorithms_aes192_ctr_hmac_sha2_256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha2-256"); } static void torture_algorithms_aes192_ctr_hmac_sha2_512(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha2-512"); } static void torture_algorithms_aes192_ctr_hmac_sha1_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes192_ctr_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes192_ctr_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "aes192-ctr", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes256_ctr_hmac_sha1(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha1"); } static void torture_algorithms_aes256_ctr_hmac_sha2_256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha2-256"); } static void torture_algorithms_aes256_ctr_hmac_sha2_512(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha2-512"); } static void torture_algorithms_aes256_ctr_hmac_sha1_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_aes256_ctr_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_aes256_ctr_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-ctr", "hmac-sha2-512-etm@openssh.com"); } static void torture_algorithms_aes128_gcm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes128-gcm@openssh.com", NULL); } static void torture_algorithms_aes256_gcm(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, NULL/*kex*/, "aes256-gcm@openssh.com", NULL); } static void torture_algorithms_3des_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha1"); } static void torture_algorithms_3des_cbc_hmac_sha2_256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-256"); } static void torture_algorithms_3des_cbc_hmac_sha2_512(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-512"); } static void torture_algorithms_3des_cbc_hmac_sha1_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_3des_cbc_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_3des_cbc_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "3des-cbc", "hmac-sha2-512-etm@openssh.com"); } #if defined(WITH_BLOWFISH_CIPHER) && defined(OPENSSH_BLOWFISH_CBC) static void torture_algorithms_blowfish_cbc_hmac_sha1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha1"); } static void torture_algorithms_blowfish_cbc_hmac_sha2_256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-256"); } static void torture_algorithms_blowfish_cbc_hmac_sha2_512(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-512"); } static void torture_algorithms_blowfish_cbc_hmac_sha1_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha1-etm@openssh.com"); } static void torture_algorithms_blowfish_cbc_hmac_sha2_256_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-256-etm@openssh.com"); } static void torture_algorithms_blowfish_cbc_hmac_sha2_512_etm(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL/*kex*/, "blowfish-cbc", "hmac-sha2-512-etm@openssh.com"); } #endif /* WITH_BLOWFISH_CIPHER */ #ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM static void torture_algorithms_chacha20_poly1305(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, NULL, /*kex*/ "chacha20-poly1305@openssh.com", NULL); } #endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ static void torture_algorithms_zlib(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib"); #ifdef WITH_ZLIB assert_int_equal(rc, SSH_OK); #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib"); #ifdef WITH_ZLIB assert_int_equal(rc, SSH_OK); #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_connect(session); #ifdef WITH_ZLIB if (ssh_get_openssh_version(session)) { assert_false(rc == SSH_OK); ssh_disconnect(session); return; } #endif assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session, NULL); if (rc != SSH_OK) { rc = ssh_get_error_code(session); assert_int_equal(rc, SSH_REQUEST_DENIED); } ssh_disconnect(session); } static void torture_algorithms_zlib_openssh(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib@openssh.com"); #ifdef WITH_ZLIB assert_int_equal(rc, SSH_OK); #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib@openssh.com"); #ifdef WITH_ZLIB assert_int_equal(rc, SSH_OK); #else assert_int_equal(rc, SSH_ERROR); #endif rc = ssh_connect(session); #ifdef WITH_ZLIB if (ssh_get_openssh_version(session)) { assert_true(rc==SSH_OK); rc = ssh_userauth_none(session, NULL); if (rc != SSH_OK) { rc = ssh_get_error_code(session); assert_int_equal(rc, SSH_REQUEST_DENIED); } ssh_disconnect(session); return; } assert_false(rc == SSH_OK); #else assert_int_equal(rc, SSH_OK); #endif ssh_disconnect(session); } #if defined(HAVE_ECC) static void torture_algorithms_ecdh_sha2_nistp256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "ecdh-sha2-nistp256", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_ecdh_sha2_nistp384(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "ecdh-sha2-nistp384", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_ecdh_sha2_nistp521(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "ecdh-sha2-nistp521", NULL/*cipher*/, NULL/*hmac*/); } #endif #ifdef OPENSSH_CURVE25519_SHA256 static void torture_algorithms_ecdh_curve25519_sha256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "curve25519-sha256", NULL/*cipher*/, NULL/*hmac*/); } #endif /* OPENSSH_CURVE25519_SHA256 */ #ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG static void torture_algorithms_ecdh_curve25519_sha256_libssh_org(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "curve25519-sha256@libssh.org", NULL/*cipher*/, NULL/*hmac*/); } #endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */ static void torture_algorithms_dh_group1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "diffie-hellman-group1-sha1", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_dh_group14(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "diffie-hellman-group14-sha1", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_dh_group14_sha256(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "diffie-hellman-group14-sha256", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_dh_group16(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "diffie-hellman-group16-sha512", NULL/*cipher*/, NULL/*hmac*/); } static void torture_algorithms_dh_group18(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "diffie-hellman-group18-sha512", NULL/*cipher*/, NULL/*hmac*/); } #ifdef WITH_GEX static void torture_algorithms_dh_gex_sha1(void **state) { struct torture_state *s = *state; if (ssh_fips_mode()) { skip(); } test_algorithm(s->ssh.session, "diffie-hellman-group-exchange-sha1", NULL, /* cipher */ NULL); /* hmac */ } static void torture_algorithms_dh_gex_sha256(void **state) { struct torture_state *s = *state; test_algorithm(s->ssh.session, "diffie-hellman-group-exchange-sha256", NULL, /* cipher */ NULL); /* hmac */ } #endif /* WITH_GEX */ int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_cbc_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_cbc_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_cbc_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_ctr_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes192_ctr_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_ctr_hmac_sha2_512_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes128_gcm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_aes256_gcm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_3des_cbc_hmac_sha2_512_etm, session_setup, session_teardown), #if defined(WITH_BLOWFISH_CIPHER) && defined(OPENSSH_BLOWFISH_CBC) cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha1_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_256_etm, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_blowfish_cbc_hmac_sha2_512_etm, session_setup, session_teardown), #endif /* WITH_BLOWFISH_CIPHER */ #ifdef OPENSSH_CHACHA20_POLY1305_OPENSSH_COM cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305, session_setup, session_teardown), #endif /* OPENSSH_CHACHA20_POLY1305_OPENSSH_COM */ cmocka_unit_test_setup_teardown(torture_algorithms_zlib, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_zlib_openssh, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_group1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_group14_sha256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_group16, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_group18, session_setup, session_teardown), #ifdef WITH_GEX cmocka_unit_test_setup_teardown(torture_algorithms_dh_gex_sha1, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_dh_gex_sha256, session_setup, session_teardown), #endif /* WITH_GEX */ #ifdef OPENSSH_CURVE25519_SHA256 cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256, session_setup, session_teardown), #endif /* OPENSSH_CURVE25519_SHA256 */ #ifdef OPENSSH_CURVE25519_SHA256_LIBSSH_ORG cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_curve25519_sha256_libssh_org, session_setup, session_teardown), #endif /* OPENSSH_CURVE25519_SHA256_LIBSSH_ORG */ #if defined(HAVE_ECC) cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp384, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_algorithms_ecdh_sha2_nistp521, session_setup, session_teardown), #endif }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_auth.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include #include #include /* agent_is_running */ #include "agent.c" static int sshd_setup(void **state) { torture_setup_sshd_server(state, true); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); const char *all_keytypes = NULL; struct passwd *pwd; bool b = false; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); /* Enable all hostkeys */ all_keytypes = ssh_kex_get_supported_method(SSH_HOSTKEYS); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, all_keytypes); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static int pubkey_setup(void **state) { int rc; rc = session_setup(state); if (rc != 0) { return rc; } /* Make sure we do not interfere with another ssh-agent */ unsetenv("SSH_AUTH_SOCK"); unsetenv("SSH_AGENT_PID"); return 0; } static int agent_setup(void **state) { struct torture_state *s = *state; char ssh_agent_cmd[4096]; char ssh_agent_sock[1024]; char ssh_agent_pidfile[1024]; char bob_ssh_key[1024]; struct passwd *pwd; int rc; rc = pubkey_setup(state); if (rc != 0) { return rc; } pwd = getpwnam("bob"); assert_non_null(pwd); snprintf(ssh_agent_sock, sizeof(ssh_agent_sock), "%s/agent.sock", s->socket_dir); snprintf(ssh_agent_pidfile, sizeof(ssh_agent_pidfile), "%s/agent.pid", s->socket_dir); /* Production ready code!!! */ snprintf(ssh_agent_cmd, sizeof(ssh_agent_cmd), "eval `ssh-agent -a %s`; echo $SSH_AGENT_PID > %s", ssh_agent_sock, ssh_agent_pidfile); /* run ssh-agent and ssh-add as the normal user */ unsetenv("UID_WRAPPER_ROOT"); rc = system(ssh_agent_cmd); assert_return_code(rc, errno); setenv("SSH_AUTH_SOCK", ssh_agent_sock, 1); setenv("TORTURE_SSH_AGENT_PIDFILE", ssh_agent_pidfile, 1); snprintf(bob_ssh_key, sizeof(bob_ssh_key), "ssh-add %s/.ssh/id_rsa", pwd->pw_dir); rc = system(bob_ssh_key); assert_return_code(rc, errno); return 0; } static int agent_cert_setup(void **state) { char bob_alt_ssh_key[1024]; struct passwd *pwd; int rc; rc = agent_setup(state); if (rc != 0) { return rc; } pwd = getpwnam("bob"); assert_non_null(pwd); /* remove all keys, load alternative key + cert */ snprintf(bob_alt_ssh_key, sizeof(bob_alt_ssh_key), "ssh-add -D && ssh-add %s/.ssh_cert/id_rsa", pwd->pw_dir); rc = system(bob_alt_ssh_key); assert_return_code(rc, errno); return 0; } static int agent_teardown(void **state) { const char *ssh_agent_pidfile; int rc; rc = session_teardown(state); if (rc != 0) { return rc; } ssh_agent_pidfile = getenv("TORTURE_SSH_AGENT_PIDFILE"); assert_non_null(ssh_agent_pidfile); /* kill agent pid */ torture_terminate_process(ssh_agent_pidfile); unlink(ssh_agent_pidfile); unsetenv("TORTURE_SSH_AGENT_PIDFILE"); unsetenv("SSH_AUTH_SOCK"); return 0; } static void torture_auth_none(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); assert_int_equal(rc, SSH_AUTH_DENIED); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } } static void torture_auth_none_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } ssh_set_blocking(session,0); do { rc = ssh_userauth_none(session,NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_DENIED); assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } static void torture_auth_autopubkey(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; /* Authenticate as alice with bob his pubkey */ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_autopubkey_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); ssh_set_blocking(session,0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); do { rc = ssh_userauth_publickey_auto(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_kbdint(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE); rc = ssh_userauth_kbdint(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1); rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD); assert_false(rc < 0); rc = ssh_userauth_kbdint(session, NULL, NULL); /* Sometimes, SSH server send an empty query at the end of exchange */ if(rc == SSH_AUTH_INFO) { assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0); rc = ssh_userauth_kbdint(session, NULL, NULL); } assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_kbdint_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); ssh_set_blocking(session,0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE); do { rc = ssh_userauth_kbdint(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1); rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD); assert_false(rc < 0); do { rc = ssh_userauth_kbdint(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); /* Sometimes, SSH server send an empty query at the end of exchange */ if(rc == SSH_AUTH_INFO) { assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0); do { rc = ssh_userauth_kbdint(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); } assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_password(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_AUTH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PASSWORD); rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_password_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); ssh_set_blocking(session,0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_AUTH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PASSWORD); do { rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD); } while(rc==SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_agent(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; if (!ssh_agent_is_running(session)){ print_message("*** Agent not running. Test ignored\n"); return; } rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_agent(session, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_agent_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; if (!ssh_agent_is_running(session)){ print_message("*** Agent not running. Test ignored\n"); return; } rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); ssh_set_blocking(session,0); do { rc = ssh_userauth_agent(session, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_cert(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_key privkey = NULL; ssh_key cert = NULL; char bob_ssh_key[1024]; char bob_ssh_cert[2048]; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); snprintf(bob_ssh_key, sizeof(bob_ssh_key), "%s/.ssh_cert/id_rsa", pwd->pw_dir); snprintf(bob_ssh_cert, sizeof(bob_ssh_cert), "%s-cert.pub", bob_ssh_key); /* cert has been signed for login as alice */ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); assert_int_equal(rc, SSH_OK); rc = ssh_pki_import_cert_file(bob_ssh_cert, &cert); assert_int_equal(rc, SSH_OK); rc = ssh_pki_copy_cert_to_privkey(cert, privkey); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_try_publickey(session, NULL, cert); assert_int_equal(rc, SSH_AUTH_SUCCESS); rc = ssh_userauth_publickey(session, NULL, privkey); assert_int_equal(rc, SSH_AUTH_SUCCESS); SSH_KEY_FREE(privkey); SSH_KEY_FREE(cert); } static void torture_auth_agent_cert(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; /* Skip this test if in FIPS mode. * * OpenSSH agent has a bug which makes it to not use SHA2 in signatures when * using certificates. It always uses SHA1. * * This should be removed as soon as OpenSSH agent bug is fixed. * (see https://gitlab.com/libssh/libssh-mirror/merge_requests/34) */ if (ssh_fips_mode()) { skip(); } else { /* After the bug is solved, this also should be removed */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-rsa-cert-v01@openssh.com"); assert_int_equal(rc, SSH_OK); } /* Setup loads a different key, tests are exactly the same. */ torture_auth_agent(state); } static void torture_auth_agent_cert_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; /* Skip this test if in FIPS mode. * * OpenSSH agent has a bug which makes it to not use SHA2 in signatures when * using certificates. It always uses SHA1. * * This should be removed as soon as OpenSSH agent bug is fixed. * (see https://gitlab.com/libssh/libssh-mirror/merge_requests/34) */ if (ssh_fips_mode()) { skip(); } else { /* After the bug is solved, this also should be removed */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-rsa-cert-v01@openssh.com"); assert_int_equal(rc, SSH_OK); } torture_auth_agent_nonblocking(state); } static void torture_auth_pubkey_types(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* Disable RSA key types for authentication */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp384"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_DENIED); /* Now enable it and retry */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "rsa-sha2-512,ssh-rsa"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_pubkey_types_ecdsa(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* We have only the 256b key -- whitelisting only larger should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp384"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_DENIED); /* Verify we can use also ECDSA keys with their various names */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp256"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_pubkey_types_ed25519(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char bob_ssh_key[1024]; ssh_key privkey = NULL; struct passwd *pwd; int rc; if (ssh_fips_mode()) { skip(); } pwd = getpwnam("bob"); assert_non_null(pwd); snprintf(bob_ssh_key, sizeof(bob_ssh_key), "%s/.ssh/id_ed25519", pwd->pw_dir); rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* Import the ED25519 private key */ rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); assert_int_equal(rc, SSH_OK); /* Enable only RSA keys -- authentication should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-rsa"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey(session, NULL, privkey); assert_int_equal(rc, SSH_AUTH_DENIED); /* Verify we can use also ed25519 keys */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-ed25519"); assert_ssh_return_code(session, rc); rc = ssh_userauth_publickey(session, NULL, privkey); assert_int_equal(rc, SSH_AUTH_SUCCESS); SSH_KEY_FREE(privkey); } static void torture_auth_pubkey_types_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_set_blocking(session, 0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* Disable RSA key types for authentication */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey_auto(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_DENIED); /* Now enable it and retry */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "rsa-sha2-512,ssh-rsa"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey_auto(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_pubkey_types_ecdsa_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_set_blocking(session, 0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* We have only the 256b key -- whitelisting only larger should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp384"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey_auto(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_DENIED); /* Verify we can use also ECDSA key to authenticate */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ecdsa-sha2-nistp256"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey_auto(session, NULL, NULL); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_auth_pubkey_types_ed25519_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char bob_ssh_key[1024]; ssh_key privkey = NULL; struct passwd *pwd; int rc; if (ssh_fips_mode()) { skip(); } pwd = getpwnam("bob"); assert_non_null(pwd); snprintf(bob_ssh_key, sizeof(bob_ssh_key), "%s/.ssh/id_ed25519", pwd->pw_dir); rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_set_blocking(session, 0); do { rc = ssh_userauth_none(session, NULL); } while (rc == SSH_AUTH_AGAIN); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); /* Import the ED25519 private key */ rc = ssh_pki_import_privkey_file(bob_ssh_key, NULL, NULL, NULL, &privkey); assert_int_equal(rc, SSH_OK); /* Enable only RSA keys -- authentication should fail */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-rsa"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey(session, NULL, privkey); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_DENIED); /* Verify we can use also ED25519 key to authenticate */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-ed25519"); assert_ssh_return_code(session, rc); do { rc = ssh_userauth_publickey(session, NULL, privkey); } while (rc == SSH_AUTH_AGAIN); assert_int_equal(rc, SSH_AUTH_SUCCESS); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_auth_none, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_none_nonblocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_password, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_password_nonblocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_kbdint, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_kbdint_nonblocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_autopubkey, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_autopubkey_nonblocking, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_agent, agent_setup, agent_teardown), cmocka_unit_test_setup_teardown(torture_auth_agent_nonblocking, agent_setup, agent_teardown), cmocka_unit_test_setup_teardown(torture_auth_cert, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_agent_cert, agent_cert_setup, agent_teardown), cmocka_unit_test_setup_teardown(torture_auth_agent_cert_nonblocking, agent_cert_setup, agent_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_nonblocking, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ecdsa_nonblocking, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519, pubkey_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_auth_pubkey_types_ed25519_nonblocking, pubkey_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_client_config.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include "torture.h" #include "libssh/session.h" #include "libssh/misc.h" #define LIBSSH_SSH_CONFIG "libssh_config" #define TORTURE_CONFIG_USER "test-user" #define CIPHERS "aes256-gcm@openssh.com,chacha20-poly1305@openssh.com" #define CIPHERS2 "aes256-cbc,aes128-ctr" static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int setup_config_files(void **state) { struct torture_state *s = *state; int verbosity; struct passwd *pwd; char *filename = NULL; int rc; /* Work under the bob's UID to be able to load his configuration file */ pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); filename = ssh_path_expand_tilde("~/.ssh/config"); torture_write_file(filename, "Ciphers "CIPHERS"\nTestBogus1\nUser "TORTURE_CONFIG_USER); free(filename); torture_write_file(LIBSSH_SSH_CONFIG, "Ciphers "CIPHERS2"\nTestBogus2\n"); verbosity = torture_libssh_verbosity(); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); return 0; } static int teardown(void **state) { struct torture_state *s = *state; char *filename; filename = ssh_path_expand_tilde("~/.ssh/config"); if (filename != NULL) { if (strlen(filename) > 0) { unlink(filename); } SAFE_FREE(filename); } unlink(LIBSSH_SSH_CONFIG); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } /* This tests makes sure that parsing both system-wide and per-user * configuration files retains OpenSSH semantics (the per-user overrides * the system-wide values). * This function ssh_options_parse_config() has hardcoded path to the * system-wide configuration file so this might not test anything at all * if this system-wide file does not overwrite this option. */ static void torture_client_config_system(void **state) { struct torture_state *s = *state; int ret = 0; char *fips_ciphers = NULL; if (ssh_fips_mode()) { fips_ciphers = ssh_keep_fips_algos(SSH_CRYPT_C_S, CIPHERS); assert_non_null(fips_ciphers); } /* The first tests assumes there is system-wide configuration file * setting Ciphers to some non-default value. We do not have any control * of that in this test case. */ ret = ssh_options_parse_config(s->ssh.session, NULL); assert_ssh_return_code(s->ssh.session, ret); assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S]); assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], fips_ciphers); assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], CIPHERS); assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], CIPHERS); } /* Make sure the configuration was processed and user modified */ assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER); SAFE_FREE(fips_ciphers); } /* This tests makes sure that parsing both system-wide and per-user * configuration files retains OpenSSH semantics (the per-user overrides * the system-wide values). * The function ssh_options_parse_config() has hardcoded path to the * system-wide configuraion file so we try to emmulate the behavior by parsing * the files separately in the same order. */ static void torture_client_config_emulate(void **state) { struct torture_state *s = *state; char *filename = NULL; int ret = 0; char *fips_ciphers = NULL; if (ssh_fips_mode()) { fips_ciphers = ssh_keep_fips_algos(SSH_CRYPT_C_S, CIPHERS); assert_non_null(fips_ciphers); } /* The first tests assumes there is system-wide configuration file * setting Ciphers to some non-default value. We do not have any control * of that in this test case */ filename = ssh_path_expand_tilde("~/.ssh/config"); ret = ssh_options_parse_config(s->ssh.session, filename); free(filename); assert_ssh_return_code(s->ssh.session, ret); ret = ssh_options_parse_config(s->ssh.session, LIBSSH_SSH_CONFIG); assert_ssh_return_code(s->ssh.session, ret); assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S]); assert_non_null(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], fips_ciphers); assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_C_S], CIPHERS); assert_string_equal(s->ssh.session->opts.wanted_methods[SSH_CRYPT_S_C], CIPHERS); } /* Make sure the configuration was processed and user modified */ assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER); SAFE_FREE(fips_ciphers); } /* This verifies that configuration files are parsed by default. */ static void torture_client_config_autoparse(void **state) { struct torture_state *s = *state; int ret = 0; ret = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, ret); /* Make sure the configuration was processed and user modified */ assert_string_equal(s->ssh.session->opts.username, TORTURE_CONFIG_USER); } /* This verifies that we are able to suppress parsing of the configuration files * on connect using an option. */ static void torture_client_config_suppress(void **state) { struct torture_state *s = *state; bool b = false; int ret = 0; ret = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, ret); ret = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, ret); /* Make sure the configuration was not processed and user modified */ assert_string_equal(s->ssh.session->opts.username, "bob"); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_client_config_system, setup_config_files, teardown), cmocka_unit_test_setup_teardown(torture_client_config_emulate, setup_config_files, teardown), cmocka_unit_test_setup_teardown(torture_client_config_autoparse, setup_config_files, teardown), cmocka_unit_test_setup_teardown(torture_client_config_suppress, setup_config_files, teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_client_global_requests.c ================================================ /* * torture_client_global_requests.c - Tests for client global requests * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/channels.h" #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, true); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool b = false; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static int authenticate(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD); assert_int_equal(rc, SSH_AUTH_SUCCESS); return rc; } static void torture_unknown_request(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_channel channel; int rc; rc = authenticate(state); assert_ssh_return_code(session, rc); /* Request asking for reply */ rc = ssh_global_request(session, "unknown-request-00@test.com", NULL, 1); assert_ssh_return_code_equal(session, rc, SSH_ERROR); /* Request and don't ask for reply */ rc = ssh_global_request(session, "another-bad-req-00@test.com", NULL, 0); assert_ssh_return_code(session, rc); /* Open channel to make sure the session is still working */ channel = ssh_channel_new(session); assert_non_null(channel); rc = ssh_channel_open_session(channel); assert_ssh_return_code(session, rc); ssh_channel_close(channel); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_unknown_request, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_connect.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #include #include #include #include #include #include /* Should work until Apnic decides to assign it :) */ #define BLACKHOLE "1.1.1.1" static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, BLACKHOLE); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_connect_nonblocking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); ssh_set_blocking(session,0); do { rc = ssh_connect(session); assert_ssh_return_code_not_equal(session, rc, SSH_ERROR); } while(rc == SSH_AGAIN); assert_ssh_return_code(session, rc); } #if 0 /* This does not work with socket_wrapper */ static void torture_connect_timeout(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; struct timeval before, after; int rc; long timeout = 2; time_t sec; suseconds_t usec; rc = ssh_options_set(session, SSH_OPTIONS_HOST, BLACKHOLE); assert_true(rc == SSH_OK); rc = ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &timeout); assert_true(rc == SSH_OK); rc = gettimeofday(&before, NULL); assert_true(rc == 0); rc = ssh_connect(session); assert_true(rc == SSH_ERROR); rc = gettimeofday(&after, NULL); assert_true(rc == 0); sec = after.tv_sec - before.tv_sec; usec = after.tv_usec - before.tv_usec; /* Borrow a second for the missing usecs, but don't bother calculating */ if (usec < 0) sec--; assert_in_range(sec, 1, 3); } #endif static void torture_connect_double(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } static void torture_connect_failure(void **state) { /* * The intent of this test is to check that a fresh * ssh_new/ssh_disconnect/ssh_free sequence doesn't crash/leak * and the behavior of a double ssh_disconnect */ struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_disconnect(session); } static void torture_connect_socket(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; int sock_fd = 0; struct sockaddr_in server_addr = { .sin_family = AF_INET, .sin_port = htons(22), .sin_addr.s_addr = inet_addr(TORTURE_SSH_SERVER), }; sock_fd = socket(AF_INET, SOCK_STREAM, 0); assert_true(sock_fd > 2); rc = connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); assert_return_code(rc, errno); ssh_options_set(session, SSH_OPTIONS_FD, &sock_fd); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } static void torture_connect_uninitialized(UNUSED_PARAM(void **state)) { int rc; ssh_session session; struct passwd *pwd; /* Make sure the library is unitialized */ while (is_ssh_initialized()) { rc = ssh_finalize(); assert_return_code(rc, errno); } pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); session = ssh_new(); assert_non_null(session); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); /* Expect error from ssh_connect */ rc = ssh_connect(session); assert_false(rc == SSH_OK); assert_string_equal(ssh_get_error(session), "Library not initialized."); ssh_free(session); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_connect_nonblocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_connect_double, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_connect_failure, session_setup, session_teardown), #if 0 cmocka_unit_test_setup_teardown(torture_connect_timeout, session_setup, session_teardown), #endif cmocka_unit_test_setup_teardown(torture_connect_socket, session_setup, session_teardown), cmocka_unit_test(torture_connect_uninitialized), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_forward.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_ssh_forward(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_channel c; int dport; int bound_port; int rc; int verbosity = SSH_LOG_TRACE; ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); rc = ssh_channel_listen_forward(session, "127.0.0.21", 8080, &bound_port); assert_ssh_return_code(session, rc); c = ssh_channel_accept_forward(session, 10, &dport); /* We do not get a listener and run into the timeout here */ assert_null(c); ssh_channel_send_eof(c); ssh_channel_close(c); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_ssh_forward, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_hostkey.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Jakub Jelen * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #ifdef HAVE_SYS_TIME_H #include #endif /* HAVE_SYS_TIME_H */ #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_hostkey_rsa(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char rsa[] = "ssh-rsa"; int rc; if (ssh_fips_mode()) { skip(); } rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &rsa); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } static void torture_hostkey_ed25519(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char ed[] = "ssh-ed25519"; int rc; if (ssh_fips_mode()) { skip(); } rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &ed); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } #ifdef HAVE_DSA static void torture_hostkey_dss(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char rsa[] = "ssh-dss"; int rc; if (ssh_fips_mode()) { skip(); } rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &rsa); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } #endif /* HAVE_DSA */ #ifdef HAVE_ECC static void torture_hostkey_ecdsa(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char ecdsa[] = "ecdsa-sha2-nistp521"; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &ecdsa); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } #endif static void torture_hostkey_rsa_sha256(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char rsa[] = "rsa-sha2-256"; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &rsa); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } static void torture_hostkey_rsa_sha512(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char rsa[] = "rsa-sha2-512"; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, &rsa); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); rc = ssh_connect(session); assert_ssh_return_code(session, rc); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_hostkey_rsa, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_hostkey_ed25519, session_setup, session_teardown), #ifdef HAVE_ECC cmocka_unit_test_setup_teardown(torture_hostkey_ecdsa, session_setup, session_teardown), #endif #ifdef HAVE_DSA cmocka_unit_test_setup_teardown(torture_hostkey_dss, session_setup, session_teardown), #endif /* the client is able to handle SHA2 extension (if negotiated) */ cmocka_unit_test_setup_teardown(torture_hostkey_rsa_sha256, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_hostkey_rsa_sha512, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_knownhosts.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2010 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include #include #include #include "session.c" #include "known_hosts.c" #define TMP_FILE_TEMPLATE "known_hosts_XXXXXX" #define BADRSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQChm5" \ "a6Av65O8cKtx5YXOnui3wJnYE6A6J/I4kZSAibbn14Jcl+34VJQwv96f25AxNmo" \ "NwoiZV93IzdypQmiuieh6s6wB9WhYjU9K/6CkIpNhpCxswA90b3ePjS7LnR9B9J" \ "slPSbG1H0KC1c5lb7G3utXteXtM+4YvCvpN5VdC4CpghT+p0cwN2Na8Md5vRItz" \ "YgIytryNn7LLiwYfoSxvWigFrTTZsrVtCOYyNgklmffpGdzuC43wdANvTewfI9G" \ "o71r8EXmEc228CrYPmb8Scv3mpXFK/BosohSGkPlEHu9lf3YjnknBicDaVtJOYp" \ "wnXJPjZo2EhG79HxDRpjJHH" #define BADED25519 "AAAAC3NzaC1lZDI1NTE5AAAAIE74wHmKKkrxpW/dZ69pKPlMoWG9VvWfrNnUkWRQqaDa" static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool process_config = false; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_knownhosts_port(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; char buffer[200]; char *p; FILE *file; int rc; bool process_config = false; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); session->opts.port = 1234; rc = ssh_write_knownhost(session); assert_ssh_return_code(session, rc); file = fopen(known_hosts_file, "r"); assert_non_null(file); p = fgets(buffer, sizeof(buffer), file); assert_non_null(p); fclose(file); buffer[sizeof(buffer) - 1] = '\0'; assert_non_null(strstr(buffer,"[127.0.0.10]:1234 ")); ssh_disconnect(session); ssh_free(session); /* Now, connect back to the ssh server and verify the known host line */ s->ssh.session = session = ssh_new(); ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); free(known_hosts_file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); session->opts.port = 1234; rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_OK); } static void torture_knownhosts_wildcard(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; const char *key = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); file = fopen(known_hosts_file, "w"); assert_non_null(file); key = torture_get_testkey_pub(SSH_KEYTYPE_RSA); fprintf(file, "[127.0.0.10]:* %s\n", key); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); free(known_hosts_file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_OK); } static void torture_knownhosts_standard_port(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; const char *key = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); file = fopen(known_hosts_file, "w"); assert_non_null(file); key = torture_get_testkey_pub(SSH_KEYTYPE_RSA); fprintf(file, "[127.0.0.10]:22 %s\n", key); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); free(known_hosts_file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_OK); } static void torture_knownhosts_fail(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); file = fopen(known_hosts_file, "w"); assert_non_null(file); free(known_hosts_file); fprintf(file, "127.0.0.10 ssh-rsa %s\n", BADRSA); fclose(file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_CHANGED); } static void torture_knownhosts_other(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); file = fopen(known_hosts_file, "w"); assert_non_null(file); free(known_hosts_file); fprintf(file, "127.0.0.10 ssh-rsa %s\n", BADRSA); fclose(file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_FOUND_OTHER); } static void torture_knownhosts_other_auto(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; int rc; bool process_config = false; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_NOT_KNOWN); rc = ssh_write_knownhost(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); ssh_free(session); /* connect again and check host key */ session = ssh_new(); assert_non_null(session); s->ssh.session = session; rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); /* ssh-rsa is the default but libssh should try ssh-ed25519 instead */ rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_OK); /* session will be freed by session_teardown() */ free(known_hosts_file); } static void torture_knownhosts_conflict(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; FILE *file; int rc; bool process_config = false; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 ssh-rsa %s\n", BADRSA); fprintf(file, "127.0.0.10 ssh-ed25519 %s\n", BADED25519); fclose(file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_CHANGED); rc = ssh_write_knownhost(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); ssh_free(session); /* connect again and check host key */ session = ssh_new(); assert_non_null(session); s->ssh.session = session; rc = ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); assert_ssh_return_code(session, rc); ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_is_server_known(session); assert_int_equal(rc, SSH_SERVER_KNOWN_OK); /* session will be freed by session_teardown() */ free(known_hosts_file); } static void torture_knownhosts_no_hostkeychecking(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; enum ssh_known_hosts_e found; int strict_host_key_checking = 0; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); free(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_UNKNOWN); rc = ssh_options_set(session, SSH_OPTIONS_STRICTHOSTKEYCHECK, &strict_host_key_checking); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_knownhosts_wildcard, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_standard_port, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_port, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_fail, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_other, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_other_auto, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_conflict, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_no_hostkeychecking, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_knownhosts_verify.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include #include #include "knownhosts.c" #define TMP_FILE_TEMPLATE "known_hosts_XXXXXX" #define BAD_RSA "AAAAB3NzaC1yc2EAAAADAQABAAABAQDXvXuawzaArEwkLIXTz/EWywLOC" \ "tqQL3P9yKkrhz6AplXP2PhOh5pyxa1VfGKe453jNeYBJ0ROto3BshXgZX" \ "bo86oLXTkbe0gO5xi3r5WjXxjOFvRRTLot5fPLNDOv9+TnsPmkNn0iIey" \ "PnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpbJvTXSDipukpUy41d7jg4uWGu" \ "onMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdcARyhix4RMWZZqVY20" \ "H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1TjzkrBZ6B6" \ "thmZtyeb9IsiB0tg2g0JN2VTAGkxqp" const char template[] = "temp_dir_XXXXXX"; static int sshd_group_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_group_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; int rc; bool process_config = false; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } #define KNOWN_HOST_ENTRY_ECDSA "127.0.0.10 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl17sFnTTrT8wYo1FCzE07wV262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee16VwhJGsMzGGh1FJ0XXhRJjUbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOOB7EmFZd18g==\n" #define KNOWN_HOST_ENTRY_ED25519 "127.0.0.10 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWWnxuCYiOyvMYLtkgoEyEKlLV+klM+BU6Nh3PmAiqX\n" static void torture_knownhosts_export(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char *entry = NULL; char *p = NULL; int rc; rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_session_export_known_hosts_entry(session, &entry); assert_ssh_return_code(session, rc); p = strstr(entry, "ssh-ed25519"); if (p != NULL) { assert_string_equal(entry, KNOWN_HOST_ENTRY_ED25519); } else { assert_string_equal(entry, KNOWN_HOST_ENTRY_ECDSA); } SAFE_FREE(entry); } static void torture_knownhosts_write_and_verify(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; enum ssh_known_hosts_e found; int rc; rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_session_update_known_hosts(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); } static void torture_knownhosts_precheck(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; struct ssh_list *algo_list = NULL; struct ssh_iterator *it = NULL; size_t algo_count; const char *algo = NULL; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_ED25519)); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_ECDSA_P521)); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); free(known_hosts_file); algo_list = ssh_known_hosts_get_algorithms(session); assert_non_null(algo_list); algo_count = ssh_list_count(algo_list); assert_int_equal(algo_count, 3); it = ssh_list_get_iterator(algo_list); assert_non_null(it); algo = ssh_iterator_value(const char *, it); assert_string_equal(algo, "ssh-rsa"); ssh_list_remove(algo_list, it); it = ssh_list_get_iterator(algo_list); assert_non_null(it); algo = ssh_iterator_value(const char *, it); assert_string_equal(algo, "ssh-ed25519"); ssh_list_remove(algo_list, it); it = ssh_list_get_iterator(algo_list); assert_non_null(it); algo = ssh_iterator_value(const char *, it); assert_string_equal(algo, "ecdsa-sha2-nistp521"); ssh_list_free(algo_list); } static void torture_knownhosts_duplicate(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; struct ssh_list *algo_list = NULL; struct ssh_iterator *it = NULL; size_t algo_count; const char *algo = NULL; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; FILE *file; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); free(known_hosts_file); algo_list = ssh_known_hosts_get_algorithms(session); assert_non_null(algo_list); algo_count = ssh_list_count(algo_list); assert_int_equal(algo_count, 1); it = ssh_list_get_iterator(algo_list); assert_non_null(it); algo = ssh_iterator_value(const char *, it); assert_string_equal(algo, "ssh-rsa"); ssh_list_free(algo_list); } static void torture_knownhosts_other(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; enum ssh_known_hosts_e found; FILE *file = NULL; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fclose(file); free(known_hosts_file); rc = ssh_connect(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OTHER); } static void torture_knownhosts_unknown(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; enum ssh_known_hosts_e found; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_UNKNOWN); rc = ssh_session_update_known_hosts(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); ssh_free(session); /* connect again and check host key */ session = ssh_new(); assert_non_null(session); s->ssh.session = session; rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); /* ssh-rsa is the default but libssh should try ssh-ed25519 instead */ found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* session will be freed by session_teardown() */ free(known_hosts_file); } static void torture_knownhosts_conflict(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; char tmp_file[1024] = {0}; char *known_hosts_file = NULL; enum ssh_known_hosts_e found; FILE *file = NULL; int rc; snprintf(tmp_file, sizeof(tmp_file), "%s/%s", s->socket_dir, TMP_FILE_TEMPLATE); known_hosts_file = torture_create_temp_file(tmp_file); assert_non_null(known_hosts_file); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 %s %s\n", "ssh-rsa", BAD_RSA); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_CHANGED); rc = ssh_session_update_known_hosts(session); assert_ssh_return_code(session, rc); ssh_disconnect(session); ssh_free(session); /* connect again and check host key */ session = ssh_new(); assert_non_null(session); s->ssh.session = session; rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* session will be freed by session_teardown() */ free(known_hosts_file); } static void torture_knownhosts_new_file(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; enum ssh_known_hosts_e found; int rc; char new_known_hosts[256]; char *tmp_dir = NULL; ssize_t count = 0; /* Create a disposable directory */ tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); count = snprintf(new_known_hosts, sizeof(new_known_hosts), "%s/a/b/c/d/known_hosts", tmp_dir); assert_return_code(count, errno); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, new_known_hosts); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_session_update_known_hosts(session); assert_ssh_return_code(session, rc); found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* Cleanup */ torture_rmdirs(tmp_dir); SAFE_FREE(tmp_dir); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_knownhosts_export, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_write_and_verify, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_precheck, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_other, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_unknown, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_conflict, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_duplicate, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_knownhosts_new_file, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_group_setup, sshd_group_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_proxycommand.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #include "libssh/priv.h" #include #include #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } #ifdef NC_EXECUTABLE static void torture_options_set_proxycommand(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; const char *address = torture_server_address(AF_INET); int port = torture_server_port(); char command[255] = {0}; struct stat sb; int rc; socket_t fd; rc = stat(NC_EXECUTABLE, &sb); if (rc != 0 || (sb.st_mode & S_IXOTH) == 0) { SSH_LOG(SSH_LOG_WARNING, "Could not find " NC_EXECUTABLE ": Skipping the test"); skip(); } rc = snprintf(command, sizeof(command), NC_EXECUTABLE " %s %d", address, port); assert_true((size_t)rc < sizeof(command)); rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command); assert_int_equal(rc, 0); rc = ssh_connect(session); assert_ssh_return_code(session, rc); fd = ssh_get_fd(session); assert_true(fd != SSH_INVALID_SOCKET); rc = fcntl(fd, F_GETFL); assert_int_equal(rc & O_RDWR, O_RDWR); } #else /* NC_EXECUTABLE */ static void torture_options_set_proxycommand(void **state) { (void) state; skip(); } #endif /* NC_EXECUTABLE */ static void torture_options_set_proxycommand_notexist(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; int rc; rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "this_command_does_not_exist"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code_equal(session, rc, SSH_ERROR); } static void torture_options_set_proxycommand_ssh(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; const char *address = torture_server_address(AF_INET); char command[255] = {0}; int rc; socket_t fd; rc = snprintf(command, sizeof(command), "ssh -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s", address); assert_true((size_t)rc < sizeof(command)); rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command); assert_int_equal(rc, 0); rc = ssh_connect(session); assert_ssh_return_code(session, rc); fd = ssh_get_fd(session); assert_true(fd != SSH_INVALID_SOCKET); rc = fcntl(fd, F_GETFL); assert_int_equal(rc & O_RDWR, O_RDWR); } static void torture_options_set_proxycommand_ssh_stderr(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; const char *address = torture_server_address(AF_INET); char command[255] = {0}; int rc; socket_t fd; /* The -vvv switches produce the desired output on the standard error */ rc = snprintf(command, sizeof(command), "ssh -vvv -oStrictHostKeyChecking=no -W [%%h]:%%p alice@%s", address); assert_true((size_t)rc < sizeof(command)); rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, command); assert_int_equal(rc, 0); rc = ssh_connect(session); assert_ssh_return_code(session, rc); fd = ssh_get_fd(session); assert_true(fd != SSH_INVALID_SOCKET); rc = fcntl(fd, F_GETFL); assert_int_equal(rc & O_RDWR, O_RDWR); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_options_set_proxycommand, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_notexist, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_options_set_proxycommand_ssh_stderr, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_rekey.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Authors: Jakub Jelen * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/sftp.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/crypto.h" #include #include #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool b = false; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); /* Authenticate as alice with bob's pubkey */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); /* Make sure we do not interfere with another ssh-agent */ unsetenv("SSH_AUTH_SOCK"); unsetenv("SSH_AGENT_PID"); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_free(s->ssh.session); return 0; } /* Check that the default limits for rekeying are enforced. * the limits are too high for testsuite to verify so * we should be fine with checking the values in internal * structures */ static void torture_rekey_default(void **state) { struct torture_state *s = *state; int rc; struct ssh_crypto_struct *c = NULL; /* Define preferred ciphers: */ if (ssh_fips_mode()) { /* We do not have any FIPS allowed cipher with different block size */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_CIPHERS_C_S, "aes128-gcm@openssh.com"); } else { /* (out) C->S has 8B block */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_CIPHERS_C_S, "chacha20-poly1305@openssh.com"); } assert_ssh_return_code(s->ssh.session, rc); /* (in) S->C has 16B block */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_CIPHERS_S_C, "aes128-cbc"); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, rc); c = s->ssh.session->current_crypto; /* The blocks limit is set correctly */ /* For S->C (in) we have 16B block => 2**(L/4) blocks */ assert_int_equal(c->in_cipher->max_blocks, (uint64_t)1 << (2 * c->in_cipher->blocksize)); if (ssh_fips_mode()) { /* We do not have any FIPS allowed cipher with different block size */ assert_int_equal(c->in_cipher->max_blocks, (uint64_t)1 << (2 * c->in_cipher->blocksize)); } else { /* The C->S (out) we have 8B block => 1 GB limit */ assert_int_equal(c->out_cipher->max_blocks, ((uint64_t)1 << 30) / c->out_cipher->blocksize); } ssh_disconnect(s->ssh.session); } /* We lower the rekey limits manually and check that the rekey * really happens when sending data */ static void torture_rekey_send(void **state) { struct torture_state *s = *state; int rc; char data[256]; unsigned int i; uint64_t bytes = 2048; /* 2KB (more than the authentication phase) */ struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, rc); /* The blocks limit is set correctly */ c = s->ssh.session->current_crypto; assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); /* We should have less encrypted packets than transfered (first are not encrypted) */ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); /* Copy the initial secret hash = session_id so we know we changed keys later */ secret_hash = malloc(c->digest_len); assert_non_null(secret_hash); memcpy(secret_hash, c->secret_hash, c->digest_len); /* OpenSSH can not rekey before authentication so authenticate here */ rc = ssh_userauth_none(s->ssh.session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(s->ssh.session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); /* send ignore packets of up to 1KB to trigger rekey */ memset(data, 0, sizeof(data)); memset(data, 'A', 128); for (i = 0; i < 16; i++) { ssh_send_ignore(s->ssh.session, data); ssh_handle_packets(s->ssh.session, 50); } /* The rekey limit was restored in the new crypto to the same value */ c = s->ssh.session->current_crypto; assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); /* Check that the secret hash is different than initially */ assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len); free(secret_hash); ssh_disconnect(s->ssh.session); } #ifdef WITH_SFTP static void session_setup_sftp(void **state) { struct torture_state *s = *state; int rc; rc = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, rc); /* OpenSSH can not rekey before authentication so authenticate here */ rc = ssh_userauth_none(s->ssh.session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(s->ssh.session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); /* Initialize SFTP session */ s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); } uint64_t bytes = 2048; /* 2KB */ static int session_setup_sftp_client(void **state) { struct torture_state *s = *state; int rc; session_setup(state); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_DATA, &bytes); assert_ssh_return_code(s->ssh.session, rc); session_setup_sftp(state); return 0; } #define MAX_XFER_BUF_SIZE 16384 /* To trigger rekey by receiving data, the easiest thing is probably to * use sftp */ static void torture_rekey_recv(void **state) { struct torture_state *s = *state; struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; char libssh_tmp_file[] = "/tmp/libssh_sftp_test_XXXXXX"; char buf[MAX_XFER_BUF_SIZE]; ssize_t bytesread; ssize_t byteswritten; int fd; sftp_file file; mode_t mask; /* The blocks limit is set correctly */ c = s->ssh.session->current_crypto; assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); /* We should have less encrypted packets than transfered (first are not encrypted) */ assert_true(c->out_cipher->packets < s->ssh.session->send_seq); assert_true(c->in_cipher->packets < s->ssh.session->recv_seq); /* Copy the initial secret hash = session_id so we know we changed keys later */ secret_hash = malloc(c->digest_len); assert_non_null(secret_hash); memcpy(secret_hash, c->secret_hash, c->digest_len); /* Download a file */ file = sftp_open(s->ssh.tsftp->sftp, SSH_EXECUTABLE, O_RDONLY, 0); assert_non_null(file); mask = umask(S_IRWXO | S_IRWXG); fd = mkstemp(libssh_tmp_file); umask(mask); unlink(libssh_tmp_file); for (;;) { bytesread = sftp_read(file, buf, MAX_XFER_BUF_SIZE); if (bytesread == 0) { break; /* EOF */ } assert_false(bytesread < 0); byteswritten = write(fd, buf, bytesread); assert_int_equal(byteswritten, bytesread); } close(fd); /* The rekey limit was restored in the new crypto to the same value */ c = s->ssh.session->current_crypto; assert_int_equal(c->in_cipher->max_blocks, bytes / c->in_cipher->blocksize); assert_int_equal(c->out_cipher->max_blocks, bytes / c->out_cipher->blocksize); /* Check that the secret hash is different than initially */ assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len); free(secret_hash); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); } #endif /* WITH_SFTP */ /* Rekey time requires rekey after specified time and is off by default. * Setting the time to small enough value and waiting, we should trigger * rekey on the first sent packet afterward. */ static void torture_rekey_time(void **state) { struct torture_state *s = *state; int rc; char data[256]; unsigned int i; uint32_t time = 3; /* 3 seconds */ struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_REKEY_TIME, &time); assert_ssh_return_code(s->ssh.session, rc); /* The time is internally stored in microseconds */ assert_int_equal(time * 1000, s->ssh.session->opts.rekey_time); rc = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, rc); /* Copy the initial secret hash = session_id so we know we changed keys later */ c = s->ssh.session->current_crypto; secret_hash = malloc(c->digest_len); assert_non_null(secret_hash); memcpy(secret_hash, c->secret_hash, c->digest_len); /* OpenSSH can not rekey before authentication so authenticate here */ rc = ssh_userauth_none(s->ssh.session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(s->ssh.session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); /* Send some data. This should not trigger rekey yet */ memset(data, 0, sizeof(data)); memset(data, 'A', 8); for (i = 0; i < 3; i++) { ssh_send_ignore(s->ssh.session, data); ssh_handle_packets(s->ssh.session, 50); } /* Check that the secret hash is the same */ c = s->ssh.session->current_crypto; assert_memory_equal(secret_hash, c->secret_hash, c->digest_len); /* Wait some more time */ sleep(3); /* send some more data to trigger rekey and handle the * key exchange "in background" */ for (i = 0; i < 8; i++) { ssh_send_ignore(s->ssh.session, data); ssh_handle_packets(s->ssh.session, 50); } /* Check that the secret hash is different than initially */ c = s->ssh.session->current_crypto; assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len); free(secret_hash); ssh_disconnect(s->ssh.session); } /* We lower the rekey limits manually and check that the rekey * really happens when sending data */ static void torture_rekey_server_send(void **state) { struct torture_state *s = *state; int rc; char data[256]; unsigned int i; struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; const char *sshd_config = "RekeyLimit 2K none"; torture_update_sshd_config(state, sshd_config); rc = ssh_connect(s->ssh.session); assert_ssh_return_code(s->ssh.session, rc); /* Copy the initial secret hash = session_id so we know we changed keys later */ c = s->ssh.session->current_crypto; secret_hash = malloc(c->digest_len); assert_non_null(secret_hash); memcpy(secret_hash, c->secret_hash, c->digest_len); /* OpenSSH can not rekey before authentication so authenticate here */ rc = ssh_userauth_none(s->ssh.session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(s->ssh.session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(s->ssh.session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(s->ssh.session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); /* send ignore packets of up to 1KB to trigger rekey */ memset(data, 0, sizeof(data)); memset(data, 'A', 128); for (i = 0; i < 20; i++) { ssh_send_ignore(s->ssh.session, data); ssh_handle_packets(s->ssh.session, 50); } /* Check that the secret hash is different than initially */ c = s->ssh.session->current_crypto; assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len); free(secret_hash); ssh_disconnect(s->ssh.session); } #ifdef WITH_SFTP static int session_setup_sftp_server(void **state) { const char *sshd_config = "RekeyLimit 2K none"; session_setup(state); torture_update_sshd_config(state, sshd_config); session_setup_sftp(state); return 0; } static void torture_rekey_server_recv(void **state) { struct torture_state *s = *state; struct ssh_crypto_struct *c = NULL; unsigned char *secret_hash = NULL; char libssh_tmp_file[] = "/tmp/libssh_sftp_test_XXXXXX"; char buf[MAX_XFER_BUF_SIZE]; ssize_t bytesread; ssize_t byteswritten; int fd; sftp_file file; mode_t mask; /* Copy the initial secret hash = session_id so we know we changed keys later */ c = s->ssh.session->current_crypto; secret_hash = malloc(c->digest_len); assert_non_null(secret_hash); memcpy(secret_hash, c->secret_hash, c->digest_len); /* Download a file */ file = sftp_open(s->ssh.tsftp->sftp, SSH_EXECUTABLE, O_RDONLY, 0); assert_non_null(file); mask = umask(S_IRWXO | S_IRWXG); fd = mkstemp(libssh_tmp_file); umask(mask); unlink(libssh_tmp_file); for (;;) { bytesread = sftp_read(file, buf, MAX_XFER_BUF_SIZE); if (bytesread == 0) { break; /* EOF */ } assert_false(bytesread < 0); byteswritten = write(fd, buf, bytesread); assert_int_equal(byteswritten, bytesread); } close(fd); /* Check that the secret hash is different than initially */ c = s->ssh.session->current_crypto; assert_memory_not_equal(secret_hash, c->secret_hash, c->digest_len); free(secret_hash); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); } #endif /* WITH_SFTP */ int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_rekey_default, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_rekey_time, session_setup, session_teardown), #ifdef WITH_SFTP cmocka_unit_test_setup_teardown(torture_rekey_recv, session_setup_sftp_client, session_teardown), #endif /* WITH_SFTP */ cmocka_unit_test_setup_teardown(torture_rekey_send, session_setup, session_teardown), /* Note, that this modifies the sshd_config */ cmocka_unit_test_setup_teardown(torture_rekey_server_send, session_setup, session_teardown), #ifdef WITH_SFTP cmocka_unit_test_setup_teardown(torture_rekey_server_recv, session_setup_sftp_server, session_teardown), #endif /* WITH_SFTP */ /* TODO verify the two rekey are possible and the states are not broken after rekey */ }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_request_env.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2013 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_request_env(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_channel c; char buffer[4096] = {0}; int nbytes; int rc; int lang_found = 0; c = ssh_channel_new(session); assert_non_null(c); rc = ssh_channel_open_session(c); assert_ssh_return_code(session, rc); rc = ssh_channel_request_env(c, "LC_LIBSSH", "LIBSSH_EXPORTED_VARIABLE"); assert_ssh_return_code(session, rc); rc = ssh_channel_request_exec(c, "echo $LC_LIBSSH"); assert_ssh_return_code(session, rc); nbytes = ssh_channel_read(c, buffer, sizeof(buffer) - 1, 0); printf("nbytes=%d\n", nbytes); while (nbytes > 0) { #if 1 rc = fwrite(buffer, 1, nbytes, stdout); assert_int_equal(rc, nbytes); #endif buffer[nbytes]='\0'; if (strstr(buffer, "LIBSSH_EXPORTED_VARIABLE")) { lang_found = 1; break; } nbytes = ssh_channel_read(c, buffer, sizeof(buffer), 0); } assert_int_equal(lang_found, 1); ssh_channel_close(c); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_request_env, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_scp.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #define LIBSSH_STATIC #include "config.h" #include "torture.h" #include "libssh/scp.h" #include #include #include #include #include #define BUF_SIZE 1024 #define TEMPLATE BINARYDIR "/tests/home/alice/temp_dir_XXXXXX" #define ALICE_HOME BINARYDIR "/tests/home/alice" struct scp_st { struct torture_state *s; char *tmp_dir; char *tmp_dir_basename; }; static int sshd_setup(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ts = (struct scp_st *)calloc(1, sizeof(struct scp_st)); assert_non_null(ts); torture_setup_sshd_server((void **)&s, false); assert_non_null(s); ts->s = s; *state = ts; return 0; } static int sshd_teardown(void **state) { struct scp_st *ts = NULL; ts = *((struct scp_st **)state); assert_non_null(ts); assert_non_null(ts->s); torture_teardown_sshd_server((void **)&(ts->s)); SAFE_FREE(ts); return 0; } static int session_setup(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; char *tmp_dir = NULL; char *tmp_dir_basename = NULL; struct passwd *pwd; int rc; assert_non_null(state); ts = *state; assert_non_null(ts); assert_non_null(ts->s); s = ts->s; /* Create temporary directory for alice */ tmp_dir = torture_make_temp_dir(TEMPLATE); assert_non_null(tmp_dir); ts->tmp_dir = tmp_dir; tmp_dir_basename = ssh_basename(tmp_dir); assert_non_null(tmp_dir_basename); ts->tmp_dir_basename = tmp_dir_basename; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); return 0; } static int session_teardown(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; assert_non_null(state); ts = *((struct scp_st **)state); assert_non_null(ts->s); s = ts->s; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); assert_non_null(ts->tmp_dir); torture_rmdirs(ts->tmp_dir); SAFE_FREE(ts->tmp_dir); SAFE_FREE(ts->tmp_dir_basename); return 0; } static void torture_scp_upload(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; char expected_a[BUF_SIZE]; char buf[BUF_SIZE]; FILE *file = NULL; size_t len = 0; int rc; assert_non_null(state); ts = *state; assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Upload file "a" to alice's temp dir */ /* When writing the file_name must be the directory name */ scp = ssh_scp_new(session, SSH_SCP_WRITE, ts->tmp_dir_basename); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); /* Init buffer content to be written */ memset(expected_a, 'A', BUF_SIZE); /* For ssh_scp_push_file(), the file_name is the name of the file without * path */ rc = ssh_scp_push_file(scp, "a", BUF_SIZE, 0644); assert_ssh_return_code(session, rc); rc = ssh_scp_write(scp, expected_a, BUF_SIZE); assert_ssh_return_code(session, rc); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); /* Open file and check content */ snprintf(buf, BUF_SIZE, "%s/a", ts->tmp_dir); file = fopen(buf, "r"); assert_non_null(file); len = fread(buf, BUF_SIZE, 1, file); assert_int_equal(len, 1); assert_memory_equal(buf, expected_a, BUF_SIZE); fclose(file); } static void torture_scp_upload_recursive(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; char expected_b[BUF_SIZE]; char buf[BUF_SIZE]; FILE *file = NULL; size_t len = 0; int rc; assert_non_null(state); ts = *state; assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Upload directory "test_dir" containing file "b" to alice's temp dir */ /* When writing the file_name must be the directory name */ scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ts->tmp_dir_basename); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); /* Push directory where the new file will be copied */ rc = ssh_scp_push_directory(scp, "test_dir", 0755); assert_ssh_return_code(session, rc); memset(expected_b, 'B', BUF_SIZE); /* For ssh_scp_push_file(), the file_name is the name of the file without * path */ rc = ssh_scp_push_file(scp, "b", BUF_SIZE, 0644); assert_ssh_return_code(session, rc); rc = ssh_scp_write(scp, expected_b, BUF_SIZE); assert_ssh_return_code(session, rc); /* Leave the directory */ rc = ssh_scp_leave_directory(scp); assert_ssh_return_code(session, rc); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); /* Open file and check content */ snprintf(buf, BUF_SIZE, "%s/test_dir/b", ts->tmp_dir); file = fopen(buf, "r"); assert_non_null(file); len = fread(buf, BUF_SIZE, 1, file); assert_int_equal(len, 1); assert_memory_equal(buf, expected_b, BUF_SIZE); fclose(file); } static void torture_scp_download(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; char expected_a[BUF_SIZE]; char buf[BUF_SIZE]; const char *remote_file = NULL; FILE *file = NULL; int fd = 0; size_t size; int mode; int rc; assert_non_null(state); ts = *state; assert_non_null(ts); assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Create file "a" for alice */ memset(expected_a, 'A', BUF_SIZE); snprintf(buf, BUF_SIZE, "%s/a", ts->tmp_dir); fd = open(buf, O_WRONLY | O_CREAT, 0644); assert_true(fd > 0); file = fdopen(fd, "w"); assert_non_null(file); size = fwrite(expected_a, 1, BUF_SIZE, file); assert_int_equal(size, BUF_SIZE); fclose(file); /* Construct the file path */ snprintf(buf, BUF_SIZE, "%s/a", ts->tmp_dir_basename); /* When reading, the location is the file path */ scp = ssh_scp_new(session, SSH_SCP_READ, buf); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); rc = ssh_scp_pull_request(scp); assert_int_equal(rc, SSH_SCP_REQUEST_NEWFILE); size = ssh_scp_request_get_size(scp); assert_int_equal(size, BUF_SIZE); mode = ssh_scp_request_get_permissions(scp); assert_int_equal(mode, 0644); remote_file = ssh_scp_request_get_filename(scp); assert_non_null(remote_file); assert_string_equal(remote_file, "a"); rc = ssh_scp_accept_request(scp); assert_ssh_return_code(session, rc); rc = ssh_scp_read(scp, buf, BUF_SIZE); assert_int_equal(rc, size); assert_memory_equal(expected_a, buf, BUF_SIZE); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); } static void torture_scp_download_recursive(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; char expected_b[BUF_SIZE]; char buf[BUF_SIZE]; const char *remote_file = NULL; FILE *file = NULL; int fd = 0; size_t size; int mode; int rc; assert_non_null(state); ts = *state; assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Create file "b" for alice */ memset(expected_b, 'B', BUF_SIZE); snprintf(buf, BUF_SIZE, "%s/b", ts->tmp_dir); fd = open(buf, O_WRONLY | O_CREAT, 0644); assert_true(fd > 0); file = fdopen(fd, "w"); assert_non_null(file); size = fwrite(expected_b, 1, BUF_SIZE, file); assert_int_equal(size, BUF_SIZE); fclose(file); /* Copy the directory containing the file "b" */ scp = ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, ts->tmp_dir_basename); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); /* Receive the directory */ rc = ssh_scp_pull_request(scp); assert_int_equal(rc, SSH_SCP_REQUEST_NEWDIR); mode = ssh_scp_request_get_permissions(scp); assert_int_equal(mode, 0700); remote_file = ssh_scp_request_get_filename(scp); assert_non_null(remote_file); assert_string_equal(remote_file, ts->tmp_dir_basename); rc = ssh_scp_accept_request(scp); assert_ssh_return_code(session, rc); /* Receive the file "b" */ rc = ssh_scp_pull_request(scp); assert_int_equal(rc, SSH_SCP_REQUEST_NEWFILE); size = ssh_scp_request_get_size(scp); assert_int_equal(size, BUF_SIZE); mode = ssh_scp_request_get_permissions(scp); assert_int_equal(mode, 0644); remote_file = ssh_scp_request_get_filename(scp); assert_non_null(remote_file); assert_string_equal(remote_file, "b"); rc = ssh_scp_accept_request(scp); assert_ssh_return_code(session, rc); rc = ssh_scp_read(scp, buf, BUF_SIZE); assert_int_equal(rc, size); /* Check if the content was the expected */ assert_memory_equal(expected_b, buf, BUF_SIZE); /* Receive end of directory */ rc = ssh_scp_pull_request(scp); assert_int_equal(rc, SSH_SCP_REQUEST_ENDDIR); /* Receive end of communication */ rc = ssh_scp_pull_request(scp); assert_int_equal(rc, SSH_SCP_REQUEST_EOF); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); } static void torture_scp_upload_newline(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; FILE *file = NULL; char buf[1024]; char *rs = NULL; int rc; assert_non_null(state); ts = *state; assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Upload recursively trying to inject protocol messages */ /* When writing the file_name must be the directory name */ scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ts->tmp_dir_basename); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); /* Push directory where the new file will be copied */ rc = ssh_scp_push_directory(scp, "test_inject", 0755); assert_ssh_return_code(session, rc); /* Try to push file with injected protocol messages */ rc = ssh_scp_push_file(scp, "original\nreplacedC0777 8 injected", 8, 0644); assert_ssh_return_code(session, rc); rc = ssh_scp_write(scp, "original", 8); assert_ssh_return_code(session, rc); /* Leave the directory */ rc = ssh_scp_leave_directory(scp); assert_ssh_return_code(session, rc); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); /* Open the file and check content */ snprintf(buf, BUF_SIZE, "%s/test_inject/" "original\\nreplacedC0777 8 injected", ts->tmp_dir); file = fopen(buf, "r"); assert_non_null(file); rs = fgets(buf, 1024, file); assert_non_null(rs); assert_string_equal(buf, "original"); fclose(file); } static void torture_scp_upload_appended_command(void **state) { struct scp_st *ts = NULL; struct torture_state *s = NULL; ssh_session session = NULL; ssh_scp scp = NULL; FILE *file = NULL; char buf[1024]; char *rs = NULL; int rc; assert_non_null(state); ts = *state; assert_non_null(ts->s); s = ts->s; session = s->ssh.session; assert_non_null(session); assert_non_null(ts->tmp_dir_basename); assert_non_null(ts->tmp_dir); /* Upload a file path with a command appended */ /* Append a command to the file path */ snprintf(buf, BUF_SIZE, "%s" "/;touch hack", ts->tmp_dir); /* When writing the file_name must be the directory name */ scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, buf); assert_non_null(scp); rc = ssh_scp_init(scp); assert_ssh_return_code(session, rc); /* Push directory where the new file will be copied */ rc = ssh_scp_push_directory(scp, ";touch hack", 0755); assert_ssh_return_code(session, rc); /* Try to push file */ rc = ssh_scp_push_file(scp, "original", 8, 0644); assert_ssh_return_code(session, rc); rc = ssh_scp_write(scp, "original", 8); assert_ssh_return_code(session, rc); /* Leave the directory */ rc = ssh_scp_leave_directory(scp); assert_ssh_return_code(session, rc); /* Cleanup */ ssh_scp_close(scp); ssh_scp_free(scp); /* Make sure the command was not executed */ snprintf(buf, BUF_SIZE, ALICE_HOME "/hack"); file = fopen(buf, "r"); assert_null(file); /* Open the file and check content */ snprintf(buf, BUF_SIZE, "%s" "/;touch hack/original", ts->tmp_dir); file = fopen(buf, "r"); assert_non_null(file); rs = fgets(buf, 1024, file); assert_non_null(rs); assert_string_equal(buf, "original"); fclose(file); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_scp_upload, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_scp_upload_recursive, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_scp_download, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_scp_download_recursive, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_scp_upload_newline, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_scp_upload_appended_command, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_session.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2012 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include #include #include #define BUFLEN 4096 static char buffer[BUFLEN]; static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_channel_read_error(void **state) { struct torture_state *s = *state; ssh_session session = s->ssh.session; ssh_channel channel; int rc; int fd; int i; channel = ssh_channel_new(session); assert_non_null(channel); rc = ssh_channel_open_session(channel); assert_ssh_return_code(session, rc); rc = ssh_channel_request_exec(channel, "hexdump -C /dev/urandom"); assert_ssh_return_code(session, rc); /* send crap and for server to send us a disconnect */ fd = ssh_get_fd(session); assert_true(fd > 2); rc = write(fd, "AAAA", 4); assert_int_equal(rc, 4); for (i=0;i<20;++i){ rc = ssh_channel_read(channel,buffer,sizeof(buffer),0); if (rc == SSH_ERROR) break; } #if OPENSSH_VERSION_MAJOR == 6 && OPENSSH_VERSION_MINOR >= 7 /* With openssh 6.7 this doesn't produce and error anymore */ assert_ssh_return_code(session, rc); #else assert_ssh_return_code_equal(session, rc, SSH_ERROR); #endif ssh_channel_free(channel); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_channel_read_error, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_benchmark.c ================================================ #define LIBSSH_STATIC #include "config.h" #include "torture.h" #include "sftp.c" #include #include #include #define MAX_XFER_BUF_SIZE 16384 static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; torture_rmdirs(s->ssh.tsftp->testdir); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_sftp_benchmark_write_read(void **state) { struct torture_state *s = *state; struct torture_sftp *t = s->ssh.tsftp; sftp_session sftp = t->sftp; ssh_session session = s->ssh.session; sftp_file file = NULL; struct stat sb = { .st_size = 0, }; uint8_t buf_16k[MAX_XFER_BUF_SIZE]; char local_path[1024] = {0}; ssize_t bwritten, nread; size_t i; int rc; memset(buf_16k, 'X', sizeof(buf_16k)); snprintf(local_path, sizeof(local_path), "%s/128M.dat", t->testdir); file = sftp_open(sftp, local_path, O_CREAT|O_WRONLY|O_TRUNC, 0644); assert_non_null(file); /* Write 128M */ for (i = 0; i < 0x2000; i++) { bwritten = sftp_write(file, buf_16k, sizeof(buf_16k)); assert_int_equal(bwritten, sizeof(buf_16k)); } rc = sftp_close(file); assert_ssh_return_code(session, rc); /* Check that 128M has been written */ rc = stat(local_path, &sb); assert_int_equal(sb.st_size, 0x8000000); file = sftp_open(sftp, local_path, O_RDONLY, 0); assert_non_null(file); for (;;) { nread = sftp_read(file, buf_16k, sizeof(buf_16k)); if (nread == 0) { break; /* EOF */ } assert_int_equal(nread, sizeof(buf_16k)); } rc = sftp_close(file); assert_ssh_return_code(session, rc); unlink(local_path); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_sftp_benchmark_write_read, session_setup, session_teardown) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_canonicalize_path.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "sftp.c" #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; torture_rmdirs(s->ssh.tsftp->testdir); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_sftp_canonicalize_path(void **state) { struct torture_state *s = *state; struct torture_sftp *t = s->ssh.tsftp; struct passwd *pwd = NULL; char *canonicalized_path = NULL; pwd = getpwnam(TORTURE_SSH_USER_ALICE); assert_non_null(pwd); canonicalized_path = sftp_canonicalize_path(t->sftp, "."); assert_non_null(canonicalized_path); assert_string_equal(canonicalized_path, pwd->pw_dir); SSH_STRING_FREE_CHAR(canonicalized_path); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_sftp_canonicalize_path, session_setup, session_teardown) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_dir.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "sftp.c" #include #include #include static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; torture_rmdirs(s->ssh.tsftp->testdir); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_sftp_mkdir(void **state) { struct torture_state *s = *state; struct torture_sftp *t = s->ssh.tsftp; char tmpdir[128] = {0}; int rc; assert_non_null(t); snprintf(tmpdir, sizeof(tmpdir) - 1, "%s/mkdir_test", t->testdir); rc = sftp_mkdir(t->sftp, tmpdir, 0755); if(rc != SSH_OK) fprintf(stderr,"error:%s\n",ssh_get_error(t->sftp->session)); assert_true(rc == 0); /* check if it really has been created */ assert_true(torture_isdir(tmpdir)); rc = sftp_rmdir(t->sftp, tmpdir); assert_true(rc == 0); /* check if it has been deleted */ assert_false(torture_isdir(tmpdir)); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_sftp_mkdir, session_setup, session_teardown) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_ext.c ================================================ #define LIBSSH_STATIC #include "config.h" #include "torture.h" #include "sftp.c" static void torture_sftp_ext_new(void **state) { sftp_ext x; (void) state; x = sftp_ext_new(); assert_non_null(x); assert_int_equal(x->count, 0); assert_null(x->name); assert_null(x->data); sftp_ext_free(x); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_sftp_ext_new), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_fsync.c ================================================ #define LIBSSH_STATIC #include "config.h" #include "torture.h" #include "sftp.c" #include #include #include #define MAX_XFER_BUF_SIZE 16384 static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; torture_rmdirs(s->ssh.tsftp->testdir); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_sftp_fsync(void **state) { struct torture_state *s = *state; struct torture_sftp *t = s->ssh.tsftp; char libssh_tmp_file[] = "/tmp/libssh_sftp_test_XXXXXX"; char buf[MAX_XFER_BUF_SIZE] = {0}; char buf_verify[MAX_XFER_BUF_SIZE] = {0}; size_t count; size_t bytesread; ssize_t byteswritten; int fd; sftp_file file; mode_t mask; int rc; FILE *fp; struct stat sb; mask = umask(S_IRWXO | S_IRWXG); fd = mkstemp(libssh_tmp_file); umask(mask); assert_return_code(fd, errno); close(fd); unlink(libssh_tmp_file); file = sftp_open(t->sftp, libssh_tmp_file, O_WRONLY | O_CREAT, 0600); assert_non_null(file); rc = lstat(libssh_tmp_file, &sb); assert_return_code(rc, errno); snprintf(buf, sizeof(buf), "libssh fsync test\n"); count = strlen(buf) + 1; byteswritten = sftp_write(file, buf, count); assert_int_equal(byteswritten, count); rc = sftp_fsync(file); assert_return_code(rc, errno); fp = fopen(libssh_tmp_file, "r"); assert_non_null(fp); rc = fstat(fileno(fp), &sb); assert_return_code(rc, errno); bytesread = fread(buf_verify, sizeof(buf_verify), 1, fp); if (bytesread == 0) { if (!feof(fp)) { assert_int_equal(bytesread, count); } } assert_string_equal(buf, buf_verify); sftp_close(file); fclose(fp); unlink(libssh_tmp_file); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_sftp_fsync, session_setup, session_teardown) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/client/torture_sftp_read.c ================================================ #define LIBSSH_STATIC #include "config.h" #include "torture.h" #include "sftp.c" #include #include #include #define MAX_XFER_BUF_SIZE 16384 static int sshd_setup(void **state) { torture_setup_sshd_server(state, false); return 0; } static int sshd_teardown(void **state) { torture_teardown_sshd_server(state); return 0; } static int session_setup(void **state) { struct torture_state *s = *state; struct passwd *pwd; int rc; pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = torture_ssh_session(s, TORTURE_SSH_SERVER, NULL, TORTURE_SSH_USER_ALICE, NULL); assert_non_null(s->ssh.session); s->ssh.tsftp = torture_sftp_session(s->ssh.session); assert_non_null(s->ssh.tsftp); return 0; } static int session_teardown(void **state) { struct torture_state *s = *state; torture_rmdirs(s->ssh.tsftp->testdir); torture_sftp_close(s->ssh.tsftp); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_sftp_read_blocking(void **state) { struct torture_state *s = *state; struct torture_sftp *t = s->ssh.tsftp; char libssh_tmp_file[] = "/tmp/libssh_sftp_test_XXXXXX"; char buf[MAX_XFER_BUF_SIZE]; ssize_t bytesread; ssize_t byteswritten; int fd; sftp_file file; mode_t mask; file = sftp_open(t->sftp, SSH_EXECUTABLE, O_RDONLY, 0); assert_non_null(file); mask = umask(S_IRWXO | S_IRWXG); fd = mkstemp(libssh_tmp_file); umask(mask); unlink(libssh_tmp_file); for (;;) { bytesread = sftp_read(file, buf, MAX_XFER_BUF_SIZE); if (bytesread == 0) { break; /* EOF */ } assert_false(bytesread < 0); byteswritten = write(fd, buf, bytesread); assert_int_equal(byteswritten, bytesread); } close(fd); sftp_close(file); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { /* This test is intentionally running twice to trigger a bug in OpenSSH * or in pam_wrapper, causing the second invocation to fail. * See: https://bugs.libssh.org/T122 */ cmocka_unit_test_setup_teardown(torture_sftp_read_blocking, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_sftp_read_blocking, session_setup, session_teardown) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/cmdline.c ================================================ #include "config.h" #include "torture.h" #ifdef HAVE_ARGP_H #include const char *argp_program_version = "libssh test 0.2"; const char *argp_program_bug_address = ""; static char **cmdline; /* Program documentation. */ static char doc[] = "libssh test test"; /* The options we understand. */ static struct argp_option options[] = { { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Make libssh test more verbose", .group = 0 }, {NULL, 0, NULL, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ struct argument_s *arguments = state->input; /* arg is currently not used */ (void) arg; switch (key) { case 'v': arguments->verbose++; break; case ARGP_KEY_ARG: /* End processing here. */ arguments->pattern = state->argv[state->next - 1]; cmdline = &state->argv [state->next - 1]; state->next = state->argc; break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ /* static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; */ static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments) { /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ #ifdef HAVE_ARGP_H argp_parse(&argp, argc, argv, 0, 0, arguments); #else (void) argc; (void) argv; (void) arguments; #endif /* HAVE_ARGP_H */ } ================================================ FILE: src/libssh/tests/connection.c ================================================ /* This file is distributed in public domain. You can do whatever you want with its content. */ #include #include #include "tests.h" SSH_OPTIONS *set_opts(int argc, char **argv){ SSH_OPTIONS *options=ssh_options_new(); char *host=NULL; if(ssh_options_getopt(options,&argc, argv)){ fprintf(stderr,"error parsing command line :%s\n",ssh_get_error(options)); return NULL; } int i; while((i=getopt(argc,argv,""))!=-1){ switch(i){ default: fprintf(stderr,"unknown option %c\n",optopt); } } if(optind < argc) host=argv[optind++]; if(host==NULL){ fprintf(stderr,"must provide an host name\n"); return NULL; } ssh_options_set_host(options,host); return options; } ================================================ FILE: src/libssh/tests/ctest-default.cmake ================================================ ## The directory to run ctest in. set(CTEST_DIRECTORY "$ENV{HOME}/workspace/tmp/dashboards/libssh") ## The hostname of the machine set(CTEST_SITE "host.libssh.org") ## The buildname set(CTEST_BUILD_NAME "Linux_2.6-GCC_4.5-x86_64-default") ## The Makefile generator to use set(CTEST_CMAKE_GENERATOR "Unix Makefiles") ## The Build configuration to use. set(CTEST_BUILD_CONFIGURATION "Debug") ## The build options for the project set(CTEST_BUILD_OPTIONS "-DUNIT_TESTING=ON -WITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DDEBUG_CRYPTO=ON -DWITH_GCRYPT=OFF") #set(CTEST_CUSTOM_MEMCHECK_IGNORE torture_rand) ## The Model to set: Nightly, Continous, Experimental set(CTEST_MODEL "Experimental") ## The branch #set(CTEST_GIT_BRANCH "--branch v0-5") ## Wether to enable memory checking. set(WITH_MEMCHECK FALSE) ## Wether to enable code coverage. set(WITH_COVERAGE FALSE) ####################################################################### if (WITH_COVERAGE AND NOT WIN32) set(CTEST_BUILD_CONFIGURATION "Profiling") endif (WITH_COVERAGE AND NOT WIN32) set(CTEST_SOURCE_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/source") set(CTEST_BINARY_DIRECTORY "${CTEST_DIRECTORY}/${CTEST_BUILD_NAME}/build") set(CTEST_MEMORYCHECK_SUPPRESSIONS_FILE ${CMAKE_SOURCE_DIR}/tests/valgrind.supp) set(CTEST_MEMORYCHECK_COMMAND_OPTIONS " --trace-children-skip=${SSHD_EXECUTABLE}") find_program(CTEST_GIT_COMMAND NAMES git) find_program(CTEST_COVERAGE_COMMAND NAMES gcov) find_program(CTEST_MEMORYCHECK_COMMAND NAMES valgrind) if(NOT EXISTS "${CTEST_SOURCE_DIRECTORY}") set(CTEST_CHECKOUT_COMMAND "${CTEST_GIT_COMMAND} clone ${CTEST_GIT_BRANCH} git://git.libssh.org/projects/libssh.git ${CTEST_SOURCE_DIRECTORY}") endif() set(CTEST_UPDATE_COMMAND "${CTEST_GIT_COMMAND}") set(CTEST_CONFIGURE_COMMAND "${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE:STRING=${CTEST_BUILD_CONFIGURATION}") set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} -DUNIT_TESTING:BOOL=ON ${CTEST_BUILD_OPTIONS}") set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} \"-G${CTEST_CMAKE_GENERATOR}\"") set(CTEST_CONFIGURE_COMMAND "${CTEST_CONFIGURE_COMMAND} \"${CTEST_SOURCE_DIRECTORY}\"") ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) ctest_start(${CTEST_MODEL} TRACK ${CTEST_MODEL}) ctest_update(SOURCE ${CTEST_SOURCE_DIRECTORY}) ctest_configure(BUILD ${CTEST_BINARY_DIRECTORY}) ctest_build(BUILD ${CTEST_BINARY_DIRECTORY}) ctest_test(BUILD ${CTEST_BINARY_DIRECTORY}) if (WITH_COVERAGE) ctest_coverage(BUILD ${CTEST_BINARY_DIRECTORY}) endif () if (WITH_MEMCHECK) ctest_memcheck(BUILD ${CTEST_BINARY_DIRECTORY}) endif () ctest_submit() ================================================ FILE: src/libssh/tests/etc/group.in ================================================ users:x:9000: sshd:x:65531: nobody:x:65533: nogroup:x:65534:nobody root:x:65532: ================================================ FILE: src/libssh/tests/etc/hosts.in ================================================ 127.0.0.10 server.libssh.site 127.0.0.21 client.libssh.site ================================================ FILE: src/libssh/tests/etc/pam.d/sshd.in ================================================ auth required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb account required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb password required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb session required @PAM_WRAPPER_MODULE_DIR@/pam_matrix.so passdb=@CMAKE_CURRENT_BINARY_DIR@/etc/pam_matrix_passdb ================================================ FILE: src/libssh/tests/etc/pam_matrix_passdb.in ================================================ bob:secret:sshd alice:secret:sshd ================================================ FILE: src/libssh/tests/etc/passwd.in ================================================ bob:x:5000:9000:bob gecos:@HOMEDIR@/bob:/bin/sh alice:x:5001:9000:alice gecos:@HOMEDIR@/alice:/bin/sh sshd:x:65530:65531:sshd:@HOMEDIR@:/sbin/nologin nobody:x:65533:65534:nobody gecos:@HOMEDIR@:/bin/false root:x:65534:65532:root gecos:@HOMEDIR@:/bin/false @LOCAL_USER@:x:@LOCAL_UID@:9000:local user:@HOMEDIR@:/bin/false ================================================ FILE: src/libssh/tests/etc/shadow.in ================================================ alice:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0::::: bob:$6$0jWkA8VP$MvBUvtGy38jWCZ5KtqnZEKQWXvvImDkDhDQII1kTqtAp3/xH31b71c.AjGkBFle.2QwCJQH7OzB/NXiMprusr/::0::::: ================================================ FILE: src/libssh/tests/fuzz/CMakeLists.txt ================================================ project(fuzzing CXX) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") add_executable(ssh_server_fuzzer ssh_server_fuzzer.cpp) set_target_properties(ssh_server_fuzzer PROPERTIES COMPILE_FLAGS "-fsanitize=fuzzer" LINK_FLAGS "-fsanitize=fuzzer") endif() ================================================ FILE: src/libssh/tests/fuzz/ssh_server_fuzzer.cpp ================================================ /* # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ################################################################################ */ #include #include #include #include #include #include #define LIBSSH_STATIC 1 #include #include static const char kRSAPrivateKeyPEM[] = "-----BEGIN RSA PRIVATE KEY-----\n" "MIIEowIBAAKCAQEArAOREUWlBXJAKZ5hABYyxnRayDZP1bJeLbPVK+npxemrhHyZ\n" "gjdbY3ADot+JRyWjvll2w2GI+3blt0j+x/ZWwjMKu/QYcycYp5HL01goxOxuusZb\n" "i+KiHRGB6z0EMdXM7U82U7lA/j//HyZppyDjUDniWabXQJge8ksGXGTiFeAJ/687\n" "uV+JJcjGPxAGFQxzyjitf/FrL9S0WGKZbyqeGDzyeBZ1NLIuaiOORyLGSW4duHLD\n" "N78EmsJnwqg2gJQmRSaD4BNZMjtbfiFcSL9Uw4XQFTsWugUDEY1AU4c5g11nhzHz\n" "Bi9qMOt5DzrZQpD4j0gA2LOHpHhoOdg1ZuHrGQIDAQABAoIBAFJTaqy/jllq8vZ4\n" "TKiD900wBvrns5HtSlHJTe80hqQoT+Sa1cWSxPR0eekL32Hjy9igbMzZ83uWzh7I\n" "mtgNODy9vRdznfgO8CfTCaBfAzQsjFpr8QikMT6EUI/LpiRL1UaGsNOlSEvnSS0Z\n" "b1uDzAdrjL+nsEHEDJud+K9jwSkCRifVMy7fLfaum+YKpdeEz7K2Mgm5pJ/Vg+9s\n" "vI2V1q7HAOI4eUVTgJNHXy5ediRJlajQHf/lNUzHKqn7iH+JRl01gt62X8roG62b\n" "TbFylbheqMm9awuSF2ucOcx+guuwhkPir8BEMb08j3hiK+TfwPdY0F6QH4OhiKK7\n" "MTqTVgECgYEA0vmmu5GOBtwRmq6gVNCHhdLDQWaxAZqQRmRbzxVhFpbv0GjbQEF7\n" "tttq3fjDrzDf6CE9RtZWw2BUSXVq+IXB/bXb1kgWU2xWywm+OFDk9OXQs8ui+MY7\n" "FiP3yuq3YJob2g5CCsVQWl2CHvWGmTLhE1ODll39t7Y1uwdcDobJN+ECgYEA0LlR\n" "hfMjydWmwqooU9TDjXNBmwufyYlNFTH351amYgFUDpNf35SMCP4hDosUw/zCTDpc\n" "+1w04BJJfkH1SNvXSOilpdaYRTYuryDvGmWC66K2KX1nLErhlhs17CwzV997nYgD\n" "H3OOU4HfqIKmdGbjvWlkmY+mLHyG10bbpOTbujkCgYAc68xHejSWDCT9p2KjPdLW\n" "LYZGuOUa6y1L+QX85Vlh118Ymsczj8Z90qZbt3Zb1b9b+vKDe255agMj7syzNOLa\n" "/MseHNOyq+9Z9gP1hGFekQKDIy88GzCOYG/fiT2KKJYY1kuHXnUdbiQgSlghODBS\n" "jehD/K6DOJ80/FVKSH/dAQKBgQDJ+apTzpZhJ2f5k6L2jDq3VEK2ACedZEm9Kt9T\n" "c1wKFnL6r83kkuB3i0L9ycRMavixvwBfFDjuY4POs5Dh8ip/mPFCa0hqISZHvbzi\n" "dDyePJO9zmXaTJPDJ42kfpkofVAnfohXFQEy+cguTk848J+MmMIKfyE0h0QMabr9\n" "86BUsQKBgEVgoi4RXwmtGovtMew01ORPV9MOX3v+VnsCgD4/56URKOAngiS70xEP\n" "ONwNbTCWuuv43HGzJoVFiAMGnQP1BAJ7gkHkjSegOGKkiw12EPUWhFcMg+GkgPhc\n" "pOqNt/VMBPjJ/ysHJqmLfQK9A35JV6Cmdphe+OIl28bcKhAOz8Dw\n" "-----END RSA PRIVATE KEY-----\n"; extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int socket_fds[2]; int res = socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds); assert(res >= 0); ssize_t send_res = send(socket_fds[1], data, size, 0); assert(send_res == size); res = shutdown(socket_fds[1], SHUT_WR); assert(res == 0); int fd = open("/tmp/libssh_fuzzer_private_key", O_WRONLY | O_CREAT, S_IRWXU); assert(fd >= 0); ssize_t write_res = write(fd, kRSAPrivateKeyPEM, strlen(kRSAPrivateKeyPEM)); assert(write_res == strlen(kRSAPrivateKeyPEM)); close(fd); ssh_bind sshbind = ssh_bind_new(); ssh_session session = ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "/tmp/libssh_fuzzer_private_key"); res = ssh_bind_accept_fd(sshbind, session, socket_fds[0]); assert(res == SSH_OK); if (ssh_handle_key_exchange(session) == SSH_OK) { while (true) { ssh_message message = ssh_message_get(session); if (!message) { break; } ssh_message_free(message); } } close(socket_fds[0]); close(socket_fds[1]); ssh_disconnect(session); ssh_free(session); ssh_bind_free(sshbind); return 0; } ================================================ FILE: src/libssh/tests/generate.py ================================================ #!/usr/bin/python import os a="" for i in xrange(4096): a+=chr(i % 256); while True: try: os.write(1,a) except: exit(0) ================================================ FILE: src/libssh/tests/keys/certauth/id_rsa ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEiwIBAAKB/QMTSsCQqarOIauonYgjAt8E+lgSWBU/43ITyDDzLM4IS4wCcqXB 1Fagz386FU1B2AcUqlPZ1+7RlaXkqgKr4nGHv00U/GG+YAUgUAw1G12kI4cvrnWr FIXwcq+VTJNej5pHxEqcRLw7ZBorpqm2UsY5KLr5R3uMNap7koj1Hbt9lKsvfDn6 HjM4qY0ygx8hxf/4wCzIh5V4k9/UAMkqI2CM9c3yEE2aWh/4MDOnAFj+0T2sMAo8 jyOZ6v+W7hmEtsUc9mEv+5B+hhVeYO/RwxketJAQRPYDSPSi1mjtv9fnzGk15q/l Hb2V/HP/pyIpao19A4daR0a4ia9Hk4UCAwEAAQKB/QKEaPxjrKzlWoQSWRdUaQY5 Idyy7yw9hiMa9BK1COh/u66XVlY86Fwb9puR5Fu/WF67WIuX1PpizJXkLBBRtuDs lvY2BjrPQ/MONtc3JPYp4vbFXYxtAzh6zrTPhMVfcjV7Jr1XWZ+lEVOmhR2G4gvk P2WDozIKWub3jMLTt4afgHCGaKfKEUpKjFkiAalz8oLVv8qV1FVPPDT2PWeKMuE3 XfoN7YUaP6+aPlNnjIv/3BDsrPsiKZ+AKXcERdPvVQa/LypzW08cqC6sIJKWVmQI 3KgoYs9VvbDXfQ8jKfcsTApZkSDaLX6tf3Ei+76R0lbV4L1rpypa25qj9YECfwHP N+v/6yObJFL5/1rEuT7CFbfP8g5J8qUVufcPRKv//ChluLuWNxgLJmIv2ZffWwhe GKHlT98QPgFvsMSOyLeut4beZYKDSeVNvEt9eCBjOax2jOBGo3hv8j/Fs8yAfZOV Ardv2qUszubM+DVwjJzb3vaZyEesRucJISqkJeUCfwGzGdMp0LXrZ7aaQGgHj/P2 DKGq0E2gnj/EBapatjxKm4hMRn/vkTWjCDCryTnvJqkW/00tr4GqWXoeilBFD270 RcvbOe9LQmGlHIYzgwc5nfLDBQyeNnHRmkeD9LQRUfdTdHj4jf+35pHlsVUT0Rnl IMNoRA6V07bySFdI3SECfiF+1rbrxuhaCRIA0Ax3pL0eGuuTgksAm8VlbCMTgSiC kF1CrXXgSAHOZb02C9Bf4cwEFfjh/KxM/4eXDa+Rfg7JQJxmVLivqEAlxIOvIxBp xDnSWAljmrrllozyQnBsJDbbOm6BLf5+e5wIuryHvnP7vHNEU0J24g/78PxrrQJ/ AVD4OzYzUfESzbUBFJBmyIZSmhJ0aOpwJOpniNvgLymI8zI/l22uhF/TQ/6HRbsV sfcBmoA7YKzRx2ZHsIsLvN6p/4u1fsJGkuERCk5yt/HDhfPLwU321IeEeMaVia+w T1/u4JF/SADhLTU69az3UJrHmQ7zRmh7I0DZDeB8gQJ+XqIqutPeerNtbqMjXGW8 TdpqZAzAQAv6dPgaH0W0OzJe2hP9uy0D84H5f8Im/irJh/AXo/QL3obXqopyeLf0 HfcUUnEZEBPlqsirZFtPClD+HL6Orf1je0oVV/aQssPkQl6/aXBNd+kS27U3NBML LmRhC4+Q+/M5MlRggLtn -----END RSA PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/certauth/id_rsa-cert.pub ================================================ ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgHZLan4ufbTFWr8Hl/8JvZTLYa0eNNm2qov9zPlK7qfwAAAADAQABAAAA/QMTSsCQqarOIauonYgjAt8E+lgSWBU/43ITyDDzLM4IS4wCcqXB1Fagz386FU1B2AcUqlPZ1+7RlaXkqgKr4nGHv00U/GG+YAUgUAw1G12kI4cvrnWrFIXwcq+VTJNej5pHxEqcRLw7ZBorpqm2UsY5KLr5R3uMNap7koj1Hbt9lKsvfDn6HjM4qY0ygx8hxf/4wCzIh5V4k9/UAMkqI2CM9c3yEE2aWh/4MDOnAFj+0T2sMAo8jyOZ6v+W7hmEtsUc9mEv+5B+hhVeYO/RwxketJAQRPYDSPSi1mjtv9fnzGk15q/lHb2V/HP/pyIpao19A4daR0a4ia9Hk4UAAAAAAAAAAAAAAAEAAAATdG9ydHVyZV9hdXRoX2NhcmxvcwAAAAkAAAAFYWxpY2UAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAKcDafm8fNluz8a9GQaWgk1XUJcchLleeubTke6xQlJbI+rcjWIIwd1gDuh7Mdr0YIVhsh6dpg/L4bpRJBGNhDPxK8BmjTpIU14lKxrWQAirHN09P2QGtGtgrf09lA+xhV9E+pkF2Zz6PCt/P3sgUQnJcwjjsWhMaSASrt67fPanH+10hnfgjkevkMMHGJxmLiOW7JFQkd9I+gHHKEXs6Q9fhtiStzr3WN4hAPG5uXrnRZgseAV9p3TFPMEgUTpdRvnkOnkCBF169KiyjU97QgoXHExWk/rrgsJtgrTou/qRyi18WWm9S1HXLHyNOgZxKirmxLNPC9dIcJBD1kDWG8UAAAEPAAAAB3NzaC1yc2EAAAEAhNLOXT0jyz/Web0HUyrtPCvUZsLkDyBWCNoNTfsxGVoYsE4WCpNwqQO1A4NT5AtIE+R7rn9wfjvXM7sYh6hJyq3HVEWhts1SkQVU7sQBrImTIrj2cWKR3gmQ+ehsgNFGhcFZTK77ugw1fMfzZRvKVTkRWhe6v92wQOtkoINtf3f1fK6xY+vLwAA/E4VdaRJmhwAaNpy3PfMAJytkCLjcjUSWHYDha4hs98/EBPduGNNNiZdyG7lcpSvvq9HBDxzOiHBa/We9m38/Dk4TNVkZ/wrtBFQxH75if6SgGa/feGJrKQHBru7sPh8dO4R1AmZaoLmRzMnzZOtB0oEXmBqHmw== libssh_torture_auth ================================================ FILE: src/libssh/tests/keys/certauth/id_rsa.pub ================================================ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/QMTSsCQqarOIauonYgjAt8E+lgSWBU/43ITyDDzLM4IS4wCcqXB1Fagz386FU1B2AcUqlPZ1+7RlaXkqgKr4nGHv00U/GG+YAUgUAw1G12kI4cvrnWrFIXwcq+VTJNej5pHxEqcRLw7ZBorpqm2UsY5KLr5R3uMNap7koj1Hbt9lKsvfDn6HjM4qY0ygx8hxf/4wCzIh5V4k9/UAMkqI2CM9c3yEE2aWh/4MDOnAFj+0T2sMAo8jyOZ6v+W7hmEtsUc9mEv+5B+hhVeYO/RwxketJAQRPYDSPSi1mjtv9fnzGk15q/lHb2V/HP/pyIpao19A4daR0a4ia9Hk4U= libssh_torture_auth ================================================ FILE: src/libssh/tests/keys/id_ecdsa ================================================ -----BEGIN EC PRIVATE KEY----- MHcCAQEEIHbL0nzpzLS3ImIlhEffbDzPlIw/tn5QcfB64PbSiBl6oAoGCCqGSM49 AwEHoUQDQgAERzA8X8OP7C3W/e1UNLh+21xIZVBiQ7i4Qb4xoOebRWuwzitEZon/ 8Dz+VpE29krJgCagqSt5RLllOx8eS2i8fw== -----END EC PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/id_ecdsa.pub ================================================ ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEcwPF/Dj+wt1v3tVDS4fttcSGVQYkO4uEG+MaDnm0VrsM4rRGaJ//A8/laRNvZKyYAmoKkreUS5ZTsfHktovH8= comment ================================================ FILE: src/libssh/tests/keys/id_ed25519 ================================================ -----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACCLo6vx1lX6ZZoe05lWTkuwrJUZN0T8hEer5UF9KPhOVgAAAKg+IRNSPiET UgAAAAtzc2gtZWQyNTUxOQAAACCLo6vx1lX6ZZoe05lWTkuwrJUZN0T8hEer5UF9KPhOVg AAAED2zFg52qYItoZaSUnir4VKubTxJveL9D2oWK7Prg/O24ujq/HWVfplmh7TmVZOS7Cs lRk3RPyER6vlQX0o+E5WAAAAHmpqZWxlbkB0NDcwcy5qamVsZW4ucmVkaGF0LmNvbQECAw QFBgc= -----END OPENSSH PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/id_ed25519.pub ================================================ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIujq/HWVfplmh7TmVZOS7CslRk3RPyER6vlQX0o+E5W jjelen@t470s.jjelen.redhat.com ================================================ FILE: src/libssh/tests/keys/id_rsa ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAs/fIz+Gy89XjUhXebNq2rs1K0RJEZXDbfcofb13ESDJ9fSbd +RlCUM6i+foEVV23xWdands2Bkn72tGinJadIgOWU+koxp+gRmtJLE/ONiAKJQqR K3eOJNBH6At96NMqJ4Gwv56G4W68uPgDwUVQwVIc6Ec6Rypiz7DE+S++gSvBQIVU Qt7XkPcXOyN5zuj5qDhZM4l6V7Og9LWj4/2IF5acvKjfIMpeqmnp9z6BTYZQtuQU 6b1VuEYhXyvM6LkMwndsVGh46kDKMmRQhyA8A6qvLAliMMq88k5gR4AeJeTnqDR/ Q120I6PMqYNl6TLTk8/KonOOPDR/XXGb3iF67wIDAQABAoIBAAVoL2dXf5nl1jOU Jp+cnpp33oSTiOyHTIDl/rXI2mnU4oJNFaQzRxPIcYsTIOgzrZ7HsShG+sOLm36C h+EugUARXYXd3nTBPP6AoK0tJKPpqIReYegtal7exxpIphrFpWGUeuv25lSFkDP6 d5pp67gzMF0mLrEOq/NTe0eFULLuwa6+IKXU7deiU90pzi4jrjcIWNoGHSw1YYAZ TC8KAxA/tYH9myya5krRCjA9B345DJ9Wd71wX+RZNgbSkIri/6dDTtvsYvqcQKo0 OZ3MUDJnKmkfPLP84qZPRoEwUI1gts1WUdoNK6LK7yOJmPL5FMyTwZx3XtDw3gAv TVhI7ikCgYEA5Ay0TCySPQAaC14WtjgIAmTa19mAtOFpbRxToi40WjXk3R6mMqyp biAcNecdZRC6zzgAUp8g1O3Yc1d9fG/3FpM5eUbIer7mMLTRuQQysoJY2Ayw9OEA qPHS/K6LPOD09aZo14fRUqVO8rwMbHtq2yhH8p3FM8WZRe5ms8zpyLUCgYEAygZ3 RTMWbgcGdNoaPa5Ms9KRqAxKJLin2fE99KowZeJfvZN24sXExawQdy4BKVYT0H6e MNEIPiEBVA4a1GDk/tyOrEt684IsidROngJaGbqb+SYm6feQAioYu0wkG/I2hS12 /Z/aK6wFz5hWzBv/YvJqC7xD1YwZm1QXDyAiL5MCgYAXz8fHqGPAoNEXXMSsVB9p +JPtM9W/jUXP0cRdy8tFnBkAiaG66tJqIEoxyqcEFYIb/vHxrpHkCc2vBXSh2KMJ JWg75IssXeB1N3wqgGi2wOt7659SgmfqPA3WunbpbWfGepC56IGPypj6uW3mqeBX b9ZLW/PqWviNF757iarjfQKBgGxKBPqRxM8bcumF0xUG7dRh5XN3ivKeDFL1Tels pF6odftPJSWvLqdqcLUBctvuaNaUWEUAdvOei3C70sPOYFEAdnWCTBhkyWzj4XQu /I7YCS0Gt0soSQfv+qvCx4Q3U+QVF7ghTDemkMLS/IuR4lXubMt3kcDQxRUOgQG5 jrmDAoGALauF7ZyzEnQgsgMVzfm9znl5I2aIsLgdsAv3lINVrvtTKhddp7cdd+2j dwZlaMnLET/3MY/Cvf13vEsS+bdNXjsdQidqBL8pe5PXY/pafBhtduQuvGzlHJA5 CEBnwB0SdtsXbzSpOAPZqea4Nz9MkQ8LMsINdPpxCuFhjeYa9Ow= -----END RSA PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/id_rsa.pub ================================================ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz98jP4bLz1eNSFd5s2rauzUrREkRlcNt9yh9vXcRIMn19Jt35GUJQzqL5+gRVXbfFZ1qd2zYGSfva0aKclp0iA5ZT6SjGn6BGa0ksT842IAolCpErd44k0EfoC33o0yongbC/nobhbry4+APBRVDBUhzoRzpHKmLPsMT5L76BK8FAhVRC3teQ9xc7I3nO6PmoOFkziXpXs6D0taPj/YgXlpy8qN8gyl6qaen3PoFNhlC25BTpvVW4RiFfK8zouQzCd2xUaHjqQMoyZFCHIDwDqq8sCWIwyrzyTmBHgB4l5OeoNH9DXbQjo8ypg2XpMtOTz8qic448NH9dcZveIXrv asn@krikkit.cryptomilk.site ================================================ FILE: src/libssh/tests/keys/ssh_host_dsa_key ================================================ -----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQD7vBS+d/eJP6wK2VQw+8AIfgCw9IR50utLRkkrWbfDdiM7V+fp tJYKCyqZT9j9ANhqicB2tuqAI6WJBZMaGekxWfI30JxPkHZrrwbdFzlRbjav07lg IKqWgcz81iVPmfn5savEoobiSFjJNMmYcizjKZgGmyNUzlJjzF7u5qD08wIVAPFp 6VKuv8VxNjENciUZCdEDRW/lAoGBAN/BFSBRSP9frsHID6e2NeKHqs8JDUWhCTE9 /WQKqUUbxO2UU98CfHuf1mNlaSsrOxaBdvTeURcZZc1svhyGr1VG+NbNTDDlzTgA UlrzNML61TYcFXQVxgifUy+Tmh8FRGCa6Ko/EsX4ZWLTto5w1u5cPpgzSbLMco9T AeeNLgYNAoGAJRuawWN3+NezI7+bBe42Kjg4gVUlpS+8TTlYFbwrM1Esab7gvxHB /b2apbk9xIAkkqsnb+EPrXTLUdE2Y7XkEuGLLSTus2UlZKobBGBX/Ioysg5W9Fk/ 2MhI4YssRb2alar8d+gmAHPaT+D+NDd90PBfY3HqcXFEK+eDTWo1JNICFBLdsuoO 6pObeFSOYbr38kJzZ0xG -----END DSA PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/ssh_host_dsa_key.pub ================================================ ssh-dss AAAAB3NzaC1kc3MAAACBAPu8FL5394k/rArZVDD7wAh+ALD0hHnS60tGSStZt8N2IztX5+m0lgoLKplP2P0A2GqJwHa26oAjpYkFkxoZ6TFZ8jfQnE+QdmuvBt0XOVFuNq/TuWAgqpaBzPzWJU+Z+fmxq8SihuJIWMk0yZhyLOMpmAabI1TOUmPMXu7moPTzAAAAFQDxaelSrr/FcTYxDXIlGQnRA0Vv5QAAAIEA38EVIFFI/1+uwcgPp7Y14oeqzwkNRaEJMT39ZAqpRRvE7ZRT3wJ8e5/WY2VpKys7FoF29N5RFxllzWy+HIavVUb41s1MMOXNOABSWvM0wvrVNhwVdBXGCJ9TL5OaHwVEYJroqj8SxfhlYtO2jnDW7lw+mDNJssxyj1MB540uBg0AAACAJRuawWN3+NezI7+bBe42Kjg4gVUlpS+8TTlYFbwrM1Esab7gvxHB/b2apbk9xIAkkqsnb+EPrXTLUdE2Y7XkEuGLLSTus2UlZKobBGBX/Ioysg5W9Fk/2MhI4YssRb2alar8d+gmAHPaT+D+NDd90PBfY3HqcXFEK+eDTWo1JNI= asn@magrathea ================================================ FILE: src/libssh/tests/keys/ssh_host_ecdsa_key ================================================ -----BEGIN EC PRIVATE KEY----- MHcCAQEEIB9v2n1oaXvBECf0gDPxTibeUPvvkI1anNWDAIkNjs5JoAoGCCqGSM49 AwEHoUQDQgAEqkTqNu7gRegPJRy0WiseJz9NAdBimzyNSzNwI5eAkEqv9D6Y95KL 7DBEnDQ2p08iOLw+vN1PKHsCM7b/ONbYVg== -----END EC PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/ssh_host_ecdsa_key.pub ================================================ ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKpE6jbu4EXoDyUctForHic/TQHQYps8jUszcCOXgJBKr/Q+mPeSi+wwRJw0NqdPIji8PrzdTyh7AjO2/zjW2FY= asn@magrathea ================================================ FILE: src/libssh/tests/keys/ssh_host_key.pub ================================================ 2048 65537 25221975523736997039149017470335977198642717886559395625730372192276493838727011206749822289920387480933533054627057418868711378045090730895752530916661328094497437687453813456961487210492465678475508526337829331199296553120728607984859224949182503917312492825658971738208505685553964707412720244524969161284321098487507924676797222812771309962906894332072854924265623785469343453142982185436565166155021228521252914913227554455102103918367844210755391318078654400527927267478149210805219779896806429660492177158822689909493046725157917529664436252598971135251689616517266344945600782273453037452082373553352939812279 asn@magrathea ================================================ FILE: src/libssh/tests/keys/ssh_host_rsa_key ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAqzabeU0oKbHDwdlqindABvtzgWCvXdHJ+d2Ew6te2LXjkwju y7u6B7y63NZRy57ccrE4YSeWItVoZn+DWN+guU354Ss/tzQ9/thUmLrvtKNvJwuF F5Ch7Q4BsrXGsb2GSv+7W5tpx3yAqH1TvKQj/MmQVX+/9KtXEnh7/vpiCqoOXQAR zvIIQxoo1aUQBHAkRW7Yw0Ds7AjC9uV1ns4xdBXPQmDk23pWvCq7E+7rOEbKRrjj lApS4lJYy0oEXsFdqUPd+PtT1gG0nIElHFQtsTgUvwYQmJEzrBxv41odwRvxbMjg THPr4SLRRRSuPwICWyvxqPpa7EsfMBnbPEIUzQIDAQABAoIBAEUO15MLvgFjRDQy P7jt9JNcZPBwUQukjLUN1nkd7Dm407wAxGDErXplc3GTuJZK01wngzgcwX/3WA7P q+jy+l8DxqA904tPtRnPo/+elwTjTvgOu3YPzmBRX/n3O9eBPGOP1sBSZU4jN7m+ I0JZanKR0nfJ+WD0o0A9/LWRxG3MFIntBamtT6pgee8sAu44IvW0o7tHJabMq02J Z/ndrJmox34wq6SMFANax+N1x9sZa60bL7gEoDWQJNKOaMrbtOaIoTGFIc4hFqoA SzjNqcGsHPWs44cw0mNkUGq37jEvaCwzAp+U80ma1skBhXuJL9sQOxl1v5qW91c/ Cnm5WYECgYEA4DPvqbLt+VdyTtmCQ370yiCk4OPPMPzbM65IVKgQL/rN6HdNShTO uLF6P8XC8vNP2OSydJeFt+kMKd7E/4o5LfvEqUGXZJDkB7fLjrOjyZU3bxtIx95x qYGWRcWbd3sHzlBJGuFVSE7GREE+lqhkSu4ry4l/GAKxSymAXgGd/9ECgYEAw37L ppZIavcLE2rZgXHoqMiJzeGzsidJbkHss4k7ubLe8vyBMiv0HC2anxPa2+yNWuF2 +pEr84bllh149VKeild24UEBAR2w/P41ggWqiUP7PKllh+huWzG4+KNFbfUP4dd0 4LkVgfsCz32qD8qxXNCxJCZ8H2fmjKsYw/oCID0CgYAiuSh3GdUtdtOnTpyUI4d5 /pBKnD2skpzIZkehhN3s8GUPidqYjJxvkl0in1hQFErbhp/02rrE/vz5Rx0vjpLI gmO06wmtc5s9bsPB+CR3xfpt5MXi3pqv6/gAGli3qoBM/bY0yY1Rw5GFZK1y2+Wc jUKPJV5fs5sNzwGojYuQ4QKBgQCNNgqOo2Fd+mLCvNyt1wTy3iBEWfL+DcjJ3s7G hKtioKTQqbn87qjercZRf/sH/t/ANLpHlhNETj2KaHGV6v7f+PvDC7xY/QR6SnmG GOetTTCuCcJwIGGOd+UfnHgrS+gT/xjKtoalpBXMoP31eDkTTR+XeEESQm/TTkeO UAm3FQKBgD8Y7CLHpyZZ+eOnxRSPU4m4AWAEp7JOwHDRWWQeUornrXDYgD87d2M9 iIAEuOzNggA56Nm3AzBOPRj4HkBh57ToVKPswHwB0oWvrtSjpLkkU6q8xRG3XuJD 2AskDaZONzIDoJGfZ3+W7YbKELK7DPtFXL15sOfBmpoEkI9RA5vM -----END RSA PRIVATE KEY----- ================================================ FILE: src/libssh/tests/keys/ssh_host_rsa_key.pub ================================================ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCrNpt5TSgpscPB2WqKd0AG+3OBYK9d0cn53YTDq17YteOTCO7Lu7oHvLrc1lHLntxysThhJ5Yi1Whmf4NY36C5TfnhKz+3ND3+2FSYuu+0o28nC4UXkKHtDgGytcaxvYZK/7tbm2nHfICofVO8pCP8yZBVf7/0q1cSeHv++mIKqg5dABHO8ghDGijVpRAEcCRFbtjDQOzsCML25XWezjF0Fc9CYOTbela8KrsT7us4RspGuOOUClLiUljLSgRewV2pQ934+1PWAbScgSUcVC2xOBS/BhCYkTOsHG/jWh3BG/FsyOBMc+vhItFFFK4/AgJbK/Go+lrsSx8wGds8QhTN asn@magrathea ================================================ FILE: src/libssh/tests/keys/user_ca ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEApwNp+bx82W7Pxr0ZBpaCTVdQlxyEuV565tOR7rFCUlsj6tyN YgjB3WAO6Hsx2vRghWGyHp2mD8vhulEkEY2EM/ErwGaNOkhTXiUrGtZACKsc3T0/ ZAa0a2Ct/T2UD7GFX0T6mQXZnPo8K38/eyBRCclzCOOxaExpIBKu3rt89qcf7XSG d+COR6+QwwcYnGYuI5bskVCR30j6AccoRezpD1+G2JK3OvdY3iEA8bm5eudFmCx4 BX2ndMU8wSBROl1G+eQ6eQIEXXr0qLKNT3tCChccTFaT+uuCwm2CtOi7+pHKLXxZ ab1LUdcsfI06BnEqKubEs08L10hwkEPWQNYbxQIDAQABAoIBACW2AaHgS5iVCtln LVVterKX+pyEVfu9N6cTMqpg4AbUiYGol0wBijTAUd1wo8s6zuiPLLb5BdwfPzLg y3IjMCzCUgy5mz4Dwr9JSThgFElgyb2y7LNbSDXOuLqrwtjgTqs6WhNfXMmzPw7b Rqw4mdPJ5u2k7BQO3NXfIhks4ISYzpzNAwj1a2NMphvkZyvfRnWiQ0pvEXQCxwuR 74iGpPFeyFjjku/O4TiHZllPmDdD3ERalkf8RIudQ5gcbL4fRoONTzfZHtmARWoP Jury4Zfr5b3VGSnkUDaGlzilXvBusAZOCaaU7chvOPVjXMbSAUEpFBmnRHk5dfrH fCXECcECgYEA0KMtV3IzwMToVdvzcMQc1ovDvKZAQPneLTxFgNpOeycOhzulzY9p 3fRi5QUOA/Ff+LcCL86APqwoEYe4bgam6mwGFFhv1usf4ulbLNk8ZeR51CG6emPt tLpg6PThxhMnNpu+StrBAOxeo9pZGd+Plt6d4vfoalOHVkPlSv7OC9kCgYEAzO1I HuZAQkVdKLGuZlf8E4VEaiMBKdl5+H+8w9peOOax6nqAIrwp2d0aZ52LDjwg7d3C eSmxu0U1jsbzexVVePr/NmdJOu3+gB0GvlzRjS1xT+MCZIye5a7Nxc7lBp5rFmgV dJTA6XXRoykinZIxz068SHqtNhNOzO4hUmPDN80CgYAlxOR4aBwmUX8dy+uOBnKS BEsy44XOPW2TEs4iPWLnuHJQ2ONzCvtHSu58NyYKYK/W/opOzTs6HUBDrCYfBOVC mrufA0N7zKTBFy2COPFOIMZNOK3haiWmCfdxNKOKj/0RTbBtLJyz5hZb4zMuE+KS lUpPxEE2vlhJrZDcurPiQQKBgQCIEqMKCX/vwVlLlTglsxSp7ZrxEw9Jt6O68y7n qc9Y3y6ScQc2iVUM2jkXRlA4goqnB9KDW8EthZY7mTXBq/fWXmwqtsi0faW5cgyx SLbIlL0h+63yEEHOZ5UxXOFM1NJszW45vDCglOBABCd9E79JVZHGWtc7CfUQNKsh pybQnQKBgHbPnITR7esVQYLq3PHSsdOdkFiiVf3D7wHiNZcXWjJvUqMF4tH5XAzY QafKqKk0FzO92ZOhQeB5xauFY5wzsa+Xl8cQkyvtWngFIKbWydEehZWVgXcedxEC xjbZWKmsYDqBYi3bw9Dxb0AvT+kDtq0Azi8QTDAvRwylvtkYj/V8 -----END RSA PRIVATE KEY----- ================================================ FILE: src/libssh/tests/pkd/CMakeLists.txt ================================================ project(pkd C) if (WITH_SERVER AND UNIX AND NOT WIN32) include_directories(${libssh_SOURCE_DIR}/include ${libssh_BINARY_DIR}/include ${CMOCKA_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${CMAKE_BINARY_DIR} ${libssh_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}) set(pkd_hello_src pkd_daemon.c pkd_hello.c pkd_keyutil.c pkd_util.c ) set(pkd_libs ${CMOCKA_LIBRARY} ssh::static ${ARGP_LIBRARIES} pthread ) add_executable(pkd_hello ${pkd_hello_src}) target_compile_options(pkd_hello PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(pkd_hello ${pkd_libs}) # # pkd_hello_i1 runs only one iteration per algorithm combination for # sake of speeding up overall test run time. More iterations can be # specified with `-i` and may be helpful for chasing down bugs that # are not 100% reproducible. # add_test(pkd_hello_i1 ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -e -o -i1 -w /tmp/pkd_socket_wrapper_XXXXXX) # # pkd_hello_rekey is used to test server-side implementation of rekeying. # add_test(pkd_hello_rekey ${CMAKE_CURRENT_BINARY_DIR}/pkd_hello -t torture_pkd_openssh_rsa_rsa_default -i1 --rekey=16 -v -v -v -w /tmp/pkd_socket_wrapper_XXXXXX) # # Configure environment for cwrap socket wrapper. # find_package(socket_wrapper 1.1.5 REQUIRED) if (OSX) set(PKD_ENVIRONMENT "DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${SOCKET_WRAPPER_LIBRARY}") else () set(PKD_ENVIRONMENT "LD_PRELOAD=${SOCKET_WRAPPER_LIBRARY}") endif () message(STATUS "PKD_ENVIRONMENT=${PKD_ENVIRONMENT}") set_property(TEST pkd_hello_i1 PROPERTY ENVIRONMENT ${PKD_ENVIRONMENT}) endif (WITH_SERVER AND UNIX AND NOT WIN32) ================================================ FILE: src/libssh/tests/pkd/pkd_client.h ================================================ /* * pkd_client.h -- macros for generating client-specific command * invocations for use with pkd testing * * (c) 2014, 2018 Jon Simons */ #ifndef __PKD_CLIENT_H__ #define __PKD_CLIENT_H__ #include "config.h" #include "tests_config.h" /* OpenSSH */ #define OPENSSH_BINARY SSH_EXECUTABLE #define OPENSSH_KEYGEN "ssh-keygen" #define OPENSSH_HOSTKEY_ALGOS \ "-o HostKeyAlgorithms=" \ OPENSSH_KEYS #define OPENSSH_PKACCEPTED_TYPES \ "-o PubkeyAcceptedKeyTypes=" \ OPENSSH_KEYS #define OPENSSH_CMD_START(hostkey_algos) \ OPENSSH_BINARY " " \ "-o UserKnownHostsFile=/dev/null " \ "-o StrictHostKeyChecking=no " \ "-F /dev/null " \ hostkey_algos " " \ OPENSSH_PKACCEPTED_TYPES " " \ "-i " CLIENT_ID_FILE " " \ "1> %s.out " \ "2> %s.err " \ "-vvv " #define OPENSSH_CMD_END "-p 1234 localhost ls" #define OPENSSH_CMD \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) OPENSSH_CMD_END #define OPENSSH_KEX_CMD(kexalgo) \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) "-o KexAlgorithms=" kexalgo " " OPENSSH_CMD_END #define OPENSSH_CIPHER_CMD(ciphers) \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) "-c " ciphers " " OPENSSH_CMD_END #define OPENSSH_MAC_CMD(macs) \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) "-c aes128-ctr,aes192-ctr,aes256-ctr,aes256-cbc,aes192-cbc,aes128-cbc -o MACs=" macs " " OPENSSH_CMD_END #define OPENSSH_HOSTKEY_CMD(hostkeyalgo) \ OPENSSH_CMD_START("-o HostKeyAlgorithms=" hostkeyalgo " ") OPENSSH_CMD_END #define OPENSSH_CERT_CMD \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) "-o CertificateFile=" CLIENT_ID_FILE "-cert.pub " OPENSSH_CMD_END #define OPENSSH_SHA256_CERT_CMD \ OPENSSH_CMD_START(OPENSSH_HOSTKEY_ALGOS) "-o CertificateFile=" CLIENT_ID_FILE "-sha256-cert.pub " OPENSSH_CMD_END /* Dropbear */ #define DROPBEAR_BINARY "dbclient" #define DROPBEAR_KEYGEN "dropbearkey" #define DROPBEAR_CMD_START \ DROPBEAR_BINARY " " \ "-y -y " \ "-i " CLIENT_ID_FILE " " \ "1> %s.out " \ "2> %s.err " #define DROPBEAR_CMD_END "-p 1234 localhost ls" #define DROPBEAR_CMD \ DROPBEAR_CMD_START DROPBEAR_CMD_END #if 0 /* dbclient does not expose control over kex algo */ #define DROPBEAR_KEX_CMD(kexalgo) \ DROPBEAR_CMD #endif #define DROPBEAR_CIPHER_CMD(ciphers) \ DROPBEAR_CMD_START "-c " ciphers " " DROPBEAR_CMD_END #define DROPBEAR_MAC_CMD(macs) \ DROPBEAR_CMD_START "-m " macs " " DROPBEAR_CMD_END #endif /* __PKD_CLIENT_H__ */ ================================================ FILE: src/libssh/tests/pkd/pkd_daemon.c ================================================ /* * pkd_daemon.c -- a sample public-key testing daemon using libssh * * Uses public key authentication to establish an exec channel and * echo back payloads to the user. * * (c) 2014 Jon Simons */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "torture.h" // for ssh_fips_mode() #include "pkd_daemon.h" #include // for cmocka #include static int pkdout_enabled; static int pkderr_enabled; static void pkdout(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); static void pkderr(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); static void pkdout(const char *fmt, ...) { va_list vargs; if (pkdout_enabled) { va_start(vargs, fmt); vfprintf(stdout, fmt, vargs); va_end(vargs); } } static void pkderr(const char *fmt, ...) { va_list vargs; if (pkderr_enabled) { va_start(vargs, fmt); vfprintf(stderr, fmt, vargs); va_end(vargs); } } /* * pkd state: only one thread can run pkd at a time --------------------- */ static struct { int rc; pthread_t tid; int keep_going; volatile int pkd_ready; } ctx; static struct { int server_fd; int req_exec_received; int close_received; int eof_received; } pkd_state; static void pkd_sighandler(int signum) { (void) signum; } static int pkd_init_libssh(void) { int rc = ssh_threads_set_callbacks(ssh_threads_get_pthread()); return (rc == SSH_OK) ? 0 : 1; } static int pkd_init_server_fd(short port) { int rc = 0; int yes = 1; struct sockaddr_in addr; int server_fd = socket(PF_INET, SOCK_STREAM, 0); if (server_fd < 0) { rc = -1; goto out; } rc = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (rc != 0) { goto outclose; } memset(&addr, 0x0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; rc = bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)); if (rc != 0) { goto outclose; } rc = listen(server_fd, 128); if (rc == 0) { goto out; } outclose: close(server_fd); server_fd = -1; out: pkd_state.server_fd = server_fd; return rc; } static int pkd_accept_fd(void) { int fd = -1; struct sockaddr_in addr; socklen_t len = sizeof(addr); do { fd = accept(pkd_state.server_fd, (struct sockaddr *) &addr, &len); } while ((ctx.keep_going != 0) && (fd < 0) && (errno == EINTR)); return fd; } static void pkd_eof(ssh_session session, ssh_channel channel, void *userdata) { (void) session; (void) channel; (void) userdata; pkdout("pkd_eof\n"); pkd_state.eof_received = 1; } static void pkd_chan_close(ssh_session session, ssh_channel channel, void *userdata) { (void) session; (void) channel; (void) userdata; pkdout("pkd_chan_close\n"); pkd_state.close_received = 1; } static int pkd_req_exec(ssh_session s, ssh_channel c, const char *cmd, void *userdata) { (void) s; (void) c; (void) cmd; (void) userdata; /* assumes pubkey authentication has already succeeded */ pkdout("pkd_req_exec\n"); pkd_state.req_exec_received = 1; return 0; } /* assumes there is only ever a single channel */ static struct ssh_channel_callbacks_struct pkd_channel_cb = { .channel_eof_function = pkd_eof, .channel_close_function = pkd_chan_close, .channel_exec_request_function = pkd_req_exec, }; static int pkd_auth_pubkey_cb(ssh_session s, const char *user, ssh_key key, char state, void *userdata) { (void) s; (void) user; (void) key; (void) state; (void) userdata; pkdout("pkd_auth_pubkey_cb keytype %s, state: %d\n", ssh_key_type_to_char(ssh_key_type(key)), state); if ((state == SSH_PUBLICKEY_STATE_NONE) || (state == SSH_PUBLICKEY_STATE_VALID)) { return SSH_AUTH_SUCCESS; } return SSH_AUTH_DENIED; } static int pkd_service_request_cb(ssh_session session, const char *service, void *userdata) { (void) session; (void) userdata; pkdout("pkd_service_request_cb: %s\n", service); return (0 == (strcmp(service, "ssh-userauth"))) ? 0 : -1; } static ssh_channel pkd_channel_openreq_cb(ssh_session s, void *userdata) { ssh_channel c = NULL; ssh_channel *out = (ssh_channel *) userdata; /* assumes pubkey authentication has already succeeded */ pkdout("pkd_channel_openreq_cb\n"); c = ssh_channel_new(s); if (c == NULL) { pkderr("ssh_channel_new: %s\n", ssh_get_error(s)); return NULL; } ssh_callbacks_init(&pkd_channel_cb); pkd_channel_cb.userdata = userdata; if (ssh_set_channel_callbacks(c, &pkd_channel_cb) != SSH_OK) { pkderr("ssh_set_channel_callbacks: %s\n", ssh_get_error(s)); ssh_channel_free(c); c = NULL; } *out = c; return c; } static struct ssh_server_callbacks_struct pkd_server_cb = { .auth_pubkey_function = pkd_auth_pubkey_cb, .service_request_function = pkd_service_request_cb, .channel_open_request_session_function = pkd_channel_openreq_cb, }; static int pkd_exec_hello(int fd, struct pkd_daemon_args *args) { int rc = -1; ssh_bind b = NULL; ssh_session s = NULL; ssh_event e = NULL; ssh_channel c = NULL; enum ssh_bind_options_e opts = -1; int level = args->opts.libssh_log_level; enum pkd_hostkey_type_e type = args->type; const char *hostkeypath = args->hostkeypath; const char *default_kex = NULL; char *all_kex = NULL; size_t kex_len = 0; const char *all_ciphers = NULL; const uint64_t rekey_data_limit = args->rekey_data_limit; bool process_config = false; pkd_state.eof_received = 0; pkd_state.close_received = 0; pkd_state.req_exec_received = 0; b = ssh_bind_new(); if (b == NULL) { pkderr("ssh_bind_new\n"); goto outclose; } if (type == PKD_RSA) { opts = SSH_BIND_OPTIONS_RSAKEY; } else if (type == PKD_ED25519) { opts = SSH_BIND_OPTIONS_HOSTKEY; #ifdef HAVE_DSA } else if (type == PKD_DSA) { opts = SSH_BIND_OPTIONS_DSAKEY; #endif } else if (type == PKD_ECDSA) { opts = SSH_BIND_OPTIONS_ECDSAKEY; } else { pkderr("unknown hostkey type: %d\n", type); rc = -1; goto outclose; } rc = ssh_bind_options_set(b, opts, hostkeypath); if (rc != 0) { pkderr("ssh_bind_options_set: %s\n", ssh_get_error(b)); goto outclose; } rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_LOG_VERBOSITY, &level); if (rc != 0) { pkderr("ssh_bind_options_set log verbosity: %s\n", ssh_get_error(b)); goto outclose; } rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_PROCESS_CONFIG, &process_config); if (rc != 0) { pkderr("ssh_bind_options_set process config: %s\n", ssh_get_error(b)); goto outclose; } if (!ssh_fips_mode()) { /* Add methods not enabled by default */ #define GEX_SHA1 "diffie-hellman-group-exchange-sha1" default_kex = ssh_kex_get_default_methods(SSH_KEX); kex_len = strlen(default_kex) + strlen(GEX_SHA1) + 2; all_kex = malloc(kex_len); if (all_kex == NULL) { pkderr("Failed to alloc more memory.\n"); goto outclose; } snprintf(all_kex, kex_len, "%s," GEX_SHA1, default_kex); rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_KEY_EXCHANGE, all_kex); free(all_kex); if (rc != 0) { pkderr("ssh_bind_options_set kex methods: %s\n", ssh_get_error(b)); goto outclose; } /* Enable all supported ciphers */ all_ciphers = ssh_kex_get_supported_method(SSH_CRYPT_C_S); rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_CIPHERS_C_S, all_ciphers); if (rc != 0) { pkderr("ssh_bind_options_set Ciphers C-S: %s\n", ssh_get_error(b)); goto outclose; } all_ciphers = ssh_kex_get_supported_method(SSH_CRYPT_S_C); rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_CIPHERS_S_C, all_ciphers); if (rc != 0) { pkderr("ssh_bind_options_set Ciphers S-C: %s\n", ssh_get_error(b)); goto outclose; } } s = ssh_new(); if (s == NULL) { pkderr("ssh_new\n"); goto outclose; } rc = ssh_options_set(s, SSH_OPTIONS_REKEY_DATA, &rekey_data_limit); if (rc != 0) { pkderr("ssh_options_set rekey data: %s\n", ssh_get_error(s)); goto outclose; } /* * ssh_bind_accept loads host key as side-effect. If this * succeeds, the given 'fd' will be closed upon 'ssh_free(s)'. */ rc = ssh_bind_accept_fd(b, s, fd); if (rc != SSH_OK) { pkderr("ssh_bind_accept_fd: %s\n", ssh_get_error(b)); goto outclose; } /* accept only publickey-based auth */ ssh_set_auth_methods(s, SSH_AUTH_METHOD_PUBLICKEY); /* initialize callbacks */ ssh_callbacks_init(&pkd_server_cb); pkd_server_cb.userdata = &c; rc = ssh_set_server_callbacks(s, &pkd_server_cb); if (rc != SSH_OK) { pkderr("ssh_set_server_callbacks: %s\n", ssh_get_error(s)); goto out; } /* first do key exchange */ rc = ssh_handle_key_exchange(s); if (rc != SSH_OK) { pkderr("ssh_handle_key_exchange: %s\n", ssh_get_error(s)); goto out; } /* setup and pump event to carry out exec channel */ e = ssh_event_new(); if (e == NULL) { pkderr("ssh_event_new\n"); goto out; } rc = ssh_event_add_session(e, s); if (rc != SSH_OK) { pkderr("ssh_event_add_session\n"); goto out; } /* poll until exec channel established */ while ((ctx.keep_going != 0) && (rc != SSH_ERROR) && (pkd_state.req_exec_received == 0)) { rc = ssh_event_dopoll(e, -1 /* infinite timeout */); } if (rc == SSH_ERROR) { pkderr("ssh_event_dopoll\n"); goto out; } else if (c == NULL) { pkderr("poll loop exited but exec channel not ready\n"); rc = -1; goto out; } rc = ssh_channel_write(c, args->payload.buf, args->payload.len); if (rc != (int)args->payload.len) { pkderr("ssh_channel_write partial (%d != %zd)\n", rc, args->payload.len); } rc = ssh_channel_request_send_exit_status(c, 0); if (rc != SSH_OK) { pkderr("ssh_channel_request_send_exit_status: %s\n", ssh_get_error(s)); goto out; } rc = ssh_channel_send_eof(c); if (rc != SSH_OK) { pkderr("ssh_channel_send_eof: %s\n", ssh_get_error(s)); goto out; } rc = ssh_channel_close(c); if (rc != SSH_OK) { pkderr("ssh_channel_close: %s\n", ssh_get_error(s)); goto out; } while ((ctx.keep_going != 0) && (pkd_state.eof_received == 0) && (pkd_state.close_received == 0)) { rc = ssh_event_dopoll(e, 1000 /* milliseconds */); if (rc == SSH_ERROR) { /* log, but don't consider this fatal */ pkdout("ssh_event_dopoll for eof + close: %s\n", ssh_get_error(s)); rc = 0; break; } else { rc = 0; } } while ((ctx.keep_going != 0) && (ssh_is_connected(s))) { rc = ssh_event_dopoll(e, 1000 /* milliseconds */); if (rc == SSH_ERROR) { /* log, but don't consider this fatal */ pkdout("ssh_event_dopoll for session connection: %s\n", ssh_get_error(s)); rc = 0; break; } else { rc = 0; } } goto out; outclose: close(fd); out: if (c != NULL) { ssh_channel_free(c); } if (e != NULL) { ssh_event_remove_session(e, s); ssh_event_free(e); } if (s != NULL) { ssh_disconnect(s); ssh_free(s); } if (b != NULL) { ssh_bind_free(b); } return rc; } /* * main loop ------------------------------------------------------------ */ static void *pkd_main(void *args) { int rc = -1; struct pkd_daemon_args *a = (struct pkd_daemon_args *) args; struct sigaction act = { .sa_handler = pkd_sighandler, }; pkd_state.server_fd = -1; pkd_state.req_exec_received = 0; pkd_state.close_received = 0; pkd_state.eof_received = 0; /* SIGUSR1 is used to interrupt 'pkd_accept_fd'. */ rc = sigaction(SIGUSR1, &act, NULL); if (rc != 0) { pkderr("sigaction: %d\n", rc); goto out; } /* Ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); rc = pkd_init_libssh(); if (rc != 0) { pkderr("pkd_init_libssh: %d\n", rc); goto out; } rc = pkd_init_server_fd(1234); if (rc != 0) { pkderr("pkd_init_server_fd: %d\n", rc); goto out; } ctx.pkd_ready = 1; while (ctx.keep_going != 0) { int fd = pkd_accept_fd(); if (fd < 0) { if (ctx.keep_going != 0) { pkderr("pkd_accept_fd"); rc = -1; } else { rc = 0; } break; } rc = pkd_exec_hello(fd, a); if (rc != 0) { pkderr("pkd_exec_hello: %d\n", rc); break; } } if (pkd_state.server_fd != -1) { close(pkd_state.server_fd); } pkd_state.server_fd = -1; out: ctx.rc = rc; return NULL; } /* * pkd start and stop used by setup/teardown test scaffolding ----------- */ int pkd_start(struct pkd_daemon_args *args) { int rc = 0; pkdout_enabled = args->opts.log_stdout; pkderr_enabled = args->opts.log_stderr; /* Initialize the pkd context. */ ctx.rc = -1; ctx.keep_going = 1; ctx.pkd_ready = 0; rc = pthread_create(&ctx.tid, NULL, &pkd_main, args); assert_int_equal(rc, 0); /* Busy-spin until pkd thread is ready. */ while (ctx.pkd_ready == 0); return rc; } void pkd_stop(struct pkd_result *out) { int rc = 0; ctx.keep_going = 0; close(pkd_state.server_fd); rc = pthread_kill(ctx.tid, SIGUSR1); assert_int_equal(rc, 0); rc = pthread_join(ctx.tid, NULL); assert_int_equal(rc, 0); assert_non_null(out); out->ok = (ctx.rc == 0); return; } ================================================ FILE: src/libssh/tests/pkd/pkd_daemon.h ================================================ /* * pkd_daemon.h -- tests use this interface to start, stop pkd * instances and get results * * (c) 2014 Jon Simons */ #ifndef __PKD_DAEMON_H__ #define __PKD_DAEMON_H__ #include "config.h" enum pkd_hostkey_type_e { PKD_RSA, #ifdef HAVE_DSA PKD_DSA, #endif PKD_ED25519, PKD_ECDSA }; struct pkd_daemon_args { enum pkd_hostkey_type_e type; const char *hostkeypath; struct { const uint8_t *buf; size_t len; } payload; uint64_t rekey_data_limit; struct { int list; int log_stdout; int log_stderr; int libssh_log_level; const char *testname; const char *testmatch; unsigned int iterations; struct { char *mkdtemp_str; } socket_wrapper; } opts; }; struct pkd_result { int ok; }; int pkd_start(struct pkd_daemon_args *args); void pkd_stop(struct pkd_result *out); #endif /* __PKD_DAEMON_H__ */ ================================================ FILE: src/libssh/tests/pkd/pkd_hello.c ================================================ /* * pkd_hello.c -- * * (c) 2014, 2017-2018 Jon Simons */ #include "config.h" #include // for cmocka #include // for cmocka #include #include #include // for cmocka #include #include "libssh/priv.h" #include "torture.h" // for ssh_fips_mode() #include "pkd_client.h" #include "pkd_daemon.h" #include "pkd_keyutil.h" #include "pkd_util.h" #define DEFAULT_ITERATIONS 10 static struct pkd_daemon_args pkd_dargs; static uint8_t default_payload_buf[] = { 'h', 'e', 'l', 'l', 'o', '\n', }; static size_t default_payload_len = sizeof(default_payload_buf); #ifdef HAVE_ARGP_H #include #define PROGNAME "pkd_hello" #define ARGP_PROGNAME "libssh " PROGNAME const char *argp_program_version = ARGP_PROGNAME " 2017-07-12"; const char *argp_program_bug_address = "Jon Simons "; static char doc[] = \ "\nExample usage:\n\n" " " PROGNAME "\n" " Run all tests with default number of iterations.\n" " " PROGNAME " --list\n" " List available individual test names.\n" " " PROGNAME " -i 1000 -t torture_pkd_rsa_ecdh_sha2_nistp256\n" " Run only the torture_pkd_rsa_ecdh_sha2_nistp256 testcase 1000 times.\n" " " PROGNAME " -i 1000 -m curve25519\n" " Run all tests with the string 'curve25519' 1000 times.\n" " " PROGNAME " -v -v -v -v -e -o\n" " Run all tests with maximum libssh and pkd logging.\n" ; static struct argp_option options[] = { { "buffer", 'b', "string", 0, "Use the given string for test buffer payload contents", 0 }, { "stderr", 'e', NULL, 0, "Emit pkd stderr messages", 0 }, { "list", 'l', NULL, 0, "List available individual test names", 0 }, { "iterations", 'i', "number", 0, "Run each test for the given number of iterations (default is 10)", 0 }, { "match", 'm', "testmatch", 0, "Run all tests with the given string", 0 }, { "socket-wrapper-dir", 'w', "", 0, "Run in socket-wrapper mode using the given mkdtemp directory template", 0 }, { "stdout", 'o', NULL, 0, "Emit pkd stdout messages", 0 }, { "rekey", 'r', "limit", 0, "Set the given rekey data limit, in bytes, using SSH_OPTIONS_REKEY_DATA", 0 }, { "test", 't', "testname", 0, "Run tests matching the given testname", 0 }, { "verbose", 'v', NULL, 0, "Increase libssh verbosity (can be used multiple times)", 0 }, { NULL, 0, NULL, 0, NULL, 0 }, }; static error_t parse_opt(int key, char *arg, struct argp_state *state) { (void) arg; (void) state; switch(key) { case 'b': pkd_dargs.payload.buf = (uint8_t *) arg; pkd_dargs.payload.len = strlen(arg); break; case 'e': pkd_dargs.opts.log_stderr = 1; break; case 'l': pkd_dargs.opts.list = 1; break; case 'i': pkd_dargs.opts.iterations = atoi(arg); break; case 'm': pkd_dargs.opts.testmatch = arg; break; case 'o': pkd_dargs.opts.log_stdout = 1; break; case 'r': pkd_dargs.rekey_data_limit = atoi(arg); break; case 't': pkd_dargs.opts.testname = arg; break; case 'v': pkd_dargs.opts.libssh_log_level += 1; break; case 'w': pkd_dargs.opts.socket_wrapper.mkdtemp_str = arg; break; default: return ARGP_ERR_UNKNOWN; } return 0; } static struct argp parser = { options, parse_opt, NULL, doc, NULL, NULL, NULL }; #endif /* HAVE_ARGP_H */ static struct pkd_state *torture_pkd_setup(enum pkd_hostkey_type_e type, const char *hostkeypath) { int rc = 0; pkd_dargs.type = type; pkd_dargs.hostkeypath = hostkeypath; rc = pkd_start(&pkd_dargs); assert_int_equal(rc, 0); return NULL; } static int torture_pkd_teardown(void **state) { struct pkd_result result = { .ok = 0 }; (void) state; pkd_stop(&result); assert_int_equal(result.ok, 1); return 0; } /* * one setup for each server keytype ------------------------------------ */ static int torture_pkd_setup_noop(void **state) { *state = (void *) torture_pkd_setup(PKD_RSA, NULL /*path*/); return 0; } static int torture_pkd_setup_rsa(void **state) { setup_rsa_key(); *state = (void *) torture_pkd_setup(PKD_RSA, LIBSSH_RSA_TESTKEY); return 0; } static int torture_pkd_setup_ed25519(void **state) { setup_ed25519_key(); *state = (void *) torture_pkd_setup(PKD_ED25519, LIBSSH_ED25519_TESTKEY); return 0; } #ifdef HAVE_DSA static int torture_pkd_setup_dsa(void **state) { setup_dsa_key(); *state = (void *) torture_pkd_setup(PKD_DSA, LIBSSH_DSA_TESTKEY); return 0; } #endif static int torture_pkd_setup_ecdsa_256(void **state) { setup_ecdsa_keys(); *state = (void *) torture_pkd_setup(PKD_ECDSA, LIBSSH_ECDSA_256_TESTKEY); return 0; } static int torture_pkd_setup_ecdsa_384(void **state) { setup_ecdsa_keys(); *state = (void *) torture_pkd_setup(PKD_ECDSA, LIBSSH_ECDSA_384_TESTKEY); return 0; } static int torture_pkd_setup_ecdsa_521(void **state) { setup_ecdsa_keys(); *state = (void *) torture_pkd_setup(PKD_ECDSA, LIBSSH_ECDSA_521_TESTKEY); return 0; } /* * Test matrices: f(clientname, testname, ssh-command, setup-function, teardown-function). */ #define PKDTESTS_DEFAULT_FIPS(f, client, cmd) \ f(client, rsa_default, cmd, setup_rsa, teardown) \ f(client, ecdsa_256_default, cmd, setup_ecdsa_256, teardown) \ f(client, ecdsa_384_default, cmd, setup_ecdsa_384, teardown) \ f(client, ecdsa_521_default, cmd, setup_ecdsa_521, teardown) #ifdef HAVE_DSA #define PKDTESTS_DEFAULT(f, client, cmd) \ /* Default passes by server key type. */ \ PKDTESTS_DEFAULT_FIPS(f, client, cmd) \ f(client, dsa_default, cmd, setup_dsa, teardown) #else #define PKDTESTS_DEFAULT(f, client, cmd) \ /* Default passes by server key type. */ \ PKDTESTS_DEFAULT_FIPS(f, client, cmd) #endif #define PKDTESTS_DEFAULT_OPENSSHONLY(f, client, cmd) \ /* Default passes by server key type. */ \ f(client, ed25519_default, cmd, setup_ed25519, teardown) #define GEX_SHA256 "diffie-hellman-group-exchange-sha256" #define GEX_SHA1 "diffie-hellman-group-exchange-sha1" #if defined(WITH_GEX) #define PKDTESTS_KEX_FIPS(f, client, kexcmd) \ f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \ f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \ f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) \ f(client, rsa_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_rsa, teardown) \ f(client, ecdsa_256_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_ecdsa_521, teardown) #else /* !defined(WITH_GEX) */ #define PKDTESTS_KEX_FIPS(f, client, kexcmd) \ f(client, rsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_rsa, teardown) \ f(client, rsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_rsa, teardown) \ f(client, rsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group14_sha256, kexcmd("diffie-hellman-group14-sha256"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_rsa, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group14_sha256,kexcmd("diffie-hellman-group14-sha256"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group14_sha256,kexcmd("diffie-hellman-group14-sha256"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group14_sha256,kexcmd("diffie-hellman-group14-sha256"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group16_sha512,kexcmd("diffie-hellman-group16-sha512"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group18_sha512,kexcmd("diffie-hellman-group18-sha512"), setup_ecdsa_521, teardown) #endif #define PKDTESTS_KEX_COMMON(f, client, kexcmd) \ PKDTESTS_KEX_FIPS(f, client, kexcmd) \ f(client, rsa_curve25519_sha256, kexcmd("curve25519-sha256"), setup_rsa, teardown) \ f(client, rsa_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_rsa, teardown) \ f(client, rsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_rsa, teardown) \ f(client, ecdsa_256_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ecdsa_521, teardown) #if defined(HAVE_DSA) && defined(WITH_GEX) /* GEX_SHA256 with RSA and ECDSA is included in PKDTESTS_KEX_FIPS if available */ #define PKDTESTS_KEX(f, client, kexcmd) \ /* Kex algorithms. */ \ PKDTESTS_KEX_COMMON(f, client, kexcmd) \ f(client, rsa_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_rsa, teardown) \ f(client, dsa_curve25519_sha256, kexcmd("curve25519-sha256"), setup_dsa, teardown) \ f(client, dsa_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384 "), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521 "), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group14_sha256, kexcmd("diffie-hellman-group14-sha256"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_dsa, teardown) \ f(client, ecdsa_256_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_521, teardown) #elif defined(HAVE_DSA) /* && !defined(WITH_GEX) */ #define PKDTESTS_KEX(f, client, kexcmd) \ /* Kex algorithms. */ \ PKDTESTS_KEX_COMMON(f, client, kexcmd) \ f(client, dsa_curve25519_sha256, kexcmd("curve25519-sha256"), setup_dsa, teardown) \ f(client, dsa_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256 "), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384 "), setup_dsa, teardown) \ f(client, dsa_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521 "), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group14_sha256, kexcmd("diffie-hellman-group14-sha256"), setup_dsa, teardown) \ f(client, dsa_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_dsa, teardown) #elif defined(WITH_GEX) /* && !defined(HAVE_DSA) */ /* GEX_SHA256 is included in PKDTESTS_KEX_FIPS if available */ #define PKDTESTS_KEX(f, client, kexcmd) \ /* Kex algorithms. */ \ PKDTESTS_KEX_COMMON(f, client, kexcmd) \ f(client, rsa_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_rsa, teardown) \ f(client, ecdsa_256_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ecdsa_521, teardown) #else #define PKDTESTS_KEX(f, client, kexcmd) \ /* Kex algorithms. */ \ PKDTESTS_KEX_COMMON(f, client, kexcmd) #endif #ifdef HAVE_DSA #define PKDTESTS_KEX_OPENSSHONLY(f, client, kexcmd) \ /* Kex algorithms. */ \ f(client, ed25519_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ed25519, teardown) \ f(client, ed25519_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group14_sha256, kexcmd("diffie-hellman-group14-sha256"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group14_sha1, kexcmd("diffie-hellman-group14-sha1"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ed25519, teardown) #else #define PKDTESTS_KEX_OPENSSHONLY(f, client, kexcmd) \ /* Kex algorithms. */ \ f(client, ed25519_curve25519_sha256, kexcmd("curve25519-sha256"), setup_ed25519, teardown) \ f(client, ed25519_curve25519_sha256_libssh_org, kexcmd("curve25519-sha256@libssh.org"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp256, kexcmd("ecdh-sha2-nistp256"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp384, kexcmd("ecdh-sha2-nistp384"), setup_ed25519, teardown) \ f(client, ed25519_ecdh_sha2_nistp521, kexcmd("ecdh-sha2-nistp521"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group14_sha256, kexcmd("diffie-hellman-group14-sha256"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group16_sha512, kexcmd("diffie-hellman-group16-sha512"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group18_sha512, kexcmd("diffie-hellman-group18-sha512"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group1_sha1, kexcmd("diffie-hellman-group1-sha1"), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group_exchange_sha256, kexcmd(GEX_SHA256), setup_ed25519, teardown) \ f(client, ed25519_diffie_hellman_group_exchange_sha1, kexcmd(GEX_SHA1), setup_ed25519, teardown) #endif #define PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ f(client, rsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_rsa, teardown) \ f(client, rsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_rsa, teardown) \ f(client, rsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_rsa, teardown) \ f(client, rsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_rsa, teardown) \ f(client, ecdsa_256_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_aes128_cbc, ciphercmd("aes128-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes128_ctr, ciphercmd("aes128-ctr"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes256_cbc, ciphercmd("aes256-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes256_ctr, ciphercmd("aes256-ctr"), setup_ecdsa_521, teardown) #ifdef HAVE_DSA #define PKDTESTS_CIPHER(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ f(client, dsa_3des_cbc, ciphercmd("3des-cbc"), setup_dsa, teardown) \ f(client, dsa_aes128_cbc, ciphercmd("aes128-cbc"), setup_dsa, teardown) \ f(client, dsa_aes128_ctr, ciphercmd("aes128-ctr"), setup_dsa, teardown) \ f(client, dsa_aes256_cbc, ciphercmd("aes256-cbc"), setup_dsa, teardown) \ f(client, dsa_aes256_ctr, ciphercmd("aes256-ctr"), setup_dsa, teardown) \ f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) #else #define PKDTESTS_CIPHER(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_FIPS(f, client, ciphercmd) \ f(client, rsa_3des_cbc, ciphercmd("3des-cbc"), setup_rsa, teardown) \ f(client, ecdsa_256_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_3des_cbc, ciphercmd("3des-cbc"), setup_ecdsa_521, teardown) #endif #define CHACHA20 "chacha20-poly1305@openssh.com" #define AES128_GCM "aes128-gcm@openssh.com" #define AES256_GCM "aes256-gcm@openssh.com" #define PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \ f(client, rsa_aes128_gcm, ciphercmd(AES128_GCM), setup_rsa, teardown) \ f(client, rsa_aes256_gcm, ciphercmd(AES256_GCM), setup_rsa, teardown) \ f(client, ecdsa_256_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_aes128_gcm, ciphercmd(AES128_GCM), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes256_gcm, ciphercmd(AES256_GCM), setup_ecdsa_521, teardown) #ifdef HAVE_DSA #define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \ f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \ f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \ f(client, dsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_dsa, teardown) \ f(client, dsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_dsa, teardown) \ f(client, dsa_chacha20, ciphercmd(CHACHA20), setup_dsa, teardown) \ f(client, dsa_aes128_gcm, ciphercmd(AES128_GCM), setup_dsa, teardown) \ f(client, dsa_aes256_gcm, ciphercmd(AES256_GCM), setup_dsa, teardown) \ f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes128_cbc, ciphercmd("aes128-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes128_ctr, ciphercmd("aes128-ctr"), setup_ed25519, teardown) \ f(client, ed25519_aes256_cbc, ciphercmd("aes256-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes256_ctr, ciphercmd("aes256-ctr"), setup_ed25519, teardown) \ f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \ f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \ f(client, ed25519_aes128_gcm, ciphercmd(AES128_GCM), setup_ed25519, teardown) \ f(client, ed25519_aes256_gcm, ciphercmd(AES256_GCM), setup_ed25519, teardown) \ f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) #else #define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \ /* Ciphers. */ \ PKDTESTS_CIPHER_OPENSSHONLY_FIPS(f, client, ciphercmd) \ f(client, rsa_aes192_cbc, ciphercmd("aes192-cbc"), setup_rsa, teardown) \ f(client, rsa_aes192_ctr, ciphercmd("aes192-ctr"), setup_rsa, teardown) \ f(client, rsa_chacha20, ciphercmd(CHACHA20), setup_rsa, teardown) \ f(client, ed25519_3des_cbc, ciphercmd("3des-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes128_cbc, ciphercmd("aes128-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes128_ctr, ciphercmd("aes128-ctr"), setup_ed25519, teardown) \ f(client, ed25519_aes256_cbc, ciphercmd("aes256-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes256_ctr, ciphercmd("aes256-ctr"), setup_ed25519, teardown) \ f(client, ed25519_aes192_cbc, ciphercmd("aes192-cbc"), setup_ed25519, teardown) \ f(client, ed25519_aes192_ctr, ciphercmd("aes192-ctr"), setup_ed25519, teardown) \ f(client, ed25519_chacha20, ciphercmd(CHACHA20), setup_ed25519, teardown) \ f(client, ecdsa_256_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_chacha20, ciphercmd(CHACHA20), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_chacha20, ciphercmd(CHACHA20), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_aes192_cbc, ciphercmd("aes192-cbc"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_aes192_ctr, ciphercmd("aes192-ctr"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_chacha20, ciphercmd(CHACHA20), setup_ecdsa_521, teardown) #endif #define PKDTESTS_MAC_FIPS(f, client, maccmd) \ f(client, ecdsa_256_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_hmac_sha1, maccmd("hmac-sha1"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ecdsa_521, teardown) \ f(client, rsa_hmac_sha1, maccmd("hmac-sha1"), setup_rsa, teardown) \ f(client, rsa_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_rsa, teardown) #define PKDTESTS_MAC_OPENSSHONLY_FIPS(f, client, maccmd) \ f(client, ecdsa_256_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_256, teardown) \ f(client, ecdsa_256_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_ecdsa_256, teardown) \ f(client, ecdsa_384_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_384, teardown) \ f(client, ecdsa_384_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_ecdsa_384, teardown) \ f(client, ecdsa_521_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ecdsa_521, teardown) \ f(client, ecdsa_521_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_ecdsa_521, teardown) \ f(client, rsa_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_rsa, teardown) \ f(client, rsa_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_rsa, teardown) \ f(client, rsa_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_rsa, teardown) \ f(client, rsa_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_rsa, teardown) #ifdef HAVE_DSA #define PKDTESTS_MAC(f, client, maccmd) \ /* MACs. */ \ PKDTESTS_MAC_FIPS(f, client, maccmd) \ f(client, dsa_hmac_sha1, maccmd("hmac-sha1"), setup_dsa, teardown) \ f(client, dsa_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_dsa, teardown) #define PKDTESTS_MAC_OPENSSHONLY(f, client, maccmd) \ PKDTESTS_MAC_OPENSSHONLY_FIPS(f, client, maccmd) \ f(client, dsa_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_dsa, teardown) \ f(client, dsa_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_dsa, teardown) \ f(client, dsa_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_dsa, teardown) \ f(client, dsa_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_dsa, teardown) \ f(client, ed25519_hmac_sha1, maccmd("hmac-sha1"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_ed25519, teardown) #else #define PKDTESTS_MAC(f, client, maccmd) \ /* MACs. */ \ PKDTESTS_MAC_FIPS(f, client, maccmd) #define PKDTESTS_MAC_OPENSSHONLY(f, client, maccmd) \ PKDTESTS_MAC_OPENSSHONLY_FIPS(f, client, maccmd) \ f(client, ed25519_hmac_sha1, maccmd("hmac-sha1"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha1_etm, maccmd("hmac-sha1-etm@openssh.com"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_256, maccmd("hmac-sha2-256"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_256_etm, maccmd("hmac-sha2-256-etm@openssh.com"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_512, maccmd("hmac-sha2-512"), setup_ed25519, teardown) \ f(client, ed25519_hmac_sha2_512_etm, maccmd("hmac-sha2-512-etm@openssh.com"), setup_ed25519, teardown) #endif #define PKDTESTS_HOSTKEY_OPENSSHONLY_FIPS(f, client, hkcmd) \ f(client, rsa_sha2_256, hkcmd("rsa-sha2-256"), setup_rsa, teardown) \ f(client, rsa_sha2_512, hkcmd("rsa-sha2-512"), setup_rsa, teardown) \ f(client, rsa_sha2_256_512, hkcmd("rsa-sha2-256,rsa-sha2-512"), setup_rsa, teardown) \ f(client, rsa_sha2_512_256, hkcmd("rsa-sha2-512,rsa-sha2-256"), setup_rsa, teardown) #define PKDTESTS_HOSTKEY_OPENSSHONLY(f, client, hkcmd) \ PKDTESTS_HOSTKEY_OPENSSHONLY_FIPS(f, client, hkcmd) static void torture_pkd_client_noop(void **state) { struct pkd_state *pstate = (struct pkd_state *) (*state); (void) pstate; return; } static void torture_pkd_runtest(const char *testname, const char *testcmd) { int i, rc; char logfile[1024] = { 0 }; int iterations = (pkd_dargs.opts.iterations != 0) ? pkd_dargs.opts.iterations : DEFAULT_ITERATIONS; for (i = 0; i < iterations; i++) { rc = system_checked(testcmd); assert_int_equal(rc, 0); } /* Asserts did not trip: cleanup logs. */ snprintf(&logfile[0], sizeof(logfile), "%s.out", testname); unlink(logfile); snprintf(&logfile[0], sizeof(logfile), "%s.err", testname); unlink(logfile); } /* * Though each keytest function body is the same, separate functions are * defined here to result in distinct output when running the tests. */ #define emit_keytest(client, testname, sshcmd, setup, teardown) \ static void torture_pkd_## client ## _ ## testname(void **state) { \ const char *tname = "torture_pkd_" #client "_" #testname; \ char testcmd[2048] = { 0 }; \ (void) state; \ snprintf(&testcmd[0], sizeof(testcmd), sshcmd, tname, tname); \ torture_pkd_runtest(tname, testcmd); \ } /* * Actual test functions are emitted here. */ #ifdef HAVE_DSA #define CLIENT_ID_FILE OPENSSH_DSA_TESTKEY PKDTESTS_DEFAULT(emit_keytest, openssh_dsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_keytest, openssh_cert_dsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_keytest, openssh_dsa, OPENSSH_CMD) PKDTESTS_KEX(emit_keytest, openssh_dsa, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_keytest, openssh_dsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_keytest, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_keytest, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_keytest, openssh_dsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_keytest, openssh_dsa, OPENSSH_MAC_CMD) #undef CLIENT_ID_FILE #endif #define CLIENT_ID_FILE OPENSSH_RSA_TESTKEY PKDTESTS_DEFAULT(emit_keytest, openssh_rsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_keytest, openssh_cert_rsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT(emit_keytest, openssh_sha256_cert_rsa, OPENSSH_SHA256_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_keytest, openssh_rsa, OPENSSH_CMD) PKDTESTS_KEX(emit_keytest, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_keytest, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_keytest, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_keytest, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_keytest, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_keytest, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_HOSTKEY_OPENSSHONLY(emit_keytest, openssh_rsa, OPENSSH_HOSTKEY_CMD) #undef CLIENT_ID_FILE #define CLIENT_ID_FILE OPENSSH_ECDSA256_TESTKEY PKDTESTS_DEFAULT(emit_keytest, openssh_e256, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_keytest, openssh_cert_e256, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_keytest, openssh_e256, OPENSSH_CMD) PKDTESTS_KEX(emit_keytest, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_keytest, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_keytest, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_keytest, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_keytest, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_keytest, openssh_e256, OPENSSH_MAC_CMD) #undef CLIENT_ID_FILE /* Could add these passes, too: */ //#define CLIENT_ID_FILE OPENSSH_ECDSA384_TESTKEY //#define CLIENT_ID_FILE OPENSSH_ECDSA521_TESTKEY #define CLIENT_ID_FILE OPENSSH_ED25519_TESTKEY PKDTESTS_DEFAULT(emit_keytest, openssh_ed, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_keytest, openssh_cert_ed, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_keytest, openssh_ed, OPENSSH_CMD) PKDTESTS_KEX(emit_keytest, openssh_ed, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_keytest, openssh_ed, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_keytest, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_keytest, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_keytest, openssh_ed, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_keytest, openssh_ed, OPENSSH_MAC_CMD) #undef CLIENT_ID_FILE #define CLIENT_ID_FILE DROPBEAR_RSA_TESTKEY PKDTESTS_DEFAULT(emit_keytest, dropbear, DROPBEAR_CMD) PKDTESTS_CIPHER(emit_keytest, dropbear, DROPBEAR_CIPHER_CMD) PKDTESTS_MAC(emit_keytest, dropbear, DROPBEAR_MAC_CMD) #undef CLIENT_ID_FILE /* * Define an array of testname strings mapped to their associated * test function. Enables running tests individually by name from * the command line. */ #define emit_testmap(client, testname, sshcmd, setup, teardown) \ { "torture_pkd_" #client "_" #testname, \ emit_unit_test(client, testname, sshcmd, setup, teardown) }, #define emit_unit_test(client, testname, sshcmd, setup, teardown) \ cmocka_unit_test_setup_teardown(torture_pkd_ ## client ## _ ## testname, \ torture_pkd_ ## setup, \ torture_pkd_ ## teardown) #define emit_unit_test_comma(client, testname, sshcmd, setup, teardown) \ emit_unit_test(client, testname, sshcmd, setup, teardown), struct { const char *testname; const struct CMUnitTest test; } testmap[] = { /* OpenSSH */ #ifdef HAVE_DSA PKDTESTS_DEFAULT(emit_testmap, openssh_dsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_cert_dsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_testmap, openssh_dsa, OPENSSH_CMD) PKDTESTS_KEX(emit_testmap, openssh_dsa, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_testmap, openssh_dsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_testmap, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_testmap, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_testmap, openssh_dsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_testmap, openssh_dsa, OPENSSH_MAC_CMD) #endif PKDTESTS_DEFAULT(emit_testmap, openssh_rsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_cert_rsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_sha256_cert_rsa, OPENSSH_SHA256_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_testmap, openssh_rsa, OPENSSH_CMD) PKDTESTS_KEX(emit_testmap, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_testmap, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_testmap, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_testmap, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_testmap, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_testmap, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_HOSTKEY_OPENSSHONLY(emit_testmap, openssh_rsa, OPENSSH_HOSTKEY_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_e256, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_cert_e256, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_testmap, openssh_e256, OPENSSH_CMD) PKDTESTS_KEX(emit_testmap, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_testmap, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_testmap, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_testmap, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_testmap, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_testmap, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_ed, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_testmap, openssh_cert_ed, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_testmap, openssh_ed, OPENSSH_CMD) PKDTESTS_KEX(emit_testmap, openssh_ed, OPENSSH_KEX_CMD) PKDTESTS_KEX_OPENSSHONLY(emit_testmap, openssh_ed, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_testmap, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_testmap, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_testmap, openssh_ed, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_testmap, openssh_ed, OPENSSH_MAC_CMD) /* Dropbear */ PKDTESTS_DEFAULT(emit_testmap, dropbear, DROPBEAR_CMD) PKDTESTS_CIPHER(emit_testmap, dropbear, DROPBEAR_CIPHER_CMD) PKDTESTS_MAC(emit_testmap, dropbear, DROPBEAR_MAC_CMD) /* Noop */ emit_testmap(client, noop, "", setup_noop, teardown) /* NULL tail entry */ { .testname = NULL, .test = { .name = NULL, .test_func = NULL, .setup_func = NULL, .teardown_func = NULL } } }; static int pkd_run_tests(void) { int rc = -1; int tindex = 0; const struct CMUnitTest openssh_tests[] = { #ifdef HAVE_DSA PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_dsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_cert_dsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_unit_test_comma, openssh_dsa, OPENSSH_CMD) PKDTESTS_KEX(emit_unit_test_comma, openssh_dsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_unit_test_comma, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_unit_test_comma, openssh_dsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_unit_test_comma, openssh_dsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_unit_test_comma, openssh_dsa, OPENSSH_MAC_CMD) #endif PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_rsa, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_cert_rsa, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_FIPS(emit_unit_test_comma, openssh_sha256_cert_rsa, OPENSSH_SHA256_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_unit_test_comma, openssh_rsa, OPENSSH_CMD) PKDTESTS_KEX(emit_unit_test_comma, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_unit_test_comma, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_unit_test_comma, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_unit_test_comma, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_unit_test_comma, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_e256, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_cert_e256, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_unit_test_comma, openssh_e256, OPENSSH_CMD) PKDTESTS_KEX(emit_unit_test_comma, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_unit_test_comma, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_unit_test_comma, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_unit_test_comma, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_unit_test_comma, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_ed, OPENSSH_CMD) PKDTESTS_DEFAULT(emit_unit_test_comma, openssh_cert_ed, OPENSSH_CERT_CMD) PKDTESTS_DEFAULT_OPENSSHONLY(emit_unit_test_comma, openssh_ed, OPENSSH_CMD) PKDTESTS_KEX(emit_unit_test_comma, openssh_ed, OPENSSH_KEX_CMD) PKDTESTS_CIPHER(emit_unit_test_comma, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY(emit_unit_test_comma, openssh_ed, OPENSSH_CIPHER_CMD) PKDTESTS_MAC(emit_unit_test_comma, openssh_ed, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY(emit_unit_test_comma, openssh_ed, OPENSSH_MAC_CMD) }; const struct CMUnitTest dropbear_tests[] = { PKDTESTS_DEFAULT(emit_unit_test_comma, dropbear, DROPBEAR_CMD) PKDTESTS_CIPHER(emit_unit_test_comma, dropbear, DROPBEAR_CIPHER_CMD) PKDTESTS_MAC(emit_unit_test_comma, dropbear, DROPBEAR_MAC_CMD) }; const struct CMUnitTest openssh_fips_tests[] = { PKDTESTS_DEFAULT_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_CMD) PKDTESTS_DEFAULT_FIPS(emit_unit_test_comma, openssh_sha256_cert_rsa, OPENSSH_SHA256_CERT_CMD) PKDTESTS_KEX_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_KEX_CMD) PKDTESTS_CIPHER_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_CIPHER_CMD) PKDTESTS_MAC_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY_FIPS(emit_unit_test_comma, openssh_rsa, OPENSSH_MAC_CMD) PKDTESTS_DEFAULT_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_CMD) PKDTESTS_DEFAULT_FIPS(emit_unit_test_comma, openssh_cert_e256, OPENSSH_CERT_CMD) PKDTESTS_KEX_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_KEX_CMD) PKDTESTS_CIPHER_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_CIPHER_OPENSSHONLY_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_CIPHER_CMD) PKDTESTS_MAC_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_MAC_CMD) PKDTESTS_MAC_OPENSSHONLY_FIPS(emit_unit_test_comma, openssh_e256, OPENSSH_MAC_CMD) }; const struct CMUnitTest noop_tests[] = { emit_unit_test(client, noop, "", setup_noop, teardown) }; /* Test list is populated depending on which clients are enabled. */ struct CMUnitTest all_tests[(sizeof(openssh_tests) / sizeof(openssh_tests[0])) + (sizeof(dropbear_tests) / sizeof(dropbear_tests[0])) + (sizeof(noop_tests) / sizeof(noop_tests[0]))]; memset(&all_tests[0], 0x0, sizeof(all_tests)); /* Generate client keys and populate test list for each enabled client. */ if (is_openssh_client_enabled()) { setup_openssh_client_keys(); if (ssh_fips_mode()) { memcpy(&all_tests[tindex], &openssh_fips_tests[0], sizeof(openssh_fips_tests)); tindex += (sizeof(openssh_fips_tests) / sizeof(openssh_fips_tests[0])); } else { memcpy(&all_tests[tindex], &openssh_tests[0], sizeof(openssh_tests)); tindex += (sizeof(openssh_tests) / sizeof(openssh_tests[0])); } } if (is_dropbear_client_enabled()) { setup_dropbear_client_rsa_key(); if (!ssh_fips_mode()) { memcpy(&all_tests[tindex], &dropbear_tests[0], sizeof(dropbear_tests)); tindex += (sizeof(dropbear_tests) / sizeof(dropbear_tests[0])); } } memcpy(&all_tests[tindex], &noop_tests[0], sizeof(noop_tests)); tindex += (sizeof(noop_tests) / sizeof(noop_tests[0])); if ((pkd_dargs.opts.testname == NULL) && (pkd_dargs.opts.testmatch == NULL)) { rc = _cmocka_run_group_tests("all tests", all_tests, tindex, NULL, NULL); } else { size_t i = 0; size_t num_found = 0; const char *testname = pkd_dargs.opts.testname; const char *testmatch = pkd_dargs.opts.testmatch; struct CMUnitTest matching_tests[sizeof(all_tests)]; memset(&matching_tests[0], 0x0, sizeof(matching_tests)); while (testmap[i].testname != NULL) { if ((testname != NULL) && (strcmp(testmap[i].testname, testname) == 0)) { memcpy(&matching_tests[0], &testmap[i].test, sizeof(struct CMUnitTest)); num_found += 1; break; } if ((testmatch != NULL) && (strstr(testmap[i].testname, testmatch) != NULL)) { memcpy(&matching_tests[num_found], &testmap[i].test, sizeof(struct CMUnitTest)); num_found += 1; } i += 1; } if (num_found > 0) { rc = _cmocka_run_group_tests("found", matching_tests, num_found, NULL, NULL); } else { fprintf(stderr, "Did not find test '%s'\n", testname); } } /* Clean up client keys for each enabled client. */ if (is_dropbear_client_enabled()) { cleanup_dropbear_client_rsa_key(); } if (is_openssh_client_enabled()) { cleanup_openssh_client_keys(); } /* Clean up any server keys that were generated. */ cleanup_rsa_key(); cleanup_ecdsa_keys(); if (!ssh_fips_mode()) { cleanup_ed25519_key(); #ifdef HAVE_DSA cleanup_dsa_key(); #endif } return rc; } static int pkd_init_socket_wrapper(void) { int rc = 0; char *mkdtemp_str = NULL; if (pkd_dargs.opts.socket_wrapper.mkdtemp_str == NULL) { goto out; } mkdtemp_str = strdup(pkd_dargs.opts.socket_wrapper.mkdtemp_str); if (mkdtemp_str == NULL) { fprintf(stderr, "pkd_init_socket_wrapper strdup failed\n"); goto errstrdup; } pkd_dargs.opts.socket_wrapper.mkdtemp_str = mkdtemp_str; if (mkdtemp(mkdtemp_str) == NULL) { fprintf(stderr, "pkd_init_socket_wrapper mkdtemp '%s' failed\n", mkdtemp_str); goto errmkdtemp; } if (setenv("SOCKET_WRAPPER_DIR", mkdtemp_str, 1) != 0) { fprintf(stderr, "pkd_init_socket_wrapper setenv failed\n"); goto errsetenv; } goto out; errsetenv: errmkdtemp: free(mkdtemp_str); errstrdup: rc = -1; out: return rc; } static int pkd_rmfiles(const char *path) { char bin[1024] = { 0 }; snprintf(&bin[0], sizeof(bin), "rm -f %s/*", path); return system_checked(bin); } static int pkd_cleanup_socket_wrapper(void) { int rc = 0; if (pkd_dargs.opts.socket_wrapper.mkdtemp_str == NULL) { goto out; } /* clean up socket-wrapper unix domain sockets */ if (pkd_rmfiles(pkd_dargs.opts.socket_wrapper.mkdtemp_str) != 0) { fprintf(stderr, "pkd_cleanup_socket_wrapper pkd_rmfiles '%s' failed\n", pkd_dargs.opts.socket_wrapper.mkdtemp_str); goto errrmfiles; } if (rmdir(pkd_dargs.opts.socket_wrapper.mkdtemp_str) != 0) { fprintf(stderr, "pkd_cleanup_socket_wrapper rmdir '%s' failed\n", pkd_dargs.opts.socket_wrapper.mkdtemp_str); goto errrmdir; } free(pkd_dargs.opts.socket_wrapper.mkdtemp_str); goto out; errrmdir: errrmfiles: rc = -1; out: return rc; } int main(int argc, char **argv) { int i = 0; int rc = 0; int exit_code = -1; unsetenv("SSH_AUTH_SOCK"); pkd_dargs.payload.buf = default_payload_buf; pkd_dargs.payload.len = default_payload_len; rc = ssh_init(); if (rc != 0) { goto out; } #ifdef HAVE_ARGP_H argp_parse(&parser, argc, argv, 0, 0, NULL); #else /* HAVE_ARGP_H */ (void) argc; (void) argv; #endif /* HAVE_ARGP_H */ rc = pkd_init_socket_wrapper(); if (rc != 0) { fprintf(stderr, "pkd_init_socket_wrapper failed: %d\n", rc); goto out_finalize; } if (pkd_dargs.opts.list != 0) { while (testmap[i].testname != NULL) { printf("%s\n", testmap[i++].testname); } } else { exit_code = pkd_run_tests(); if (exit_code != 0) { fprintf(stderr, "pkd_run_tests failed: %d\n", exit_code); } } rc = pkd_cleanup_socket_wrapper(); if (rc != 0) { fprintf(stderr, "pkd_cleanup_socket_wrapper failed: %d\n", rc); } out_finalize: rc = ssh_finalize(); if (rc != 0) { fprintf(stderr, "ssh_finalize: %d\n", rc); } out: return exit_code; } ================================================ FILE: src/libssh/tests/pkd/pkd_keyutil.c ================================================ /* * pkd_keyutil.c -- pkd test key utilities * * (c) 2014 Jon Simons */ #include "config.h" #include // for cmocka #include // for cmocka #include // for cmocka #include #include #include #include #include #include "torture.h" // for ssh_fips_mode() #include "pkd_client.h" #include "pkd_keyutil.h" #include "pkd_util.h" void setup_rsa_key() { int rc = 0; if (access(LIBSSH_RSA_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f " LIBSSH_RSA_TESTKEY); } assert_int_equal(rc, 0); } void setup_ed25519_key() { int rc = 0; if (access(LIBSSH_ED25519_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ed25519 -q -N \"\" -f " LIBSSH_ED25519_TESTKEY); } assert_int_equal(rc, 0); } #ifdef HAVE_DSA void setup_dsa_key() { int rc = 0; if (access(LIBSSH_DSA_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t dsa -q -N \"\" -f " LIBSSH_DSA_TESTKEY); } assert_int_equal(rc, 0); } #endif void setup_ecdsa_keys() { int rc = 0; if (access(LIBSSH_ECDSA_256_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 256 -q -N \"\" -f " LIBSSH_ECDSA_256_TESTKEY); assert_int_equal(rc, 0); } if (access(LIBSSH_ECDSA_384_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 384 -q -N \"\" -f " LIBSSH_ECDSA_384_TESTKEY); assert_int_equal(rc, 0); } if (access(LIBSSH_ECDSA_521_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 521 -q -N \"\" -f " LIBSSH_ECDSA_521_TESTKEY); assert_int_equal(rc, 0); } } void cleanup_rsa_key() { cleanup_key(LIBSSH_RSA_TESTKEY); } void cleanup_ed25519_key() { cleanup_key(LIBSSH_ED25519_TESTKEY); } #ifdef HAVE_DSA void cleanup_dsa_key() { cleanup_key(LIBSSH_DSA_TESTKEY); } #endif void cleanup_ecdsa_keys() { cleanup_key(LIBSSH_ECDSA_256_TESTKEY); cleanup_key(LIBSSH_ECDSA_384_TESTKEY); cleanup_key(LIBSSH_ECDSA_521_TESTKEY); } void setup_openssh_client_keys() { int rc = 0; if (access(OPENSSH_CA_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f " OPENSSH_CA_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_RSA_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t rsa -q -N \"\" -f " OPENSSH_RSA_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_RSA_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_RSA_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); if (access(OPENSSH_RSA_TESTKEY "-sha256-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -t rsa-sha2-256 " "-s " OPENSSH_CA_TESTKEY " " OPENSSH_RSA_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA256_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 256 -q -N \"\" -f " OPENSSH_ECDSA256_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA256_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_ECDSA256_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA384_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 384 -q -N \"\" -f " OPENSSH_ECDSA384_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA384_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_ECDSA384_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA521_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ecdsa -b 521 -q -N \"\" -f " OPENSSH_ECDSA521_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_ECDSA521_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_ECDSA521_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); if (!ssh_fips_mode()) { #ifdef HAVE_DSA if (access(OPENSSH_DSA_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t dsa -q -N \"\" -f " OPENSSH_DSA_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_DSA_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_DSA_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); #endif if (access(OPENSSH_ED25519_TESTKEY, F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -t ed25519 -q -N \"\" -f " OPENSSH_ED25519_TESTKEY); } assert_int_equal(rc, 0); if (access(OPENSSH_ED25519_TESTKEY "-cert.pub", F_OK) != 0) { rc = system_checked(OPENSSH_KEYGEN " -I ident -s " OPENSSH_CA_TESTKEY " " OPENSSH_ED25519_TESTKEY ".pub 2>/dev/null"); } assert_int_equal(rc, 0); } } void cleanup_openssh_client_keys() { cleanup_key(OPENSSH_CA_TESTKEY); cleanup_key(OPENSSH_RSA_TESTKEY); cleanup_file(OPENSSH_RSA_TESTKEY "-sha256-cert.pub"); cleanup_key(OPENSSH_ECDSA256_TESTKEY); cleanup_key(OPENSSH_ECDSA384_TESTKEY); cleanup_key(OPENSSH_ECDSA521_TESTKEY); if (!ssh_fips_mode()) { cleanup_key(OPENSSH_ED25519_TESTKEY); #ifdef HAVE_DSA cleanup_key(OPENSSH_DSA_TESTKEY); #endif } } void setup_dropbear_client_rsa_key() { int rc = 0; if (access(DROPBEAR_RSA_TESTKEY, F_OK) != 0) { rc = system_checked(DROPBEAR_KEYGEN " -t rsa -f " DROPBEAR_RSA_TESTKEY " 1>/dev/null 2>/dev/null"); } assert_int_equal(rc, 0); } void cleanup_dropbear_client_rsa_key() { unlink(DROPBEAR_RSA_TESTKEY); } ================================================ FILE: src/libssh/tests/pkd/pkd_keyutil.h ================================================ /* * pkd_keyutil.h -- * * (c) 2014 Jon Simons */ #ifndef __PKD_KEYUTIL_H__ #define __PKD_KEYUTIL_H__ #include "config.h" /* Server keys. */ #ifdef HAVE_DSA #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" #endif #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519" #define LIBSSH_ECDSA_256_TESTKEY "libssh_testkey.id_ecdsa256" #define LIBSSH_ECDSA_384_TESTKEY "libssh_testkey.id_ecdsa384" #define LIBSSH_ECDSA_521_TESTKEY "libssh_testkey.id_ecdsa521" #ifdef HAVE_DSA void setup_dsa_key(void); #endif void setup_rsa_key(void); void setup_ed25519_key(void); void setup_ecdsa_keys(void); #ifdef HAVE_DSA void cleanup_dsa_key(void); #endif void cleanup_rsa_key(void); void cleanup_ed25519_key(void); void cleanup_ecdsa_keys(void); /* Client keys. */ #ifdef HAVE_DSA #define OPENSSH_DSA_TESTKEY "openssh_testkey.id_dsa" #endif #define OPENSSH_RSA_TESTKEY "openssh_testkey.id_rsa" #define OPENSSH_ECDSA256_TESTKEY "openssh_testkey.id_ecdsa256" #define OPENSSH_ECDSA384_TESTKEY "openssh_testkey.id_ecdsa384" #define OPENSSH_ECDSA521_TESTKEY "openssh_testkey.id_ecdsa521" #define OPENSSH_ED25519_TESTKEY "openssh_testkey.id_ed25519" #define OPENSSH_CA_TESTKEY "libssh_testkey.ca" #define DROPBEAR_RSA_TESTKEY "dropbear_testkey.id_rsa" void setup_openssh_client_keys(void); void cleanup_openssh_client_keys(void); void setup_dropbear_client_rsa_key(void); void cleanup_dropbear_client_rsa_key(void); #define cleanup_file(name) do {\ if (access((name), F_OK) != -1) {\ unlink((name));\ }} while (0) #define cleanup_key(name) do {\ cleanup_file((name));\ cleanup_file((name ".pub"));\ cleanup_file((name "-cert.pub"));\ } while (0) #endif /* __PKD_KEYUTIL_H__ */ ================================================ FILE: src/libssh/tests/pkd/pkd_util.c ================================================ /* * pkd_util.c -- pkd utilities * * (c) 2014, 2018 Jon Simons */ #include #include #include #include #include #include #include #include "pkd_client.h" #include "pkd_util.h" /** * @brief runs system(3); exits if that is interrupted with SIGINT/QUIT * @returns 0 upon success, non-zero otherwise */ int system_checked(const char *cmd) { int rc = system(cmd); if (WIFSIGNALED(rc) && ((WTERMSIG(rc) == SIGINT) || (WTERMSIG(rc) == SIGQUIT))) { exit(1); } if (rc == -1) { return -1; } return WEXITSTATUS(rc); } static int bin_exists(const char *binary) { char bin[1024] = { 0 }; snprintf(&bin[0], sizeof(bin), "type %s 1>/dev/null 2>/dev/null", binary); return (system_checked(bin) == 0); } static int is_openssh_client_new_enough(void) { int rc = -1; FILE *fp = NULL; char version_buff[1024] = { 0 }; char *version; static int version_ok = 0; unsigned long int major = 0; char *tmp = NULL; if (version_ok) { return version_ok; } fp = popen("ssh -V 2>&1", "r"); if (fp == NULL) { fprintf(stderr, "failed to get OpenSSH client version\n"); goto done; } do { if (fgets(&version_buff[0], sizeof(version_buff), fp) == NULL) { fprintf(stderr, "failed to get OpenSSH client version string\n"); goto errfgets; } version = strstr(version_buff, "OpenSSH"); } while(version == NULL); /* "OpenSSH_...." */ if (strlen(version) < 11) { goto errversion; } /* Extract major. */ major = strtoul(version + 8, &tmp, 10); if ((tmp == (version + 8)) || ((errno == ERANGE) && (major == ULONG_MAX)) || ((errno != 0) && (major == 0)) || ((major < 1) || (major > 100))) { fprintf(stderr, "failed to parse OpenSSH client version, " "errno %d\n", errno); goto errversion; } if (major < 7) { fprintf(stderr, "error: minimum OpenSSH client version " "required is 7, found: %ld\n", major); goto errversion; } version_ok = 1; errversion: errfgets: rc = pclose(fp); if (rc != 0) { fprintf(stderr, "failed to get OpenSSH client version: %d\n", rc); } done: return version_ok; } int is_openssh_client_enabled(void) { return (bin_exists(OPENSSH_BINARY) && bin_exists(OPENSSH_KEYGEN) && is_openssh_client_new_enough()); } int is_dropbear_client_enabled(void) { return (bin_exists(DROPBEAR_BINARY) && bin_exists(DROPBEAR_KEYGEN)); } ================================================ FILE: src/libssh/tests/pkd/pkd_util.h ================================================ /* * pkd_keyutil.h -- * * (c) 2014 Jon Simons */ #ifndef __PKD_UTIL_H__ #define __PKD_UTIL_H__ int system_checked(const char *cmd); /* Is client 'X' enabled? */ int is_openssh_client_enabled(void); int is_dropbear_client_enabled(void); #endif /* __PKD_UTIL_H__ */ ================================================ FILE: src/libssh/tests/server/CMakeLists.txt ================================================ project(servertests C) if (WITH_SERVER AND UNIX AND NOT WIN32) find_package(socket_wrapper) add_subdirectory(test_server) set(LIBSSH_SERVER_TESTS torture_server torture_server_auth_kbdint torture_server_config ) include_directories(${libssh_SOURCE_DIR}/include ${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR} test_server) if (ARGP_INCLUDE_DIR) include_directories(${ARGP_INCLUDE_DIR}) endif () foreach(_SRV_TEST ${LIBSSH_SERVER_TESTS}) add_cmocka_test(${_SRV_TEST} SOURCES ${_SRV_TEST}.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TORTURE_LIBRARY} testserver util ) if (OSX) set_property( TEST ${_SRV_TEST} PROPERTY ENVIRONMENT DYLD_FORCE_FLAT_NAMESPACE=1;DYLD_INSERT_LIBRARIES=${SOCKET_WRAPPER_LIBRARY}) else () set_property( TEST ${_SRV_TEST} PROPERTY ENVIRONMENT ${TORTURE_ENVIRONMENT}) endif() endforeach() endif (WITH_SERVER AND UNIX AND NOT WIN32) ================================================ FILE: src/libssh/tests/server/test_server/CMakeLists.txt ================================================ project(test_server C) if (WITH_SERVER AND UNIX AND NOT WIN32) find_package(socket_wrapper) set(server_SRCS main.c ) add_library(testserver STATIC test_server.c default_cb.c) set(LIBSSH_SERVER_TESTS # torture_server_kbdint ) include_directories(${libssh_SOURCE_DIR}/include ${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR}) if (ARGP_INCLUDE_DIR) include_directories(${ARGP_INCLUDE_DIR}) endif () if (UNIX AND NOT WIN32) add_executable(test_server ${server_SRCS}) target_compile_options(test_server PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(test_server testserver ssh::ssh ${ARGP_LIBRARY} util) endif () endif (WITH_SERVER AND UNIX AND NOT WIN32) ================================================ FILE: src/libssh/tests/server/test_server/default_cb.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "test_server.h" #include "default_cb.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBUTIL_H #include #endif #ifdef HAVE_PTY_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTIL_H #include #endif int auth_pubkey_cb(UNUSED_PARAM(ssh_session session), const char *user, UNUSED_PARAM(struct ssh_key_struct *pubkey), char signature_state, void *userdata) { struct session_data_st *sdata; sdata = (struct session_data_st *)userdata; if (sdata == NULL) { fprintf(stderr, "Error: NULL userdata\n"); goto null_userdata; } printf("Public key authentication of user %s\n", user); switch(signature_state) { case SSH_PUBLICKEY_STATE_NONE: case SSH_PUBLICKEY_STATE_VALID: break; default: goto denied; } /* TODO */ /* Check wheter the user and public key are in authorized keys list */ /* Authenticated */ printf("Authenticated\n"); sdata->authenticated = 1; sdata->auth_attempts = 0; return SSH_AUTH_SUCCESS; denied: sdata->auth_attempts++; null_userdata: return SSH_AUTH_DENIED; } /* TODO implement proper pam authentication cb */ int auth_password_cb(UNUSED_PARAM(ssh_session session), const char *user, const char *password, void *userdata) { bool known_user = false; bool valid_password = false; struct session_data_st *sdata; sdata = (struct session_data_st *)userdata; if (sdata == NULL) { fprintf(stderr, "Error: NULL userdata\n"); goto null_userdata; } if (sdata->username == NULL) { fprintf(stderr, "Error: expected username not set\n"); goto denied; } if (sdata->password == NULL) { fprintf(stderr, "Error: expected password not set\n"); goto denied; } printf("Password authentication of user %s\n", user); known_user = !(strcmp(user, sdata->username)); valid_password = !(strcmp(password, sdata->password)); if (known_user && valid_password) { sdata->authenticated = 1; sdata->auth_attempts = 0; printf("Authenticated\n"); return SSH_AUTH_SUCCESS; } denied: sdata->auth_attempts++; null_userdata: return SSH_AUTH_DENIED; } #if WITH_GSSAPI int auth_gssapi_mic_cb(ssh_session session, UNUSED_PARAM(const char *user), UNUSED_PARAM(const char *principal), void *userdata) { ssh_gssapi_creds creds; struct session_data_st *sdata; sdata = (struct session_data_st *)userdata; if (sdata == NULL) { fprintf(stderr, "Error: NULL userdata\n"); goto null_userdata; } printf("GSSAPI authentication\n"); creds = ssh_gssapi_get_creds(session); if (creds != NULL) { printf("Received some gssapi credentials\n"); } else { printf("Not received any forwardable creds\n"); goto denied; } printf("Authenticated\n"); sdata->authenticated = 1; sdata->auth_attempts = 0; return SSH_AUTH_SUCCESS; denied: sdata->auth_attempts++; null_userdata: return SSH_AUTH_DENIED; } #endif int channel_data_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), void *data, uint32_t len, UNUSED_PARAM(int is_stderr), void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) { rc = SSH_OK; goto end; } rc = write(cdata->child_stdin, (char *) data, len); end: return rc; } void channel_eof_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), void *userdata) { struct channel_data_st *cdata; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto end; } end: return; } void channel_close_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), void *userdata) { struct channel_data_st *cdata; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto end; } end: return; } void channel_signal_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(const char *signal), void *userdata) { struct channel_data_st *cdata; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto end; } end: return; } void channel_exit_status_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(int exit_status), void *userdata) { struct channel_data_st *cdata; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto end; } end: return; } void channel_exit_signal_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(const char *signal), UNUSED_PARAM(int core), UNUSED_PARAM(const char *errmsg), UNUSED_PARAM(const char *lang), void *userdata) { struct channel_data_st *cdata; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto end; } end: return; } int channel_pty_request_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(const char *term), int cols, int rows, int py, int px, void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } cdata->winsize->ws_row = rows; cdata->winsize->ws_col = cols; cdata->winsize->ws_xpixel = px; cdata->winsize->ws_ypixel = py; rc = openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL, cdata->winsize); if (rc != 0) { fprintf(stderr, "Failed to open pty\n"); rc = SSH_ERROR; goto end; } rc = SSH_OK; end: return rc; } int channel_pty_resize_cb(ssh_session session, ssh_channel channel, int cols, int rows, int py, int px, void *userdata) { struct channel_data_st *cdata; int rc; (void) session; (void) channel; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } cdata->winsize->ws_row = rows; cdata->winsize->ws_col = cols; cdata->winsize->ws_xpixel = px; cdata->winsize->ws_ypixel = py; if (cdata->pty_master != -1) { rc = ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize); goto end; } rc = SSH_ERROR; end: return rc; } void channel_auth_agent_req_callback(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(void *userdata)) { /* TODO */ } void channel_x11_req_callback(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(int single_connection), UNUSED_PARAM(const char *auth_protocol), UNUSED_PARAM(const char *auth_cookie), UNUSED_PARAM(uint32_t screen_number), UNUSED_PARAM(void *userdata)) { /* TODO */ } static int exec_pty(const char *mode, const char *command, struct channel_data_st *cdata) { int rc; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } cdata->pid = fork(); switch(cdata->pid) { case -1: close(cdata->pty_master); close(cdata->pty_slave); fprintf(stderr, "Failed to fork\n"); rc = SSH_ERROR; goto end; case 0: close(cdata->pty_master); if (login_tty(cdata->pty_slave) != 0) { exit(1); } execl("/bin/sh", "sh", mode, command, NULL); exit(0); default: close(cdata->pty_slave); /* pty fd is bi-directional */ cdata->child_stdout = cdata->child_stdin = cdata->pty_master; } rc = SSH_OK; end: return rc; } static int exec_nopty(const char *command, struct channel_data_st *cdata) { int in[2], out[2], err[2]; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); goto stdin_failed; } /* Do the plumbing to be able to talk with the child process. */ if (pipe(in) != 0) { goto stdin_failed; } if (pipe(out) != 0) { goto stdout_failed; } if (pipe(err) != 0) { goto stderr_failed; } switch(cdata->pid = fork()) { case -1: goto fork_failed; case 0: /* Finish the plumbing in the child process. */ close(in[1]); close(out[0]); close(err[0]); dup2(in[0], STDIN_FILENO); dup2(out[1], STDOUT_FILENO); dup2(err[1], STDERR_FILENO); close(in[0]); close(out[1]); close(err[1]); /* exec the requested command. */ execl("/bin/sh", "sh", "-c", command, NULL); exit(0); } close(in[0]); close(out[1]); close(err[1]); cdata->child_stdin = in[1]; cdata->child_stdout = out[0]; cdata->child_stderr = err[0]; return SSH_OK; fork_failed: close(err[0]); close(err[1]); stderr_failed: close(out[0]); close(out[1]); stdout_failed: close(in[0]); close(in[1]); stdin_failed: return SSH_ERROR; } int channel_shell_request_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } if(cdata->pid > 0) { rc = SSH_ERROR; goto end; } if (cdata->pty_master != -1 && cdata->pty_slave != -1) { rc = exec_pty("-l", NULL, cdata); goto end; } /* Client requested a shell without a pty, let's pretend we allow that */ rc = SSH_OK; end: return rc; } int channel_exec_request_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), const char *command, void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } if(cdata->pid > 0) { rc = SSH_ERROR; goto end; } if (cdata->pty_master != -1 && cdata->pty_slave != -1) { rc = exec_pty("-c", command, cdata); goto end; } rc = exec_nopty(command, cdata); end: return rc; } int channel_env_request_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(const char *env_name), UNUSED_PARAM(const char *env_value), void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } rc = SSH_OK; end: return rc; } int channel_subsystem_request_cb(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata) { struct channel_data_st *cdata; int rc; cdata = (struct channel_data_st *)userdata; if (cdata == NULL) { fprintf(stderr, "NULL userdata\n"); rc = SSH_ERROR; goto end; } rc = strcmp(subsystem, "sftp"); if (rc == 0) { rc = channel_exec_request_cb(session, channel, SFTP_SERVER_PATH, userdata); goto end; } /* TODO add other subsystems */ rc = SSH_ERROR; end: return rc; } int channel_write_wontblock_cb(UNUSED_PARAM(ssh_session session), UNUSED_PARAM(ssh_channel channel), UNUSED_PARAM(size_t bytes), UNUSED_PARAM(void *userdata)) { /* TODO */ return 0; } ssh_channel channel_new_session_cb(ssh_session session, void *userdata) { struct session_data_st *sdata = NULL; ssh_channel chan = NULL; sdata = (struct session_data_st *)userdata; if (sdata == NULL) { fprintf(stderr, "NULL userdata"); goto end; } chan = ssh_channel_new(session); if (chan == NULL) { fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session)); goto end; } sdata->channel = chan; end: return chan; } #ifdef WITH_PCAP static void set_pcap(struct session_data_st *sdata, ssh_session session, char *pcap_file) { int rc = 0; if (sdata == NULL) { return; } if (pcap_file == NULL) { return; } sdata->pcap = ssh_pcap_file_new(); if (sdata->pcap == NULL) { return; } rc = ssh_pcap_file_open(sdata->pcap, pcap_file); if (rc == SSH_ERROR) { fprintf(stderr, "Error opening pcap file\n"); ssh_pcap_file_free(sdata->pcap); sdata->pcap = NULL; return; } ssh_set_pcap_file(session, sdata->pcap); } static void cleanup_pcap(struct session_data_st *sdata) { if (sdata == NULL) { return; } if (sdata->pcap == NULL) { return; } ssh_pcap_file_free(sdata->pcap); sdata->pcap = NULL; } #endif static int process_stdout(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write(channel, buf, n); } } return n; } static int process_stderr(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write_stderr(channel, buf, n); } } return n; } /* The caller is responsible to set the userdata to be provided to the callback * The caller is responsible to free the allocated structure * */ struct ssh_server_callbacks_struct *get_default_server_cb(void) { struct ssh_server_callbacks_struct *cb; cb = (struct ssh_server_callbacks_struct *)calloc(1, sizeof(struct ssh_server_callbacks_struct)); if (cb == NULL) { fprintf(stderr, "Out of memory\n"); goto end; } cb->auth_password_function = auth_password_cb; cb->auth_pubkey_function = auth_pubkey_cb; cb->channel_open_request_session_function = channel_new_session_cb; #if WITH_GSSAPI cb->auth_gssapi_mic_function = auth_gssapi_mic_cb; #endif end: return cb; } /* The caller is responsible to set the userdata to be provided to the callback * The caller is responsible to free the allocated structure * */ struct ssh_channel_callbacks_struct *get_default_channel_cb(void) { struct ssh_channel_callbacks_struct *cb; cb = (struct ssh_channel_callbacks_struct *)calloc(1, sizeof(struct ssh_channel_callbacks_struct)); if (cb == NULL) { fprintf(stderr, "Out of memory\n"); goto end; } cb->channel_pty_request_function = channel_pty_request_cb; cb->channel_pty_window_change_function = channel_pty_resize_cb; cb->channel_shell_request_function = channel_shell_request_cb; cb->channel_env_request_function = channel_env_request_cb; cb->channel_subsystem_request_function = channel_subsystem_request_cb; cb->channel_exec_request_function = channel_exec_request_cb; cb->channel_data_function = channel_data_cb; end: return cb; }; void default_handle_session_cb(ssh_event event, ssh_session session, struct server_state_st *state) { int n; int rc = 0; /* Structure for storing the pty size. */ struct winsize wsize = { .ws_row = 0, .ws_col = 0, .ws_xpixel = 0, .ws_ypixel = 0 }; /* Our struct holding information about the channel. */ struct channel_data_st cdata = { .pid = 0, .pty_master = -1, .pty_slave = -1, .child_stdin = -1, .child_stdout = -1, .child_stderr = -1, .event = NULL, .winsize = &wsize }; /* Our struct holding information about the session. */ struct session_data_st sdata = { .channel = NULL, .auth_attempts = 0, .authenticated = 0, .username = SSHD_DEFAULT_USER, .password = SSHD_DEFAULT_PASSWORD }; struct ssh_channel_callbacks_struct *channel_cb = NULL; struct ssh_server_callbacks_struct *server_cb = NULL; if (state == NULL) { fprintf(stderr, "NULL server state provided\n"); goto end; } /* If callbacks were provided use them. Otherwise, use default callbacks */ if (state->server_cb != NULL) { /* This is a macro, it does not return a value */ ssh_callbacks_init(state->server_cb); rc = ssh_set_server_callbacks(session, state->server_cb); if (rc) { goto end; } } else { server_cb = get_default_server_cb(); if (server_cb == NULL) { goto end; } server_cb->userdata = &sdata; /* This is a macro, it does not return a value */ ssh_callbacks_init(server_cb); rc = ssh_set_server_callbacks(session, server_cb); if (rc) { goto end; } } sdata.server_state = (void *)state; cdata.server_state = (void *)state; #ifdef WITH_PCAP set_pcap(&sdata, session, state->pcap_file); #endif if (state->expected_username != NULL) { sdata.username = state->expected_username; } if (state->expected_password != NULL) { sdata.password = state->expected_password; } if (ssh_handle_key_exchange(session) != SSH_OK) { fprintf(stderr, "%s\n", ssh_get_error(session)); return; } /* Set the supported authentication methods */ if (state->auth_methods) { ssh_set_auth_methods(session, state->auth_methods); } else { ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY); } ssh_event_add_session(event, session); n = 0; while (sdata.authenticated == 0 || sdata.channel == NULL) { /* If the user has used up all attempts, or if he hasn't been able to * authenticate in 10 seconds (n * 100ms), disconnect. */ if (sdata.auth_attempts >= state->max_tries || n >= 100) { return; } if (ssh_event_dopoll(event, 100) == SSH_ERROR) { fprintf(stderr, "do_poll error: %s\n", ssh_get_error(session)); return; } n++; } /* TODO check return values */ if (state->channel_cb != NULL) { ssh_callbacks_init(state->channel_cb); rc = ssh_set_channel_callbacks(sdata.channel, state->channel_cb); if (rc) { goto end; } } else { channel_cb = get_default_channel_cb(); if (channel_cb == NULL) { goto end; } channel_cb->userdata = &cdata; ssh_callbacks_init(channel_cb); rc = ssh_set_channel_callbacks(sdata.channel, channel_cb); if (rc) { goto end; } } do { /* Poll the main event which takes care of the session, the channel and * even our child process's stdout/stderr (once it's started). */ if (ssh_event_dopoll(event, -1) == SSH_ERROR) { ssh_channel_close(sdata.channel); } /* If child process's stdout/stderr has been registered with the event, * or the child process hasn't started yet, continue. */ if (cdata.event != NULL || cdata.pid == 0) { continue; } /* Executed only once, once the child process starts. */ cdata.event = event; /* If stdout valid, add stdout to be monitored by the poll event. */ if (cdata.child_stdout != -1) { if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stdout to poll context\n"); ssh_channel_close(sdata.channel); } } /* If stderr valid, add stderr to be monitored by the poll event. */ if (cdata.child_stderr != -1){ if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stderr to poll context\n"); ssh_channel_close(sdata.channel); } } } while(ssh_channel_is_open(sdata.channel) && (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0)); close(cdata.pty_master); close(cdata.child_stdin); close(cdata.child_stdout); close(cdata.child_stderr); /* Remove the descriptors from the polling context, since they are now * closed, they will always trigger during the poll calls. */ ssh_event_remove_fd(event, cdata.child_stdout); ssh_event_remove_fd(event, cdata.child_stderr); /* If the child process exited. */ if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) { rc = WEXITSTATUS(rc); ssh_channel_request_send_exit_status(sdata.channel, rc); /* If client terminated the channel or the process did not exit nicely, * but only if something has been forked. */ } else if (cdata.pid > 0) { kill(cdata.pid, SIGKILL); } ssh_channel_send_eof(sdata.channel); ssh_channel_close(sdata.channel); /* Wait up to 5 seconds for the client to terminate the session. */ for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) { ssh_event_dopoll(event, 100); } end: #ifdef WITH_PCAP cleanup_pcap(&sdata); #endif if (channel_cb != NULL) { free(channel_cb); } if (server_cb != NULL) { free(server_cb); } return; } ================================================ FILE: src/libssh/tests/server/test_server/default_cb.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #define SSHD_DEFAULT_USER "libssh" #define SSHD_DEFAULT_PASSWORD "libssh" #define SSHD_DEFAULT_PORT 2222 #define SSHD_DEFAULT_ADDRESS "127.0.0.1" #define SSHD_DEFAULT_PCAP_FILE "debug.server.pcap" #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif #define BUF_SIZE 1048576 #define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR) #define SFTP_SERVER_PATH "/usr/lib/sftp-server" #ifdef HAVE_PTY_H #include #endif /* A userdata struct for channel. */ struct channel_data_st { /* pid of the child process the channel will spawn. */ pid_t pid; /* For PTY allocation */ socket_t pty_master; socket_t pty_slave; /* For communication with the child process. */ socket_t child_stdin; socket_t child_stdout; /* Only used for subsystem and exec requests. */ socket_t child_stderr; /* Event which is used to poll the above descriptors. */ ssh_event event; /* Terminal size struct. */ struct winsize *winsize; /* This pointer will hold the server state for default callbacks */ void *server_state; /* This pointer is useful to set data for custom callbacks */ void *extra_data; }; /* A userdata struct for session. */ struct session_data_st { /* Pointer to the channel the session will allocate. */ ssh_channel channel; int auth_attempts; int authenticated; const char *username; const char *password; #ifdef WITH_PCAP ssh_pcap_file pcap; #endif /* This pointer will hold the server state for default callbacks */ void *server_state; /* This pointer is useful to set data for custom callbacks */ void *extra_data; }; int auth_password_cb(ssh_session session, const char *user, const char *password, void *userdata); #if WITH_GSSAPI int auth_gssapi_mic_cb(ssh_session session, const char *user, const char *principal, void *userdata); #endif int channel_data_cb(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata); void channel_eof_cb(ssh_session session, ssh_channel channel, void *userdata); void channel_close_cb(ssh_session session, ssh_channel channel, void *userdata); void channel_signal_cb (ssh_session session, ssh_channel channel, const char *signal, void *userdata); void channel_exit_status_cb (ssh_session session, ssh_channel channel, int exit_status, void *userdata); void channel_exit_signal_cb(ssh_session session, ssh_channel channel, const char *signal, int core, const char *errmsg, const char *lang, void *userdata); int channel_pty_request_cb(ssh_session session, ssh_channel channel, const char *term, int cols, int rows, int py, int px, void *userdata); int channel_pty_resize_cb(ssh_session session, ssh_channel channel, int cols, int rows, int py, int px, void *userdata); int channel_shell_request_cb(ssh_session session, ssh_channel channel, void *userdata); void channel_auth_agent_req_callback(ssh_session session, ssh_channel channel, void *userdata); void channel_x11_req_callback(ssh_session session, ssh_channel channel, int single_connection, const char *auth_protocol, const char *auth_cookie, uint32_t screen_number, void *userdata); int channel_exec_request_cb(ssh_session session, ssh_channel channel, const char *command, void *userdata); int channel_env_request_cb(ssh_session session, ssh_channel channel, const char *env_name, const char *env_value, void *userdata); int channel_subsystem_request_cb(ssh_session session, ssh_channel channel, const char *subsystem, void *userdata); int channel_write_wontblock_cb(ssh_session session, ssh_channel channel, size_t bytes, void *userdata); ssh_channel channel_new_session_cb(ssh_session session, void *userdata); /* The caller is responsible to set the userdata to be provided to the callback * The caller is responsible to free the allocated structure * */ struct ssh_server_callbacks_struct *get_default_server_cb(void); /* The caller is responsible to set the userdata to be provided to the callback * The caller is responsible to free the allocated structure * */ struct ssh_channel_callbacks_struct *get_default_channel_cb(void); void default_handle_session_cb(ssh_event event, ssh_session session, struct server_state_st *state); ================================================ FILE: src/libssh/tests/server/test_server/main.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "test_server.h" #include "default_cb.h" #include #include #include #include #ifdef HAVE_ARGP_H #include #endif #include #include #include #include struct arguments_st { char *address; char *port; char *ecdsa_key; char *dsa_key; char *ed25519_key; char *rsa_key; char *host_key; char *verbosity; char *auth_methods; bool with_pcap; char *pcap_file; char *username; char *password; char *config_file; bool with_global_config; }; static void free_arguments(struct arguments_st *arguments) { if (arguments == NULL) { goto end; } SAFE_FREE(arguments->address); SAFE_FREE(arguments->port); SAFE_FREE(arguments->ecdsa_key); SAFE_FREE(arguments->dsa_key); SAFE_FREE(arguments->ed25519_key); SAFE_FREE(arguments->rsa_key); SAFE_FREE(arguments->host_key); SAFE_FREE(arguments->verbosity); SAFE_FREE(arguments->auth_methods); SAFE_FREE(arguments->pcap_file); SAFE_FREE(arguments->username); SAFE_FREE(arguments->password); SAFE_FREE(arguments->config_file); end: return; } #ifdef HAVE_ARGP_H static void print_auth_methods(int auth_methods) { printf("auth_methods = \n"); if (auth_methods & SSH_AUTH_METHOD_NONE) { printf("\tSSH_AUTH_METHOD_NONE\n"); } if (auth_methods & SSH_AUTH_METHOD_PASSWORD) { printf("\tSSH_AUTH_METHOD_PASSWORD\n"); } if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { printf("\tSSH_AUTH_METHOD_PUBLICKEY\n"); } if (auth_methods & SSH_AUTH_METHOD_HOSTBASED) { printf("\tSSH_AUTH_METHOD_HOSTBASED\n"); } if (auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { printf("\tSSH_AUTH_METHOD_INTERACTIVE\n"); } if (auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { printf("\tSSH_AUTH_METHOD_GSSAPI_MIC\n"); } } static void print_verbosity(int verbosity) { printf("verbosity = "); switch(verbosity) { case SSH_LOG_NOLOG: printf("NO LOG\n"); break; case SSH_LOG_WARNING: printf("WARNING\n"); break; case SSH_LOG_PROTOCOL: printf("PROTOCOL\n"); break; case SSH_LOG_PACKET: printf("PACKET\n"); break; case SSH_LOG_FUNCTIONS: printf("FUNCTIONS\n"); break; default: printf("UNKNOWN\n");; break; } } static void print_server_state(struct server_state_st *state) { if (state) { printf("===================| STATE |=====================\n"); printf("address = %s\n", state->address? state->address: "NULL"); printf("port = %d\n", state->port? state->port: 0); printf("=================================================\n"); printf("ecdsa_key = %s\n", state->ecdsa_key? state->ecdsa_key: "NULL"); printf("dsa_key = %s\n", state->dsa_key? state->dsa_key: "NULL"); printf("ed25519_key = %s\n", state->ed25519_key? state->ed25519_key: "NULL"); printf("rsa_key = %s\n", state->rsa_key? state->rsa_key: "NULL"); printf("host_key = %s\n", state->host_key? state->host_key: "NULL"); printf("=================================================\n"); print_auth_methods(state->auth_methods); print_verbosity(state->verbosity); printf("with_pcap = %s\n", state->with_pcap? "TRUE": "FALSE"); printf("pcap_file = %s\n", state->pcap_file? state->pcap_file: "NULL"); printf("=================================================\n"); printf("username = %s\n", state->expected_username? state->expected_username: "NULL"); printf("password = %s\n", state->expected_password? state->expected_password: "NULL"); printf("=================================================\n"); printf("with_global_config = %s\n", state->parse_global_config? "TRUE": "FALSE"); printf("config_file = %s\n", state->config_file? state->config_file: "NULL"); printf("=================================================\n"); } } static int init_server_state(struct server_state_st *state, struct arguments_st *arguments) { int rc = 0; if (state == NULL) { rc = SSH_ERROR; goto end; } /* Initialize server state. The "arguments structure" */ if (arguments->address) { state->address = arguments->address; arguments->address = NULL; } else { state->address = strdup(SSHD_DEFAULT_ADDRESS); if (state->address == NULL) { fprintf(stderr, "Out of memory\n"); rc = SSH_ERROR; goto end; } } if (arguments->port) { state->port = atoi(arguments->port); } else { state->port = SSHD_DEFAULT_PORT; } if (arguments->ecdsa_key) { state->ecdsa_key = arguments->ecdsa_key; arguments->ecdsa_key = NULL; } else { state->ecdsa_key = NULL; } if (arguments->dsa_key) { state->dsa_key = arguments->dsa_key; arguments->dsa_key = NULL; } else { state->dsa_key = NULL; } if (arguments->ed25519_key) { state->ed25519_key = arguments->ed25519_key; arguments->ed25519_key = NULL; } else { state->ed25519_key = NULL; } if (arguments->rsa_key) { state->rsa_key = arguments->rsa_key; arguments->rsa_key = NULL; } else { state->rsa_key = NULL; } if (arguments->host_key) { state->host_key = arguments->host_key; arguments->host_key = NULL; } else { state->host_key = NULL; } if (arguments->username) { state->expected_username = arguments->username; arguments->username = NULL; } else { state->expected_username = strdup(SSHD_DEFAULT_USER); if (state->expected_username == NULL) { fprintf(stderr, "Out of memory\n"); rc = SSH_ERROR; goto end; } } if (arguments->password) { state->expected_password = arguments->password; arguments->password = NULL; } else { state->expected_password = strdup(SSHD_DEFAULT_PASSWORD); if (state->expected_password == NULL) { fprintf(stderr, "Out of memory\n"); rc = SSH_ERROR; goto end; } } if (arguments->verbosity) { state->verbosity = atoi(arguments->verbosity); } else { state->verbosity = 0; } if (arguments->auth_methods) { state->auth_methods = atoi(arguments->auth_methods); } else { state->auth_methods = SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY; } state->with_pcap = arguments->with_pcap; if (arguments->pcap_file) { state->pcap_file = arguments->pcap_file; arguments->pcap_file = NULL; } else { if (arguments->with_pcap) { state->pcap_file = strdup(SSHD_DEFAULT_PCAP_FILE); if (state->pcap_file == NULL) { fprintf(stderr, "Out of memory\n"); rc = SSH_ERROR; goto end; } } else { state->pcap_file = NULL; } } state->parse_global_config = arguments->with_global_config; if (arguments->config_file) { state->config_file = arguments->config_file; arguments->config_file = NULL; } /* TODO make configurable */ state->max_tries = 3; state->error = 0; if (state) { print_server_state(state); } /* TODO make callbacks configurable through command line ? */ /* Set callbacks to be used */ state->handle_session = default_handle_session_cb; /* Check required parameters */ if (state->address == NULL) { rc = SSH_ERROR; goto end; } end: if (rc != 0) { free_server_state(state); } return rc; } const char *argp_program_version = "libssh test server " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = ""; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "ecdsakey", .key = 'c', .arg = "FILE", .flags = 0, .doc = "Set the ECDSA key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the DSA key.", .group = 0 }, { .name = "ed25519key", .key = 'e', .arg = "FILE", .flags = 0, .doc = "Set the ed25519 key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the RSA key.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "pcapfile", .key = 'f', .arg = "FILE", .flags = 0, .doc = "Set the pcap output file.", .group = 0 }, { .name = "auth-methods", .key = 'a', .arg = "METHODS", .flags = 0, .doc = "Set supported authentication methods.", .group = 0 }, { .name = "user", .key = 'u', .arg = "USERNAME", .flags = 0, .doc = "Set expected username.", .group = 0 }, { .name = "verbosity", .key = 'v', .arg = "VERBOSITY", .flags = 0, .doc = "Set output verbosity [0-4].", .group = 0 }, { .name = "with-pcap", .key = 'w', .arg = NULL, .flags = 0, .doc = "Use PCAP.", .group = 0 }, { .name = "without-global-config", .key = 'g', .arg = NULL, .flags = 0, .doc = "Do not use system-wide configuration file.", .group = 0 }, { .name = "config", .key = 'C', .arg = "CONFIG_FILE", .flags = 0, .doc = "Use this server configuration file.", .group = 0 }, { .name = NULL } }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ struct arguments_st *arguments = state->input; error_t rc = 0; if (arguments == NULL) { fprintf(stderr, "NULL pointer to arguments structure provided\n"); rc = EINVAL; goto end; } switch (key) { case 'c': arguments->ecdsa_key = strdup(arg); if (arguments->ecdsa_key == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'd': arguments->dsa_key = strdup(arg); if (arguments->dsa_key == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'e': arguments->ed25519_key = strdup(arg); if (arguments->ed25519_key == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'f': arguments->pcap_file = strdup(arg); if (arguments->pcap_file == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'k': arguments->host_key = strdup(arg); if (arguments->host_key == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'a': arguments->auth_methods = strdup(arg); if (arguments->auth_methods == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'p': arguments->port = strdup(arg); if (arguments->port == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'r': arguments->rsa_key = strdup(arg); if (arguments->rsa_key == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'u': arguments->username = strdup(arg); if (arguments->username == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'v': arguments->verbosity = strdup(arg); if (arguments->verbosity == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case 'w': arguments->with_pcap = true; break; case 'g': arguments->with_global_config = false; break; case 'C': arguments->config_file = strdup(arg); if (arguments->config_file == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ printf("Too many arguments\n"); argp_usage(state); } arguments->address = strdup(arg); if (arguments->address == NULL) { fprintf(stderr, "Out of memory\n"); rc = ENOMEM; goto end; } break; case ARGP_KEY_END: if (state->arg_num < 1) { printf("Too few arguments\n"); /* Not enough arguments. */ argp_usage(state); } break; default: return ARGP_ERR_UNKNOWN; } end: return rc; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ int main(UNUSED_PARAM(int argc), UNUSED_PARAM(char **argv)) { int rc; struct arguments_st arguments = { .address = NULL, .with_global_config = true, }; struct server_state_st state = { .address = NULL, }; #ifdef HAVE_ARGP_H argp_parse (&argp, argc, argv, 0, 0, &arguments); #endif /* Initialize the state using default or given parameters */ rc = init_server_state(&state, &arguments); if (rc != 0) { goto free_arguments; } /* Free the arguments used to initialize the state before fork */ free_arguments(&arguments); /* Run the server */ rc = run_server(&state); if (rc != 0) { goto free_state; } free_state: free_server_state(&state); free_arguments: free_arguments(&arguments); return rc; } ================================================ FILE: src/libssh/tests/server/test_server/test_server.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "test_server.h" #include #include #include #include #include #include #include #include #include #include #include void free_server_state(struct server_state_st *state) { if (state == NULL) { goto end; } SAFE_FREE(state->address); SAFE_FREE(state->ecdsa_key); SAFE_FREE(state->dsa_key); SAFE_FREE(state->ed25519_key); SAFE_FREE(state->rsa_key); SAFE_FREE(state->host_key); SAFE_FREE(state->pcap_file); SAFE_FREE(state->expected_username); SAFE_FREE(state->expected_password); SAFE_FREE(state->config_file); end: return; } /* SIGCHLD handler for cleaning up dead children. */ static void sigchld_handler(int signo) { (void) signo; while (waitpid(-1, NULL, WNOHANG) > 0); } int run_server(struct server_state_st *state) { ssh_session session = NULL; ssh_bind sshbind = NULL; ssh_event event = NULL; struct sigaction sa = { .sa_flags = 0 }; int rc; /* Check provided state */ if (state == NULL) { fprintf(stderr, "Invalid state\n"); return SSH_ERROR; } /* Set up SIGCHLD handler. */ sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa, NULL) != 0) { fprintf(stderr, "Failed to register SIGCHLD handler\n"); return SSH_ERROR; } if (state->address == NULL) { fprintf(stderr, "Missing bind address\n"); return SSH_ERROR; } if (state->address == NULL) { fprintf(stderr, "Missing bind address\n"); return SSH_ERROR; } sshbind = ssh_bind_new(); if (sshbind == NULL) { fprintf(stderr, "Out of memory\n"); return SSH_ERROR; } if (state->verbosity) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &state->verbosity); if (rc != 0) { fprintf(stderr, "Error setting verbosity level: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } } if (!state->parse_global_config) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_PROCESS_CONFIG, &(state->parse_global_config)); if (rc != 0) { goto free_sshbind; } } if (state->config_file) { rc = ssh_bind_options_parse_config(sshbind, state->config_file); if (rc != 0) { goto free_sshbind; } } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, state->address); if (rc != 0) { fprintf(stderr, "Error setting bind address: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &(state->port)); if (rc != 0) { fprintf(stderr, "Error setting bind port: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } if (state->dsa_key != NULL) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, state->dsa_key); if (rc != 0) { fprintf(stderr, "Error setting DSA key: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } } if (state->rsa_key != NULL) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, state->rsa_key); if (rc != 0) { fprintf(stderr, "Error setting RSA key: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } } if (state->ecdsa_key != NULL) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, state->ecdsa_key); if (rc != 0) { fprintf(stderr, "Error setting ECDSA key: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } } if (state->host_key) { rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, state->host_key); if (rc) { fprintf(stderr, "Error setting hostkey: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } } rc = ssh_bind_listen(sshbind); if (rc != 0) { fprintf(stderr, "Error listening to socket: %s\n", ssh_get_error(sshbind)); goto free_sshbind; } printf("Started libssh test server on port %d\n", state->port); for (;;) { session = ssh_new(); if (session == NULL) { fprintf(stderr, "Out of memory\n"); rc = SSH_ERROR; goto free_sshbind; } /* Blocks until there is a new incoming connection. */ rc = ssh_bind_accept(sshbind, session); if (rc != SSH_ERROR) { pid_t pid = fork(); switch(pid) { case 0: /* Remove the SIGCHLD handler inherited from parent. */ sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); /* Remove socket binding, which allows us to restart the * parent process, without terminating existing sessions. */ ssh_bind_free(sshbind); event = ssh_event_new(); if (event != NULL) { /* Blocks until the SSH session ends by either * child process exiting, or client disconnecting. */ state->handle_session(event, session, state); ssh_event_free(event); } else { fprintf(stderr, "Could not create polling context\n"); } ssh_disconnect(session); ssh_free(session); free_server_state(state); exit(0); case -1: fprintf(stderr, "Failed to fork\n"); } } else { fprintf(stderr, "Error accepting a connection: %s\n", ssh_get_error(sshbind)); } /* Since the session has been passed to a child fork, do some cleaning * up at the parent process. */ ssh_disconnect(session); ssh_free(session); } rc = 0; free_sshbind: ssh_bind_free(sshbind); return rc; } pid_t fork_run_server(struct server_state_st *state) { pid_t pid; int rc; char err_str[1024] = {0}; struct sigaction sa; /* Check provided state */ if (state == NULL) { fprintf(stderr, "Invalid state\n"); return -1; } /* Set up SIGCHLD handler. */ sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa, NULL) != 0) { strerror_r(errno, err_str, 1024); fprintf(stderr, "Failed to register SIGCHLD handler: %s\n", err_str); return -1; } pid = fork(); switch(pid) { case 0: /* Remove the SIGCHLD handler inherited from parent. */ sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); /* The child process starts a server which will listen for connections */ rc = run_server(state); if (rc != 0) { exit(rc); } exit(0); case -1: strerror_r(errno, err_str, 1024); fprintf(stderr, "Failed to fork: %s\n", err_str); return -1; default: /* Return the child pid */ return pid; } } ================================================ FILE: src/libssh/tests/server/test_server/test_server.h ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include #include #include #include struct server_state_st { /* Arguments */ char *address; int port; char *ecdsa_key; char *dsa_key; char *ed25519_key; char *rsa_key; char *host_key; int verbosity; int auth_methods; bool with_pcap; char *pcap_file; char *expected_username; char *expected_password; char *config_file; bool parse_global_config; /* State */ int max_tries; int error; struct ssh_server_callbacks_struct *server_cb; struct ssh_channel_callbacks_struct *channel_cb; /* Callback to handle the session, should block until disconnected */ void (*handle_session)(ssh_event event, ssh_session session, struct server_state_st *state); }; /*TODO: Add documentation */ void free_server_state(struct server_state_st *state); /*TODO: Add documentation */ int run_server(struct server_state_st *state); /*TODO: Add documentation */ pid_t fork_run_server(struct server_state_st *state); ================================================ FILE: src/libssh/tests/server/torture_server.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include #include #include #include #include "torture.h" #include "torture_key.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include "test_server.h" #include "default_cb.h" #define TORTURE_KNOWN_HOSTS_FILE "libssh_torture_knownhosts" const char template[] = "temp_dir_XXXXXX"; struct test_server_st { struct torture_state *state; struct server_state_st *ss; char *cwd; char *temp_dir; }; static int setup_default_server(void **state) { struct torture_state *s; struct server_state_st *ss; struct test_server_st *tss; #ifdef HAVE_DSA char dsa_hostkey[1024]; #endif /* HAVE_DSA */ char ed25519_hostkey[1024] = {0}; char rsa_hostkey[1024]; char ecdsa_hostkey[1024]; //char trusted_ca_pubkey[1024]; char sshd_path[1024]; struct stat sb; const char *sftp_server_locations[] = { "/usr/lib/ssh/sftp-server", "/usr/libexec/sftp-server", "/usr/libexec/openssh/sftp-server", "/usr/lib/openssh/sftp-server", /* Debian */ }; size_t sftp_sl_size = ARRAY_SIZE(sftp_server_locations); const char *sftp_server; size_t i; int rc; char pid_str[1024]; pid_t pid; assert_non_null(state); tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st)); assert_non_null(tss); torture_setup_socket_dir((void **)&s); assert_non_null(s->socket_dir); /* Set the default interface for the server */ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); setenv("PAM_WRAPPER", "1", 1); snprintf(sshd_path, sizeof(sshd_path), "%s/sshd", s->socket_dir); rc = mkdir(sshd_path, 0755); assert_return_code(rc, errno); snprintf(ed25519_hostkey, sizeof(ed25519_hostkey), "%s/sshd/ssh_host_ed25519_key", s->socket_dir); torture_write_file(ed25519_hostkey, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); #ifdef HAVE_DSA snprintf(dsa_hostkey, sizeof(dsa_hostkey), "%s/sshd/ssh_host_dsa_key", s->socket_dir); torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0)); #endif /* HAVE_DSA */ snprintf(rsa_hostkey, sizeof(rsa_hostkey), "%s/sshd/ssh_host_rsa_key", s->socket_dir); torture_write_file(rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); snprintf(ecdsa_hostkey, sizeof(ecdsa_hostkey), "%s/sshd/ssh_host_ecdsa_key", s->socket_dir); torture_write_file(ecdsa_hostkey, torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); sftp_server = getenv("TORTURE_SFTP_SERVER"); if (sftp_server == NULL) { for (i = 0; i < sftp_sl_size; i++) { sftp_server = sftp_server_locations[i]; rc = lstat(sftp_server, &sb); if (rc == 0) { break; } } } assert_non_null(sftp_server); /* Create default server state */ ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st)); assert_non_null(ss); ss->address = strdup("127.0.0.10"); assert_non_null(ss->address); ss->port = 22; ss->ecdsa_key = strdup(ecdsa_hostkey); assert_non_null(ss->ecdsa_key); #ifdef HAVE_DSA ss->dsa_key = strdup(dsa_hostkey); assert_non_null(ss->dsa_key); #endif /* HAVE_DSA */ ss->ed25519_key = strdup(ed25519_hostkey); assert_non_null(ed25519_hostkey); ss->rsa_key = strdup(rsa_hostkey); assert_non_null(ss->rsa_key); ss->host_key = NULL; /* Use default username and password (set in default_handle_session_cb) */ ss->expected_username = NULL; ss->expected_password = NULL; ss->verbosity = torture_libssh_verbosity(); ss->auth_methods = SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY; #ifdef WITH_PCAP ss->with_pcap = 1; ss->pcap_file = strdup(s->pcap_file); assert_non_null(ss->pcap_file); #endif /* TODO make configurable */ ss->max_tries = 3; ss->error = 0; /* Use the default session handling function */ ss->handle_session = default_handle_session_cb; assert_non_null(ss->handle_session); /* Do not use global configuration */ ss->parse_global_config = false; /* Start the server using the default values */ pid = fork_run_server(ss); if (pid < 0) { fail(); } snprintf(pid_str, sizeof(pid_str), "%d", pid); torture_write_file(s->srv_pidfile, (const char *)pid_str); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1); unsetenv("PAM_WRAPPER"); /* Wait until the sshd is ready to accept connections */ //rc = torture_wait_for_daemon(5); //assert_int_equal(rc, 0); /* TODO properly wait for the server (use ping approach) */ /* Wait 200ms */ usleep(200 * 1000); tss->state = s; tss->ss = ss; *state = tss; return 0; } static int teardown_default_server(void **state) { struct torture_state *s; struct server_state_st *ss; struct test_server_st *tss; tss = *state; assert_non_null(tss); s = tss->state; assert_non_null(s); ss = tss->ss; assert_non_null(ss); /* This function can be reused */ torture_teardown_sshd_server((void **)&s); free_server_state(tss->ss); SAFE_FREE(tss->ss); SAFE_FREE(tss); return 0; } static int session_setup(void **state) { struct test_server_st *tss = *state; struct torture_state *s; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; char *cwd = NULL; char *tmp_dir = NULL; bool b = false; int rc; assert_non_null(tss); /* Make sure we do not test the agent */ unsetenv("SSH_AUTH_SOCK"); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); tss->cwd = cwd; tss->temp_dir = tmp_dir; s = tss->state; assert_non_null(s); pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct test_server_st *tss = *state; struct torture_state *s; int rc = 0; assert_non_null(tss); s = tss->state; assert_non_null(s); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); rc = torture_change_dir(tss->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(tss->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(tss->temp_dir); SAFE_FREE(tss->cwd); return 0; } static void torture_server_auth_none(void **state) { struct test_server_st *tss = *state; struct torture_state *s = NULL; ssh_session session = NULL; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session, NULL); assert_int_equal(rc, SSH_AUTH_DENIED); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } } static void torture_server_auth_password(void **state) { struct test_server_st *tss = *state; struct torture_state *s; ssh_session session; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); /* TODO: implement proper pam authentication in callback */ /* Using the default user for the server */ rc = ssh_options_set(session, SSH_OPTIONS_USER, SSHD_DEFAULT_USER); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session, NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_AUTH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PASSWORD); /* TODO: implement proper pam authentication in callback */ /* Using the default password for the server */ rc = ssh_userauth_password(session, NULL, SSHD_DEFAULT_PASSWORD); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_server_auth_pubkey(void **state) { struct test_server_st *tss = *state; struct torture_state *s; ssh_session session; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); /* Authenticate as alice with bob's pubkey */ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); } static void torture_server_hostkey_mismatch(void **state) { struct test_server_st *tss = *state; struct torture_state *s = NULL; ssh_session session = NULL; char known_hosts_file[1024] = {0}; FILE *file = NULL; enum ssh_known_hosts_e found; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); /* Store the testkey in the knownhosts file */ snprintf(known_hosts_file, sizeof(known_hosts_file), "%s/%s", s->socket_dir, TORTURE_KNOWN_HOSTS_FILE); file = fopen(known_hosts_file, "w"); assert_non_null(file); fprintf(file, "127.0.0.10 %s\n", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); fclose(file); rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, known_hosts_file); assert_ssh_return_code(session, rc); /* Using the default user for the server */ rc = ssh_options_set(session, SSH_OPTIONS_USER, SSHD_DEFAULT_USER); assert_ssh_return_code(session, rc); /* Configure the client to offer only rsa-sha2-256 hostkey algorithm */ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "rsa-sha2-256"); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); /* Make sure we can verify the signature */ found = ssh_session_is_known_server(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); } static void torture_server_unknown_global_request(void **state) { struct test_server_st *tss = *state; struct torture_state *s = NULL; ssh_session session = NULL; ssh_channel channel; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); rc = ssh_options_set(session, SSH_OPTIONS_USER, SSHD_DEFAULT_USER); assert_int_equal(rc, SSH_OK); rc = ssh_connect(session); assert_int_equal(rc, SSH_OK); /* Using the default password for the server */ rc = ssh_userauth_password(session, NULL, SSHD_DEFAULT_PASSWORD); assert_int_equal(rc, SSH_AUTH_SUCCESS); /* Request asking for reply */ rc = ssh_global_request(session, "unknown-request-00@test.com", NULL, 1); assert_ssh_return_code_equal(session, rc, SSH_ERROR); /* Request and don't ask for reply */ rc = ssh_global_request(session, "another-bad-req-00@test.com", NULL, 0); assert_ssh_return_code(session, rc); /* Open channel to make sure the session is still working */ channel = ssh_channel_new(session); assert_non_null(channel); rc = ssh_channel_open_session(channel); assert_ssh_return_code(session, rc); ssh_channel_close(channel); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_server_auth_none, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_server_auth_password, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_server_auth_pubkey, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_server_hostkey_mismatch, session_setup, session_teardown), cmocka_unit_test_setup_teardown(torture_server_unknown_global_request, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, setup_default_server, teardown_default_server); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/server/torture_server_auth_kbdint.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include #include #include #include #include "torture.h" #include "torture_key.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include #include #include #include "test_server.h" #include "default_cb.h" #define TORTURE_KNOWN_HOSTS_FILE "libssh_torture_knownhosts" enum { SUCCESS, MORE, FAILED }; struct test_server_st { struct torture_state *state; struct server_state_st *ss; }; #ifdef WITH_PCAP static void set_pcap(struct session_data_st *sdata, ssh_session session, char *pcap_file) { int rc = 0; if (sdata == NULL) { return; } if (pcap_file == NULL) { return; } sdata->pcap = ssh_pcap_file_new(); if (sdata->pcap == NULL) { return; } rc = ssh_pcap_file_open(sdata->pcap, pcap_file); if (rc == SSH_ERROR) { fprintf(stderr, "Error opening pcap file\n"); ssh_pcap_file_free(sdata->pcap); sdata->pcap = NULL; return; } ssh_set_pcap_file(session, sdata->pcap); } static void cleanup_pcap(struct session_data_st *sdata) { if (sdata == NULL) { return; } if (sdata->pcap == NULL) { return; } /* Do not free the pcap data context here since its ownership was * transfered to the session object, which will take care of its cleanup. * Morover it is still in use so we can very simply crash by freeing * it here. */ sdata->pcap = NULL; } #endif static int process_stdout(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write(channel, buf, n); } } return n; } static int process_stderr(socket_t fd, int revents, void *userdata) { char buf[BUF_SIZE]; int n = -1; ssh_channel channel = (ssh_channel) userdata; if (channel != NULL && (revents & POLLIN) != 0) { n = read(fd, buf, BUF_SIZE); if (n > 0) { ssh_channel_write_stderr(channel, buf, n); } } return n; } static int authenticate_kbdint(ssh_session session, ssh_message message, void *userdata) { int rc = 0; int count; int *step = NULL; size_t expected_len; const char instruction[] = "Type the requested data"; const char name[] = "Keyboard-Interactive Authentication\n"; char initial_echo[] = {1, 0}; char retype_echo[] = {0}; const char *initial_prompt[2]; const char *retype_prompt[1]; int cmp; const char *answer; struct session_data_st *sdata = (struct session_data_st *)userdata; initial_prompt[0] = "username: "; initial_prompt[1] = "password: "; /* Prompt for aditional prompts */ retype_prompt[0] = "retype password: "; if ((session == NULL) || (message == NULL) || (sdata == NULL)) { fprintf(stderr, "Null argument provided\n"); goto failed; } if (sdata->extra_data == NULL) { goto failed; } step = (int *)sdata->extra_data; switch (*step) { case 0: ssh_message_auth_interactive_request(message, name, instruction, 2, initial_prompt, initial_echo); rc = MORE; goto end; case 1: count = ssh_userauth_kbdint_getnanswers(session); if (count != 2) { goto failed; } if ((sdata->username == NULL) || (sdata->password == NULL)) { goto failed; } /* Get and compare username */ expected_len = strlen(sdata->username); if (expected_len <= 0) { goto failed; } answer = ssh_userauth_kbdint_getanswer(session, 0); if (answer == NULL) { goto failed; } cmp = strncmp(answer, sdata->username, expected_len); if (cmp != 0) { goto failed; } /* Get and compare password */ expected_len = strlen(sdata->password); if (expected_len <= 0) { goto failed; } answer = ssh_userauth_kbdint_getanswer(session, 1); if (answer == NULL) { goto failed; } cmp = strncmp(answer, sdata->password, expected_len); if (cmp != 0) { goto failed; } /* Username and password matched. Ask for a retype. */ ssh_message_auth_interactive_request(message, name, instruction, 1, retype_prompt, retype_echo); rc = MORE; goto end; case 2: /* Get and compare password */ expected_len = strlen(sdata->password); if (expected_len <= 0) { goto failed; } answer = ssh_userauth_kbdint_getanswer(session, 0); if (answer == NULL) { goto failed; } cmp = strncmp(answer, sdata->password, expected_len); if (cmp != 0) { goto failed; } /* Password was correct, authenticated */ rc = SUCCESS; goto end; default: goto failed; } failed: if (step != NULL) { *step = 0; } return FAILED; end: if (step != NULL) { (*step)++; } return rc; } static int authenticate_callback(ssh_session session, ssh_message message, void *userdata) { struct session_data_st *sdata = (struct session_data_st *)userdata; int rc; if (sdata == NULL) { fprintf(stderr, "Null userdata\n"); goto denied; } if (sdata->extra_data == NULL) { sdata->extra_data = (void *)calloc(1, sizeof(int)); } switch (ssh_message_type(message)) { case SSH_REQUEST_AUTH: switch (ssh_message_subtype(message)) { case SSH_AUTH_METHOD_INTERACTIVE: rc = authenticate_kbdint(session, message, (void *)sdata); if (rc == SUCCESS) { goto accept; } else if (rc == MORE) { goto more; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_INTERACTIVE); goto denied; default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_INTERACTIVE); goto denied; } default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_INTERACTIVE); goto denied; } ssh_message_free(message); accept: if (sdata) { if (sdata->extra_data) { free(sdata->extra_data); sdata->extra_data = NULL; } } ssh_message_auth_reply_success (message, 0); more: return 0; denied: if (sdata) { if (sdata->extra_data) { free(sdata->extra_data); sdata->extra_data = NULL; } } return 1; } static void handle_kbdint_session_cb(ssh_event event, ssh_session session, struct server_state_st *state) { int n; int rc = 0; /* Structure for storing the pty size. */ struct winsize wsize = { .ws_row = 0, .ws_col = 0, .ws_xpixel = 0, .ws_ypixel = 0 }; /* Our struct holding information about the channel. */ struct channel_data_st cdata = { .pid = 0, .pty_master = -1, .pty_slave = -1, .child_stdin = -1, .child_stdout = -1, .child_stderr = -1, .event = NULL, .winsize = &wsize }; /* Our struct holding information about the session. */ struct session_data_st sdata = { .channel = NULL, .auth_attempts = 0, .authenticated = 0, .username = TORTURE_SSH_USER_BOB, .password = TORTURE_SSH_USER_BOB_PASSWORD }; struct ssh_channel_callbacks_struct *channel_cb = NULL; struct ssh_server_callbacks_struct *server_cb = NULL; if (state == NULL) { fprintf(stderr, "NULL server state provided\n"); goto end; } server_cb = get_default_server_cb(); if (server_cb == NULL) { goto end; } server_cb->userdata = &sdata; /* This is a macro, it does not return a value */ ssh_callbacks_init(server_cb); rc = ssh_set_server_callbacks(session, server_cb); if (rc) { goto end; } #ifdef WITH_PCAP set_pcap(&sdata, session, state->pcap_file); #endif rc = ssh_handle_key_exchange(session); if (rc != SSH_OK) { fprintf(stderr, "%s\n", ssh_get_error(session)); goto end; } /* Set the supported authentication methods */ ssh_set_auth_methods(session, SSH_AUTH_METHOD_INTERACTIVE); ssh_set_message_callback(session, authenticate_callback, &sdata); rc = ssh_event_add_session(event, session); if (rc != 0) { fprintf(stderr, "Error adding session to event\n"); goto end; } n = 0; while (sdata.authenticated == 0 || sdata.channel == NULL) { /* If the user has used up all attempts, or if he hasn't been able to * authenticate in 10 seconds (n * 100ms), disconnect. */ if (sdata.auth_attempts >= state->max_tries || n >= 100) { goto end; } if (ssh_event_dopoll(event, 100) == SSH_ERROR) { fprintf(stderr, "do_poll error: %s\n", ssh_get_error(session)); goto end; } n++; } channel_cb = get_default_channel_cb(); if (channel_cb == NULL) { goto end; } channel_cb->userdata = &cdata; ssh_callbacks_init(channel_cb); rc = ssh_set_channel_callbacks(sdata.channel, channel_cb); if (rc != 0) { goto end; } do { /* Poll the main event which takes care of the session, the channel and * even our child process's stdout/stderr (once it's started). */ rc = ssh_event_dopoll(event, -1); if (rc == SSH_ERROR) { ssh_channel_close(sdata.channel); } /* If child process's stdout/stderr has been registered with the event, * or the child process hasn't started yet, continue. */ if (cdata.event != NULL || cdata.pid == 0) { continue; } /* Executed only once, once the child process starts. */ cdata.event = event; /* If stdout valid, add stdout to be monitored by the poll event. */ if (cdata.child_stdout != -1) { if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stdout to poll context\n"); ssh_channel_close(sdata.channel); } } /* If stderr valid, add stderr to be monitored by the poll event. */ if (cdata.child_stderr != -1){ if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stderr to poll context\n"); ssh_channel_close(sdata.channel); } } } while(ssh_channel_is_open(sdata.channel) && (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0)); close(cdata.pty_master); close(cdata.child_stdin); close(cdata.child_stdout); close(cdata.child_stderr); /* Remove the descriptors from the polling context, since they are now * closed, they will always trigger during the poll calls. */ ssh_event_remove_fd(event, cdata.child_stdout); ssh_event_remove_fd(event, cdata.child_stderr); /* If the child process exited. */ if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) { rc = WEXITSTATUS(rc); ssh_channel_request_send_exit_status(sdata.channel, rc); /* If client terminated the channel or the process did not exit nicely, * but only if something has been forked. */ } else if (cdata.pid > 0) { kill(cdata.pid, SIGKILL); } ssh_channel_send_eof(sdata.channel); ssh_channel_close(sdata.channel); /* Wait up to 5 seconds for the client to terminate the session. */ for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) { ssh_event_dopoll(event, 100); } end: #ifdef WITH_PCAP cleanup_pcap(&sdata); #endif if (channel_cb != NULL) { free(channel_cb); } if (server_cb != NULL) { free(server_cb); } return; } static int setup_kbdint_server(void **state) { struct torture_state *s; struct server_state_st *ss; struct test_server_st *tss; char rsa_hostkey[1024] = {0}; char sshd_path[1024]; int rc; char pid_str[1024]; pid_t pid; assert_non_null(state); tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st)); assert_non_null(tss); torture_setup_socket_dir((void **)&s); assert_non_null(s->socket_dir); /* Set the default interface for the server */ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); setenv("PAM_WRAPPER", "1", 1); snprintf(sshd_path, sizeof(sshd_path), "%s/sshd", s->socket_dir); rc = mkdir(sshd_path, 0755); assert_return_code(rc, errno); snprintf(rsa_hostkey, sizeof(rsa_hostkey), "%s/sshd/ssh_host_rsa_key", s->socket_dir); torture_write_file(rsa_hostkey, torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0)); /* Create the server state */ ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st)); assert_non_null(ss); ss->address = strdup("127.0.0.10"); assert_non_null(ss->address); ss->port = 22; ss->host_key = strdup(rsa_hostkey); assert_non_null(rsa_hostkey); ss->verbosity = torture_libssh_verbosity(); #ifdef WITH_PCAP ss->with_pcap = 1; ss->pcap_file = strdup(s->pcap_file); assert_non_null(ss->pcap_file); #endif ss->max_tries = 3; ss->error = 0; /* Set the session handling function */ ss->handle_session = handle_kbdint_session_cb; assert_non_null(ss->handle_session); /* Start the server */ pid = fork_run_server(ss); if (pid < 0) { fail(); } snprintf(pid_str, sizeof(pid_str), "%d", pid); torture_write_file(s->srv_pidfile, (const char *)pid_str); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1); unsetenv("PAM_WRAPPER"); /* Wait 200ms */ usleep(200 * 1000); tss->state = s; tss->ss = ss; *state = tss; return 0; } static int teardown_kbdint_server(void **state) { struct torture_state *s; struct server_state_st *ss; struct test_server_st *tss; tss = *state; assert_non_null(tss); s = tss->state; assert_non_null(s); ss = tss->ss; assert_non_null(ss); /* This function can be reused */ torture_teardown_sshd_server((void **)&s); free_server_state(tss->ss); SAFE_FREE(tss->ss); SAFE_FREE(tss); return 0; } static int session_setup(void **state) { struct test_server_st *tss = *state; struct torture_state *s; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool b = false; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct test_server_st *tss = *state; struct torture_state *s; assert_non_null(tss); s = tss->state; assert_non_null(s); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static void torture_server_auth_kbdint(void **state) { struct test_server_st *tss = *state; struct torture_state *s; ssh_session session; int rc; assert_non_null(tss); s = tss->state; assert_non_null(s); session = s->ssh.session; assert_non_null(session); rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE); rc = ssh_userauth_kbdint(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 2); /* Reply the first 2 prompts using the username and password */ rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB); assert_false(rc < 0); rc = ssh_userauth_kbdint_setanswer(session, 1, TORTURE_SSH_USER_BOB_PASSWORD); assert_false(rc < 0); /* Resend the password */ rc = ssh_userauth_kbdint(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_INFO); assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1); rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD); assert_false(rc < 0); rc = ssh_userauth_kbdint(session, NULL, NULL); /* Sometimes, SSH server send an empty query at the end of exchange */ if(rc == SSH_AUTH_INFO) { assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0); rc = ssh_userauth_kbdint(session, NULL, NULL); } assert_int_equal(rc, SSH_AUTH_SUCCESS); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_server_auth_kbdint, session_setup, session_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, setup_kbdint_server, teardown_kbdint_server); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/server/torture_server_config.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include #include #include #include #include "torture.h" #include "torture_key.h" #include "libssh/libssh.h" #include "libssh/priv.h" #include "libssh/session.h" #include "libssh/token.h" #include "test_server.h" #include "default_cb.h" const char template[] = "temp_dir_XXXXXX"; struct test_server_st { struct torture_state *state; struct server_state_st *ss; char *cwd; char *temp_dir; char ed25519_hostkey[1024]; char rsa_hostkey[1024]; char ecdsa_521_hostkey[1024]; char ecdsa_384_hostkey[1024]; char ecdsa_256_hostkey[1024]; #ifdef HAVE_DSA char dsa_hostkey[1024]; #endif /* HAVE_DSA */ }; static int setup_files(void **state) { struct test_server_st *tss; struct torture_state *s; char sshd_path[1024]; int rc; tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st)); assert_non_null(tss); torture_setup_socket_dir((void **)&s); assert_non_null(s->socket_dir); /* Set the default interface for the server */ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); setenv("PAM_WRAPPER", "1", 1); snprintf(sshd_path, sizeof(sshd_path), "%s/sshd", s->socket_dir); rc = mkdir(sshd_path, 0755); assert_return_code(rc, errno); snprintf(tss->rsa_hostkey, sizeof(tss->rsa_hostkey), "%s/sshd/ssh_host_rsa_key", s->socket_dir); torture_write_file(tss->rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); snprintf(tss->ecdsa_521_hostkey, sizeof(tss->ecdsa_521_hostkey), "%s/sshd/ssh_host_ecdsa_521_key", s->socket_dir); torture_write_file(tss->ecdsa_521_hostkey, torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); snprintf(tss->ecdsa_384_hostkey, sizeof(tss->ecdsa_384_hostkey), "%s/sshd/ssh_host_ecdsa_384_key", s->socket_dir); torture_write_file(tss->ecdsa_384_hostkey, torture_get_testkey(SSH_KEYTYPE_ECDSA_P384, 0)); snprintf(tss->ecdsa_256_hostkey, sizeof(tss->ecdsa_256_hostkey), "%s/sshd/ssh_host_ecdsa_256_key", s->socket_dir); torture_write_file(tss->ecdsa_256_hostkey, torture_get_testkey(SSH_KEYTYPE_ECDSA_P256, 0)); if (!ssh_fips_mode()) { snprintf(tss->ed25519_hostkey, sizeof(tss->ed25519_hostkey), "%s/sshd/ssh_host_ed25519_key", s->socket_dir); torture_write_file(tss->ed25519_hostkey, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); #ifdef HAVE_DSA snprintf(tss->dsa_hostkey, sizeof(tss->dsa_hostkey), "%s/sshd/ssh_host_dsa_key", s->socket_dir); torture_write_file(tss->dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0)); #endif /* HAVE_DSA */ } tss->state = s; *state = tss; return 0; } static int teardown_files(void **state) { struct torture_state *s; struct test_server_st *tss; tss = *state; assert_non_null(tss); s = tss->state; assert_non_null(s); torture_teardown_socket_dir((void **)&s); SAFE_FREE(tss); return 0; } static int setup_temp_dir(void **state) { struct test_server_st *tss = *state; struct torture_state *s; char *cwd = NULL; char *tmp_dir = NULL; assert_non_null(tss); s = tss->state; assert_non_null(s); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); tss->cwd = cwd; tss->temp_dir = tmp_dir; return 0; } static int teardown_temp_dir(void **state) { struct test_server_st *tss = *state; int rc; assert_non_null(tss); rc = torture_change_dir(tss->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(tss->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(tss->temp_dir); SAFE_FREE(tss->cwd); return 0; } static struct server_state_st *setup_server_state(char *config_file, bool parse_global) { struct server_state_st *ss = NULL; assert_non_null(config_file); /* Create default server state */ ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st)); assert_non_null(ss); ss->address = strdup("127.0.0.10"); assert_non_null(ss->address); ss->port = 22; ss->host_key = NULL; /* Use default username and password (set in default_handle_session_cb) */ ss->expected_username = NULL; ss->expected_password = NULL; ss->verbosity = torture_libssh_verbosity(); ss->auth_methods = SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY; /* TODO make configurable */ ss->max_tries = 3; ss->error = 0; /* Use the default session handling function */ ss->handle_session = default_handle_session_cb; assert_non_null(ss->handle_session); /* Set if should parse global configuration before */ ss->parse_global_config = parse_global; /* Set the config file to be used */ ss->config_file = strdup(config_file); assert_non_null(ss->config_file); return ss; } static int start_server(void **state) { struct test_server_st *tss = *state; struct torture_state *s; struct server_state_st *ss; char pid_str[1024]; pid_t pid; assert_non_null(tss); s = tss->state; assert_non_null(s); ss = tss->ss; assert_non_null(ss); /* Start the server using the default values */ pid = fork_run_server(ss); if (pid < 0) { fail(); } snprintf(pid_str, sizeof(pid_str), "%d", pid); torture_write_file(s->srv_pidfile, (const char *)pid_str); /* TODO properly wait for the server (use ping approach) */ /* Wait 200ms */ usleep(200 * 1000); return 0; } static int stop_server(void **state) { struct torture_state *s; struct test_server_st *tss; int rc; tss = *state; assert_non_null(tss); s = tss->state; assert_non_null(s); rc = torture_terminate_process(s->srv_pidfile); if (rc != 0) { fprintf(stderr, "XXXXXX Failed to terminate sshd\n"); } unlink(s->srv_pidfile); return 0; } static int session_setup(void **state) { struct test_server_st *tss = *state; struct torture_state *s; int verbosity = torture_libssh_verbosity(); struct passwd *pwd; bool b = false; int rc; assert_non_null(tss); /* Make sure we do not test the agent */ unsetenv("SSH_AUTH_SOCK"); s = tss->state; assert_non_null(s); pwd = getpwnam("bob"); assert_non_null(pwd); rc = setuid(pwd->pw_uid); assert_return_code(rc, errno); s->ssh.session = ssh_new(); assert_non_null(s->ssh.session); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); assert_ssh_return_code(s->ssh.session, rc); rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER); assert_ssh_return_code(s->ssh.session, rc); /* Make sure no other configuration options from system will get used */ rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b); assert_ssh_return_code(s->ssh.session, rc); return 0; } static int session_teardown(void **state) { struct test_server_st *tss = *state; struct torture_state *s; assert_non_null(tss); s = tss->state; assert_non_null(s); ssh_disconnect(s->ssh.session); ssh_free(s->ssh.session); return 0; } static int try_config_content(void **state, const char *config_content, bool parse_global) { struct test_server_st *tss = *state; struct server_state_st *ss; struct torture_state *s; char config_file[1024]; int rc; ssh_session session; assert_non_null(tss); s = tss->state; assert_non_null(s); /* Prepare the config file to test */ snprintf(config_file, sizeof(config_file), "%s/config_file", tss->temp_dir); if (parse_global) { fprintf(stderr, "Using system-wide configuration\n"); } fprintf(stderr, "Trying content: \n\n%s\n", config_content); torture_write_file(config_file, config_content); ss = setup_server_state(config_file, parse_global); assert_non_null(ss); tss->ss = ss; rc = start_server(state); assert_int_equal(rc, 0); rc = session_setup(state); assert_int_equal(rc, 0); session = s->ssh.session; assert_non_null(session); /* Authenticate as alice with bob */ rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE); assert_ssh_return_code(session, rc); rc = ssh_connect(session); assert_ssh_return_code(session, rc); rc = ssh_userauth_none(session,NULL); /* This request should return a SSH_REQUEST_DENIED error */ if (rc == SSH_ERROR) { assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED); } rc = ssh_userauth_list(session, NULL); assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY); rc = ssh_userauth_publickey_auto(session, NULL, NULL); assert_int_equal(rc, SSH_AUTH_SUCCESS); rc = session_teardown(state); assert_int_equal(rc, 0); rc = stop_server(state); assert_int_equal(rc, 0); free_server_state(tss->ss); SAFE_FREE(tss->ss); unlink(config_file); return 0; } static char *hostkey_files[6] = {0}; static size_t setup_hostkey_files(struct test_server_st *tss) { size_t num_hostkey_files = 1; hostkey_files[0] = tss->rsa_hostkey; #ifdef TEST_ALL_CRYPTO_COMBINATIONS hostkey_files[1] = tss->ecdsa_256_hostkey; hostkey_files[2] = tss->ecdsa_384_hostkey; hostkey_files[3] = tss->ecdsa_521_hostkey; num_hostkey_files = 4; if (!ssh_fips_mode()) { hostkey_files[4] = tss->ed25519_hostkey; num_hostkey_files++; #ifdef HAVE_DSA hostkey_files[5] = tss->dsa_hostkey; num_hostkey_files++; #endif } #endif /* TEST_ALL_CRYPTO_COMBINATIONS */ return num_hostkey_files; } static void torture_server_config_hostkey(void **state) { struct test_server_st *tss = *state; size_t i, num_hostkey_files; char config_content[4096]; int rc; assert_non_null(tss); num_hostkey_files = setup_hostkey_files(tss); for (i = 0; i < num_hostkey_files; i++) { snprintf(config_content, sizeof(config_content), "HostKey %s\n", hostkey_files[i]); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); } } static void torture_server_config_ciphers(void **state) { struct test_server_st *tss = *state; size_t i, j, num_hostkey_files = 1; char config_content[4096]; const char *ciphers; struct ssh_tokens_st *tokens; int rc; assert_non_null(tss); num_hostkey_files = setup_hostkey_files(tss); if (ssh_fips_mode()) { ciphers = ssh_kex_get_fips_methods(SSH_CRYPT_S_C); assert_non_null(ciphers); } else { ciphers = ssh_kex_get_default_methods(SSH_CRYPT_S_C); assert_non_null(ciphers); } tokens = ssh_tokenize(ciphers, ','); assert_non_null(tokens); for (i = 0; i < num_hostkey_files; i++) { /* Try setting all default algorithms */ snprintf(config_content, sizeof(config_content), "HostKey %s\nCiphers %s\n", hostkey_files[i], ciphers); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* Try each algorithm individually */ j = 0; while(tokens->tokens[j] != NULL) { snprintf(config_content, sizeof(config_content), "HostKey %s\nCiphers %s\n", hostkey_files[i], tokens->tokens[j]); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); j++; } } ssh_tokens_free(tokens); } static void torture_server_config_macs(void **state) { struct test_server_st *tss = *state; size_t i, j, num_hostkey_files = 1; char config_content[4096]; const char *macs; struct ssh_tokens_st *tokens; int rc; assert_non_null(tss); num_hostkey_files = setup_hostkey_files(tss); if (ssh_fips_mode()) { macs = ssh_kex_get_fips_methods(SSH_MAC_S_C); assert_non_null(macs); } else { macs = ssh_kex_get_default_methods(SSH_MAC_S_C); assert_non_null(macs); } tokens = ssh_tokenize(macs, ','); assert_non_null(tokens); for (i = 0; i < num_hostkey_files; i++) { /* Try setting all default algorithms */ snprintf(config_content, sizeof(config_content), "HostKey %s\nMACs %s\n", hostkey_files[i], macs); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* Try each algorithm individually */ j = 0; while(tokens->tokens[j] != NULL) { snprintf(config_content, sizeof(config_content), "HostKey %s\nMACs %s\n", hostkey_files[i], tokens->tokens[j]); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); j++; } } ssh_tokens_free(tokens); } static void torture_server_config_kex(void **state) { struct test_server_st *tss = *state; size_t i, j, num_hostkey_files = 1; char config_content[4096]; const char *kex; struct ssh_tokens_st *tokens; int rc; assert_non_null(tss); num_hostkey_files = setup_hostkey_files(tss); if (ssh_fips_mode()) { kex = ssh_kex_get_fips_methods(SSH_KEX); assert_non_null(kex); } else { kex = ssh_kex_get_default_methods(SSH_KEX); assert_non_null(kex); } tokens = ssh_tokenize(kex, ','); assert_non_null(tokens); for (i = 0; i < num_hostkey_files; i++) { /* Try setting all default algorithms */ snprintf(config_content, sizeof(config_content), "HostKey %s\nKexAlgorithms %s\n", hostkey_files[i], kex); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* Try each algorithm individually */ j = 0; while(tokens->tokens[j] != NULL) { snprintf(config_content, sizeof(config_content), "HostKey %s\nKexAlgorithms %s\n", hostkey_files[i], tokens->tokens[j]); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); j++; } } ssh_tokens_free(tokens); } static void torture_server_config_hostkey_algorithms(void **state) { struct test_server_st *tss = *state; size_t i, num_hostkey_files = 5; char config_content[4096]; const char *allowed; int rc; assert_non_null(tss); num_hostkey_files = setup_hostkey_files(tss); if (ssh_fips_mode()) { allowed = ssh_kex_get_fips_methods(SSH_HOSTKEYS); assert_non_null(allowed); } else { allowed = ssh_kex_get_default_methods(SSH_HOSTKEYS); assert_non_null(allowed); } for (i = 0; i < num_hostkey_files; i++) { /* Should work with all allowed */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostKeyAlgorithms %s\n", hostkey_files[i], allowed); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); } /* Should work with matching hostkey and allowed algorithm */ if (!ssh_fips_mode()) { /* ed25519 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->ed25519_hostkey, "ssh-ed25519"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* ssh-rsa */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->rsa_hostkey, "ssh-rsa"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); } /* rsa-sha2-256 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->rsa_hostkey, "rsa-sha2-256"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* ssh-sha2-512 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->rsa_hostkey, "rsa-sha2-512"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* ecdsa-sha2-nistp256 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->ecdsa_256_hostkey, "ecdsa-sha2-nistp256"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* ecdsa-sha2-nistp384 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->ecdsa_384_hostkey, "ecdsa-sha2-nistp384"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); /* ecdsa-sha2-nistp521 */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->ecdsa_521_hostkey, "ecdsa-sha2-nistp521"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); #ifdef HAVE_DSA if (!ssh_fips_mode()) { /* ssh-dss */ snprintf(config_content, sizeof(config_content), "HostKey %s\nHostkeyAlgorithms %s\n", tss->dsa_hostkey, "ssh-dss"); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); } #endif } static void torture_server_config_unknown(void **state) { struct test_server_st *tss = *state; char config_content[4096]; int rc; assert_non_null(tss); assert_non_null(tss->rsa_hostkey); snprintf(config_content, sizeof(config_content), "HostKey %s\nUnknownOption unknown-value1,unknown-value2\n", tss->rsa_hostkey); rc = try_config_content(state, config_content, false); assert_int_equal(rc, 0); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_server_config_hostkey, setup_temp_dir, teardown_temp_dir), cmocka_unit_test_setup_teardown(torture_server_config_ciphers, setup_temp_dir, teardown_temp_dir), cmocka_unit_test_setup_teardown(torture_server_config_macs, setup_temp_dir, teardown_temp_dir), cmocka_unit_test_setup_teardown(torture_server_config_kex, setup_temp_dir, teardown_temp_dir), cmocka_unit_test_setup_teardown(torture_server_config_hostkey_algorithms, setup_temp_dir, teardown_temp_dir), cmocka_unit_test_setup_teardown(torture_server_config_unknown, setup_temp_dir, teardown_temp_dir), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, setup_files, teardown_files); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/sftp_stress/main.c ================================================ /* * main.c * * Created on: 22 juin 2009 * Author: aris */ #include #include #include #include #include #include #include #include #define TEST_READ 1 #define TEST_WRITE 2 #define NTHREADS 3 #define FILESIZE 100000 unsigned char samplefile[FILESIZE]; volatile int stop=0; const char* hosts[]={"localhost","barebone"}; void signal_stop(){ stop=1; printf("Stopping...\n"); } SSH_SESSION *connect_host(const char *hostname); int sftp_test(SSH_SESSION *session, int test); int docycle(const char *host, int test){ SSH_SESSION *session=connect_host(host); int ret=SSH_ERROR; if(!session){ printf("connect failed\n"); } else { printf("Connected\n"); ret=sftp_test(session,test); if(ret != SSH_OK){ printf("Error in sftp\n"); } ssh_disconnect(session); } return ret; } int thread(){ while(docycle(hosts[rand()%2],TEST_WRITE) == SSH_OK) if(stop) break; return 0; } int main(int argc, char **argv){ int i; pthread_t threads[NTHREADS]; ssh_init(); srand(time(NULL)); for(i=0;i This file is part of the SSH Library You are free to copy this file, modify it in any way, consider it being public domain. This does not apply to the rest of the library though, but it is allowed to cut-and-paste working code from this file to any license of program. The goal is to show the API in action. It's not a reference on how terminal clients must be made or how a client should react. */ #include #include #include int main(int argc, char **argv) { const char *banner = NULL; ssh_session session = NULL; int rc = 1; if (argc < 1 || argv[1] == NULL) { fprintf(stderr, "Error: Need an argument (hostname)\n"); goto out; } session = ssh_new(); if (session == NULL) { goto out; } rc = ssh_options_set(session, SSH_OPTIONS_HOST, argv[1]); if (rc < 0) { goto out; } /* The automatic username is not available under uid wrapper */ rc = ssh_options_set(session, SSH_OPTIONS_USER, "ping"); if (rc < 0) { goto out; } rc = ssh_connect(session); if (rc != SSH_OK) { fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session)); goto out; } banner = ssh_get_serverbanner(session); if (banner == NULL) { fprintf(stderr, "Did not receive SSH banner\n"); goto out; } printf("OK: %s\n", banner); rc = 0; out: ssh_free(session); return rc; } ================================================ FILE: src/libssh/tests/test_exec.c ================================================ /* This file is distributed in public domain. You can do whatever you want with its content. */ #include #include #include #include "tests.h" void do_connect(SSH_SESSION *session) { char buf[4096] = {0}; CHANNEL *channel; int error = ssh_connect(session); if (error != SSH_OK) { fprintf(stderr,"Error at connection: %s\n", ssh_get_error(session)); return; } printf("Connected\n"); ssh_session_is_known_server(session); error = authenticate(session); if(error != SSH_AUTH_SUCCESS) { fprintf(stderr,"Error at authentication: %s\n", ssh_get_error(session)); return; } printf("Authenticated\n"); channel = ssh_channel_new(session); ssh_channel_open_session(channel); printf("Execute 'ls' on the channel\n"); error = ssh_channel_request_exec(channel, "ls"); if(error != SSH_OK){ fprintf(stderr, "Error executing command: %s\n", ssh_get_error(session)); return; } printf("--------------------output----------------------\n"); while (ssh_channel_read(channel, buf, sizeof(buf), 0)) { printf("%s", buf); } printf("\n"); printf("---------------------end------------------------\n"); ssh_channel_send_eof(channel); fprintf(stderr, "Exit status: %d\n", ssh_channel_get_exit_status(channel)); printf("\nChannel test finished\n"); ssh_channel_close(channel); ssh_channel_free(channel); } int main(int argc, char **argv){ SSH_OPTIONS *options=set_opts(argc, argv); SSH_SESSION *session=ssh_new(); if(options==NULL){ return 1; } ssh_set_options(session,options); do_connect(session); ssh_disconnect(session); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/tests/test_pcap.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* Simple test for the pcap functions */ #include #include #include #include #include #include int main(int argc, char **argv){ ssh_pcap_file pcap; ssh_pcap_context ctx; ssh_buffer buffer=ssh_buffer_new(); char *str="Hello, this is a test string to test the capabilities of the" "pcap file writer."; printf("Simple pcap tester\n"); pcap=ssh_pcap_file_new(); if(ssh_pcap_file_open(pcap,"test.cap") != SSH_OK){ printf("error happened\n"); return EXIT_FAILURE; } buffer_add_data(buffer,str,strlen(str)); ctx=ssh_pcap_context_new(NULL); ssh_pcap_context_set_file(ctx,pcap); ssh_pcap_context_write(ctx,SSH_PCAP_DIR_OUT,str,strlen(str),strlen(str)); return EXIT_SUCCESS; } ================================================ FILE: src/libssh/tests/test_socket.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2009 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* Simple test for the socket callbacks */ #include #include #include #include #include #include #include int stop=0; ssh_socket s; static int data_rcv(const void *data, size_t len, void *user){ printf("Received data: '"); fwrite(data,1,len,stdout); printf("'\n"); ssh_socket_write(s,"Hello you !\n",12); ssh_socket_nonblocking_flush(s); return len; } static void controlflow(int code,void *user){ printf("Control flow: %x\n",code); } static void exception(int code, int errno_code,void *user){ printf("Exception: %d (%d)\n",code,errno_code); stop=1; } static void connected(int code, int errno_code,void *user){ if(code == SSH_SOCKET_CONNECTED_OK) printf("Connected: %d (%d)\n",code, errno_code); else { printf("Error while connecting:(%d, %d:%s)\n",code,errno_code,strerror(errno_code)); stop=1; } } struct ssh_socket_callbacks_struct callbacks={ data_rcv, controlflow, exception, connected, NULL }; int main(int argc, char **argv){ ssh_session session; ssh_poll_ctx ctx; int verbosity=SSH_LOG_FUNCTIONS; if(argc < 3){ printf("Usage : %s host port\n", argv[0]); return EXIT_FAILURE; } session=ssh_new(); ssh_options_set(session,SSH_OPTIONS_LOG_VERBOSITY,&verbosity); ssh_init(); s=ssh_socket_new(session); ctx=ssh_poll_ctx_new(2); ssh_socket_set_callbacks(s, &callbacks); ssh_poll_ctx_add_socket(ctx,s); if(ssh_socket_connect(s,argv[1],atoi(argv[2]),NULL) != SSH_OK){ printf("ssh_socket_connect: %s\n",ssh_get_error(session)); return EXIT_FAILURE; } while(!stop) ssh_poll_ctx_dopoll(ctx,-1); printf("finished\n"); return EXIT_SUCCESS; } ================================================ FILE: src/libssh/tests/test_ssh_bind_accept_fd.c ================================================ /* Test the ability to use ssh_bind_accept_fd. * * Expected behavior: Prints "SUCCESS!" * * Faulty behavior observed before change: Connection timeout */ #include #include #include #include #include #include #include #include #include #include #include struct options { const char *server_keyfile; } options; const char HOST[] = "127.0.0.1"; const int PORT = 3333; int get_connection() { int rc, server_socket, client_conn = -1; struct sockaddr_in server_socket_addr; struct sockaddr_storage client_conn_addr; socklen_t client_conn_addr_size = sizeof(client_conn_addr); server_socket = socket(PF_INET, SOCK_STREAM, 0); if (server_socket < 0) { goto out; } server_socket_addr.sin_family = AF_INET; server_socket_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, HOST, &server_socket_addr.sin_addr) != 1) { goto out; } rc = bind(server_socket, (struct sockaddr *)&server_socket_addr, sizeof(server_socket_addr)); if (rc < 0) { goto out; } if (listen(server_socket, 0) < 0) { goto out; } client_conn = accept(server_socket, (struct sockaddr *)&client_conn_addr, &client_conn_addr_size); out: return client_conn; } void ssh_server() { ssh_bind bind; ssh_session session; int client_conn = get_connection(); if (client_conn < 0) { err(1, "get_connection"); } bind = ssh_bind_new(); if (!bind) { errx(1, "ssh_bind_new"); } #ifdef HAVE_DSA /*TODO mbedtls this is probably required */ if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY, options.server_keyfile) != SSH_OK) { errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_DSAKEY"); } #else if (ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, options.server_keyfile) != SSH_OK) { errx(1, "ssh_bind_options_set(SSH_BIND_OPTIONS_RSAKEY"); } #endif session = ssh_new(); if (!session) { errx(1, "ssh_new"); } if (ssh_bind_accept_fd(bind, session, client_conn) != SSH_OK) { errx(1, "ssh_bind_accept: %s", ssh_get_error(bind)); } if (ssh_handle_key_exchange(session) != SSH_OK) { errx(1, "ssh_handle_key_exchange: %s", ssh_get_error(session)); } printf("SUCCESS!\n"); } void ssh_client() { ssh_session session; session = ssh_new(); if (!session) { errx(1, "ssh_new"); } if (ssh_options_set(session, SSH_OPTIONS_HOST, HOST) < 0) { errx(1, "ssh_options_set(SSH_OPTIONS_HOST)"); } if (ssh_options_set(session, SSH_OPTIONS_PORT, &PORT) < 0) { errx(1, "ssh_options_set(SSH_OPTIONS_PORT)"); } if (ssh_connect(session) != SSH_OK) { errx(1, "ssh_connect: %s", ssh_get_error(session)); } } int main(int argc, const char *argv[]) { if (argc != 2) { printf("Usage: %s \n", argv[0]); exit(1); } options.server_keyfile = argv[1]; pid_t pid = fork(); if (pid < 0) { errx(1, "fork"); } if (pid == 0) { /* Allow the server to get set up */ sleep(3); ssh_client(); } else { ssh_server(); } return 0; } ================================================ FILE: src/libssh/tests/test_tunnel.c ================================================ /* This file is distributed in public domain. You can do whatever you want with its content. */ #include #include #include #include "tests.h" #define ECHO_PORT 7 void do_connect(SSH_SESSION *session){ int error=ssh_connect(session); if(error != SSH_OK){ fprintf(stderr,"Error at connection :%s\n",ssh_get_error(session)); return; } printf("Connected\n"); ssh_session_is_known_server(session); // we don't care what happens here error=authenticate(session); if(error != SSH_AUTH_SUCCESS){ fprintf(stderr,"Error at authentication :%s\n",ssh_get_error(session)); return; } printf("Authenticated\n"); CHANNEL *channel=ssh_channel_new(session); error=ssh_channel_open_forward(channel,"localhost",ECHO_PORT,"localhost",42); if(error!=SSH_OK){ fprintf(stderr,"Error when opening forward:%s\n",ssh_get_error(session)); return; } printf("Forward opened\n"); int i=0; char string[20]; char buffer[20]; for(i=0;i<2000;++i){ sprintf(string,"%d\n",i); ssh_channel_write(channel,string,strlen(string)); do { error=ssh_channel_poll(channel,0); //if(error < strlen(string)) //usleep(10); } while(error < strlen(string) && error >= 0); if(error>0){ error=ssh_channel_read_nonblocking(channel,buffer,strlen(string),0); if(error>=0){ if(memcmp(buffer,string,strlen(string))!=0){ fprintf(stderr,"Problem with answer: wanted %s got %s\n",string,buffer); } else { printf("."); fflush(stdout); } } } if(error==-1){ fprintf(stderr,"Channel reading error : %s\n",ssh_get_error(session)); break; } } printf("\nChannel test finished\n"); ssh_channel_close(channel); ssh_channel_free(channel); } int main(int argc, char **argv){ SSH_OPTIONS *options=set_opts(argc, argv); SSH_SESSION *session=ssh_new(); if(options==NULL){ return 1; } ssh_set_options(session,options); do_connect(session); ssh_disconnect(session); ssh_finalize(); return 0; } ================================================ FILE: src/libssh/tests/tests.h ================================================ /* This file is distributed in public domain. You can do whatever you want with its content. */ #include int authenticate (SSH_SESSION *session); SSH_OPTIONS *set_opts(int argc, char **argv); ================================================ FILE: src/libssh/tests/tests_config.h.cmake ================================================ /* OpenSSH capabilities */ #cmakedefine OPENSSH_VERSION_MAJOR ${OPENSSH_VERSION_MAJOR} #cmakedefine OPENSSH_VERSION_MINOR ${OPENSSH_VERSION_MINOR} #cmakedefine OPENSSH_CIPHERS "${OPENSSH_CIPHERS}" #cmakedefine OPENSSH_MACS "${OPENSSH_MACS}" #cmakedefine OPENSSH_KEX "${OPENSSH_KEX}" #cmakedefine OPENSSH_KEYS "${OPENSSH_KEYS}" #cmakedefine OPENSSH_3DES_CBC 1 #cmakedefine OPENSSH_AES128_CBC 1 #cmakedefine OPENSSH_AES192_CBC 1 #cmakedefine OPENSSH_AES256_CBC 1 #cmakedefine OPENSSH_RIJNDAEL_CBC_LYSATOR_LIU_SE 1 #cmakedefine OPENSSH_AES128_CTR 1 #cmakedefine OPENSSH_AES192_CTR 1 #cmakedefine OPENSSH_AES256_CTR 1 #cmakedefine OPENSSH_AES128_GCM_OPENSSH_COM 1 #cmakedefine OPENSSH_AES256_GCM_OPENSSH_COM 1 #cmakedefine OPENSSH_CHACHA20_POLY1305_OPENSSH_COM 1 #cmakedefine OPENSSH_BLOWFISH_CBC 1 #cmakedefine OPENSSH_HMAC_SHA1 1 #cmakedefine OPENSSH_HMAC_SHA1_96 1 #cmakedefine OPENSSH_HMAC_SHA2_256 1 #cmakedefine OPENSSH_HMAC_SHA2_512 1 #cmakedefine OPENSSH_HMAC_MD5 1 #cmakedefine OPENSSH_HMAC_MD5_96 1 #cmakedefine OPENSSH_UMAC_64_OPENSSH_COM 1 #cmakedefine OPENSSH_UMAC_128_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_SHA1_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_SHA1_96_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_SHA2_256_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_SHA2_512_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_MD5_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_HMAC_MD5_96_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_UMAC_64_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_UMAC_128_ETM_OPENSSH_COM 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP1_SHA1 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP14_SHA1 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP14_SHA256 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP16_SHA512 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP18_SHA512 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA1 1 #cmakedefine OPENSSH_DIFFIE_HELLMAN_GROUP_EXCHANGE_SHA256 1 #cmakedefine OPENSSH_ECDH_SHA2_NISTP256 1 #cmakedefine OPENSSH_ECDH_SHA2_NISTP384 1 #cmakedefine OPENSSH_ECDH_SHA2_NISTP521 1 #cmakedefine OPENSSH_CURVE25519_SHA256 1 #cmakedefine OPENSSH_CURVE25519_SHA256_LIBSSH_ORG 1 #cmakedefine OPENSSH_SSH_ED25519 1 #cmakedefine OPENSSH_SSH_ED25519_CERT_V01_OPENSSH_COM 1 #cmakedefine OPENSSH_SSH_RSA 1 #cmakedefine OPENSSH_SSH_DSS 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP256 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP384 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP521 1 #cmakedefine OPENSSH_SSH_RSA_CERT_V01_OPENSSH_COM 1 #cmakedefine OPENSSH_SSH_DSS_CERT_V01_OPENSSH_COM 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP256_CERT_V01_OPENSSH_COM 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP384_CERT_V01_OPENSSH_COM 1 #cmakedefine OPENSSH_ECDSA_SHA2_NISTP521_CERT_V01_OPENSSH_COM 1 /* Available programs */ #cmakedefine NC_EXECUTABLE "${NC_EXECUTABLE}" #cmakedefine SSHD_EXECUTABLE "${SSHD_EXECUTABLE}" #cmakedefine SSH_EXECUTABLE "${SSH_EXECUTABLE}" ================================================ FILE: src/libssh/tests/torture.c ================================================ /* * torture.c - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2008-2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include "tests_config.h" #include #include #include #include #include #include #ifndef _WIN32 # include # include # include #endif #ifdef HAVE_UNISTD_H #include #elif (defined _WIN32) || (defined _WIN64) #include #include #define read _read #define open _open #define write _write #define close _close #define chdir _chdir #endif #include "torture.h" #include "torture_key.h" #include "libssh/misc.h" #define TORTURE_SSHD_SRV_IPV4 "127.0.0.10" /* socket wrapper IPv6 prefix fd00::5357:5fxx */ #define TORTURE_SSHD_SRV_IPV6 "fd00::5357:5f0a" #define TORTURE_SSHD_SRV_PORT 22 #define TORTURE_SOCKET_DIR "/tmp/test_socket_wrapper_XXXXXX" #define TORTURE_SSHD_PIDFILE "sshd/sshd.pid" #define TORTURE_SSHD_CONFIG "sshd/sshd_config" #define TORTURE_PCAP_FILE "socket_trace.pcap" #ifndef PATH_MAX # define PATH_MAX 4096 #endif static const char torture_rsa_certauth_pub[]= "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnA2n5vHzZbs/GvRkGloJNV1CXHI" "S5Xnrm05HusUJSWyPq3I1iCMHdYA7oezHa9GCFYbIenaYPy+G6USQRjYQz8SvAZo06" "SFNeJSsa1kAIqxzdPT9kBrRrYK39PZQPsYVfRPqZBdmc+jwrfz97IFEJyXMI47FoTG" "kgEq7eu3z2px/tdIZ34I5Hr5DDBxicZi4jluyRUJHfSPoBxyhF7OkPX4bYkrc691je" "IQDxubl650WYLHgFfad0xTzBIFE6XUb55Dp5AgRdevSoso1Pe0IKFxxMVpP664LCbY" "K06Lv6kcotfFlpvUtR1yx8jToGcSoq5sSzTwvXSHCQQ9ZA1hvF " "torture_certauth_key"; static int verbosity = 0; static const char *pattern = NULL; #ifndef _WIN32 static int _torture_auth_kbdint(ssh_session session, const char *password) { const char *prompt; char echo; int err; if (session == NULL || password == NULL) { return SSH_AUTH_ERROR; } err = ssh_userauth_kbdint(session, NULL, NULL); if (err == SSH_AUTH_ERROR) { return err; } if (ssh_userauth_kbdint_getnprompts(session) != 1) { return SSH_AUTH_ERROR; } prompt = ssh_userauth_kbdint_getprompt(session, 0, &echo); if (prompt == NULL) { return SSH_AUTH_ERROR; } if (ssh_userauth_kbdint_setanswer(session, 0, password) < 0) { return SSH_AUTH_ERROR; } err = ssh_userauth_kbdint(session, NULL, NULL); if (err == SSH_AUTH_INFO) { if (ssh_userauth_kbdint_getnprompts(session) != 0) { return SSH_AUTH_ERROR; } err = ssh_userauth_kbdint(session, NULL, NULL); } return err; } int torture_rmdirs(const char *path) { DIR *d; struct dirent *dp; struct stat sb; char *fname; if ((d = opendir(path)) != NULL) { while(stat(path, &sb) == 0) { /* if we can remove the directory we're done */ if (rmdir(path) == 0) { break; } switch (errno) { case ENOTEMPTY: case EEXIST: case EBADF: break; /* continue */ default: closedir(d); return 0; } while ((dp = readdir(d)) != NULL) { size_t len; /* skip '.' and '..' */ if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) { continue; } len = strlen(path) + strlen(dp->d_name) + 2; fname = malloc(len); if (fname == NULL) { closedir(d); return -1; } snprintf(fname, len, "%s/%s", path, dp->d_name); /* stat the file */ if (lstat(fname, &sb) != -1) { if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) { if (rmdir(fname) < 0) { /* can't be deleted */ if (errno == EACCES) { closedir(d); SAFE_FREE(fname); return -1; } torture_rmdirs(fname); } } else { unlink(fname); } } /* lstat */ SAFE_FREE(fname); } /* readdir */ rewinddir(d); } } else { return -1; } closedir(d); return 0; } int torture_isdir(const char *path) { struct stat sb; if (lstat (path, &sb) == 0 && S_ISDIR(sb.st_mode)) { return 1; } return 0; } static pid_t torture_read_pidfile(const char *pidfile) { char buf[8] = {0}; long int tmp; pid_t ret; ssize_t rc; int fd; fd = open(pidfile, O_RDONLY); if (fd < 0) { return -1; } rc = read(fd, buf, sizeof(buf)); close(fd); if (rc <= 0) { return -1; } buf[sizeof(buf) - 1] = '\0'; tmp = strtol(buf, NULL, 10); if (tmp == 0 || errno == ERANGE) { return -1; } ret = (pid_t)tmp; /* Check if we are out of pid_t range on this system */ if ((long)ret != tmp) { return -1; } return ret; } int torture_terminate_process(const char *pidfile) { ssize_t rc; pid_t pid; int is_running = 1; int count; /* read the pidfile */ pid = torture_read_pidfile(pidfile); assert_int_not_equal(pid, -1); for (count = 0; count < 10; count++) { /* Make sure the daemon goes away! */ kill(pid, SIGTERM); /* 10 ms */ usleep(10 * 1000); rc = kill(pid, 0); if (rc != 0) { is_running = 0; break; } } if (is_running) { fprintf(stderr, "WARNING: The process with pid %u is still running!\n", pid); } return 0; } ssh_session torture_ssh_session(struct torture_state *s, const char *host, const unsigned int *port, const char *user, const char *password) { ssh_session session; int method; int rc; bool process_config = false; if (host == NULL) { return NULL; } session = ssh_new(); if (session == NULL) { return NULL; } #ifdef WITH_PCAP if (s != NULL && s->plain_pcap != NULL) { ssh_set_pcap_file(session, s->plain_pcap); } #endif /* WITH_PCAP */ if (ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity) < 0) { goto failed; } if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) { goto failed; } if (port != NULL) { if (ssh_options_set(session, SSH_OPTIONS_PORT, port) < 0) { goto failed; } } if (user != NULL) { if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) { goto failed; } } if (ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config) < 0) { goto failed; } if (ssh_connect(session)) { goto failed; } /* We are in testing mode, so consinder the hostkey as verified ;) */ /* This request should return a SSH_REQUEST_DENIED error */ rc = ssh_userauth_none(session, NULL); if (rc == SSH_ERROR) { goto failed; } method = ssh_userauth_list(session, NULL); if (method == 0) { goto failed; } if (password != NULL) { if (method & SSH_AUTH_METHOD_PASSWORD) { rc = ssh_userauth_password(session, NULL, password); } else if (method & SSH_AUTH_METHOD_INTERACTIVE) { rc = _torture_auth_kbdint(session, password); } } else { rc = ssh_userauth_publickey_auto(session, NULL, NULL); if (rc == SSH_AUTH_ERROR) { goto failed; } } if (rc != SSH_AUTH_SUCCESS) { goto failed; } return session; failed: if (ssh_is_connected(session)) { ssh_disconnect(session); } ssh_free(session); return NULL; } #ifdef WITH_SERVER ssh_bind torture_ssh_bind(const char *addr, const unsigned int port, enum ssh_keytypes_e key_type, const char *private_key_file) { int rc; ssh_bind sshbind = NULL; enum ssh_bind_options_e opts = -1; sshbind = ssh_bind_new(); if (sshbind == NULL) { goto out; } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, addr); if (rc != 0) { goto out_free; } rc = ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port); if (rc != 0) { goto out_free; } switch (key_type) { #ifdef HAVE_DSA case SSH_KEYTYPE_DSS: opts = SSH_BIND_OPTIONS_DSAKEY; break; #endif /* HAVE_DSA */ case SSH_KEYTYPE_RSA: opts = SSH_BIND_OPTIONS_RSAKEY; break; case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: opts = SSH_BIND_OPTIONS_ECDSAKEY; break; default: goto out_free; } rc = ssh_bind_options_set(sshbind, opts, private_key_file); if (rc != 0) { goto out_free; } rc = ssh_bind_listen(sshbind); if (rc != SSH_OK) { goto out_free; } goto out; out_free: ssh_bind_free(sshbind); sshbind = NULL; out: return sshbind; } #endif /* WITH_SERVER */ #ifdef WITH_SFTP struct torture_sftp *torture_sftp_session(ssh_session session) { struct torture_sftp *t; char template[] = "/tmp/ssh_torture_XXXXXX"; char *p; int rc; if (session == NULL) { return NULL; } t = malloc(sizeof(struct torture_sftp)); if (t == NULL) { return NULL; } t->ssh = session; t->sftp = sftp_new(session); if (t->sftp == NULL) { goto failed; } rc = sftp_init(t->sftp); if (rc < 0) { goto failed; } p = mkdtemp(template); if (p == NULL) { goto failed; } /* useful if TESTUSER is not the local user */ chmod(template,0777); t->testdir = strdup(p); if (t->testdir == NULL) { goto failed; } return t; failed: if (t->sftp != NULL) { sftp_free(t->sftp); } ssh_disconnect(t->ssh); ssh_free(t->ssh); free(t); return NULL; } void torture_sftp_close(struct torture_sftp *t) { if (t == NULL) { return; } if (t->sftp != NULL) { sftp_free(t->sftp); } free(t->testdir); free(t); } #endif /* WITH_SFTP */ int torture_server_port(void) { char *env = getenv("TORTURE_SERVER_PORT"); if (env != NULL && env[0] != '\0' && strlen(env) < 6) { int port = atoi(env); if (port > 0 && port < 65536) { return port; } } return TORTURE_SSHD_SRV_PORT; } const char *torture_server_address(int family) { switch (family) { case AF_INET: { const char *ip4 = getenv("TORTURE_SERVER_ADDRESS_IPV4"); if (ip4 != NULL && ip4[0] != '\0') { return ip4; } return TORTURE_SSHD_SRV_IPV4; } case AF_INET6: { const char *ip6 = getenv("TORTURE_SERVER_ADDRESS_IPV6"); if (ip6 != NULL && ip6[0] != '\0') { return ip6; } return TORTURE_SSHD_SRV_IPV6; } default: return NULL; } return NULL; } void torture_setup_socket_dir(void **state) { struct torture_state *s; const char *p; size_t len; char *env = NULL; int rc; s = calloc(1, sizeof(struct torture_state)); assert_non_null(s); #ifdef WITH_PCAP env = getenv("TORTURE_PLAIN_PCAP_FILE"); if (env != NULL && env[0] != '\0') { s->plain_pcap = ssh_pcap_file_new(); assert_non_null(s->plain_pcap); rc = ssh_pcap_file_open(s->plain_pcap, env); assert_int_equal(rc, SSH_OK); } #endif /* WITH_PCAP */ s->socket_dir = torture_make_temp_dir(TORTURE_SOCKET_DIR); assert_non_null(s->socket_dir); p = s->socket_dir; /* pcap file */ len = strlen(p) + 1 + strlen(TORTURE_PCAP_FILE) + 1; s->pcap_file = malloc(len); assert_non_null(s->pcap_file); snprintf(s->pcap_file, len, "%s/%s", p, TORTURE_PCAP_FILE); /* pid file */ len = strlen(p) + 1 + strlen(TORTURE_SSHD_PIDFILE) + 1; s->srv_pidfile = malloc(len); assert_non_null(s->srv_pidfile); snprintf(s->srv_pidfile, len, "%s/%s", p, TORTURE_SSHD_PIDFILE); /* config file */ len = strlen(p) + 1 + strlen(TORTURE_SSHD_CONFIG) + 1; s->srv_config = malloc(len); assert_non_null(s->srv_config); snprintf(s->srv_config, len, "%s/%s", p, TORTURE_SSHD_CONFIG); setenv("SOCKET_WRAPPER_DIR", p, 1); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "170", 1); env = getenv("TORTURE_GENERATE_PCAP"); if (env != NULL && env[0] == '1') { setenv("SOCKET_WRAPPER_PCAP_FILE", s->pcap_file, 1); } *state = s; } static void torture_setup_create_sshd_config(void **state, bool pam) { struct torture_state *s = *state; char ed25519_hostkey[1024] = {0}; #ifdef HAVE_DSA char dsa_hostkey[1024]; #endif /* HAVE_DSA */ char rsa_hostkey[1024]; char ecdsa_hostkey[1024]; char trusted_ca_pubkey[1024]; char sshd_config[4096]; char sshd_path[1024]; const char *additional_config = NULL; struct stat sb; const char *sftp_server_locations[] = { "/usr/lib/ssh/sftp-server", "/usr/libexec/ssh/sftp-server", /* Tumbleweed 20200829 */ "/usr/libexec/sftp-server", "/usr/libexec/openssh/sftp-server", "/usr/lib/openssh/sftp-server", /* Debian */ }; const char config_string[]= "Port 22\n" "ListenAddress 127.0.0.10\n" "%s %s\n" /* ed25519 HostKey */ #ifdef HAVE_DSA "%s %s\n" /* DSA HostKey */ #endif /* HAVE_DSA */ "%s %s\n" /* RSA HostKey */ "%s %s\n" /* ECDSA HostKey */ "\n" "TrustedUserCAKeys %s\n" "\n" "LogLevel DEBUG3\n" "Subsystem sftp %s -l DEBUG2\n" "\n" "PasswordAuthentication yes\n" "PubkeyAuthentication yes\n" "\n" "StrictModes no\n" "\n" "%s" /* Here comes UsePam */ "\n" /* add all supported algorithms */ "HostKeyAlgorithms " OPENSSH_KEYS "\n" #if OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR >= 2 "CASignatureAlgorithms " OPENSSH_KEYS "\n" #endif "Ciphers " OPENSSH_CIPHERS "\n" "KexAlgorithms " OPENSSH_KEX "\n" "MACs " OPENSSH_MACS "\n" "\n" "AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES\n" "AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n" "AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n" "\n" "PidFile %s\n" "%s\n"; /* The space for test-specific options */ /* FIPS config */ const char fips_config_string[]= "Port 22\n" "ListenAddress 127.0.0.10\n" "%s %s\n" /* RSA HostKey */ "%s %s\n" /* ECDSA HostKey */ "\n" "TrustedUserCAKeys %s\n" /* Trusted CA */ "\n" "LogLevel DEBUG3\n" "Subsystem sftp %s -l DEBUG2\n" /* SFTP server */ "\n" "PasswordAuthentication yes\n" "PubkeyAuthentication yes\n" "\n" "StrictModes no\n" "\n" "%s" /* UsePam */ "\n" "Ciphers " "aes256-gcm@openssh.com,aes256-ctr,aes256-cbc," "aes128-gcm@openssh.com,aes128-ctr,aes128-cbc" "\n" "MACs " "hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com," "hmac-sha2-512-etm@openssh.com,hmac-sha2-256," "hmac-sha1,hmac-sha2-512" "\n" "GSSAPIKeyExchange no\n" "KexAlgorithms " "ecdh-sha2-nistp256,ecdh-sha2-nistp384," "ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256," "diffie-hellman-group14-sha256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512" "\n" "PubkeyAcceptedKeyTypes " "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com," "ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com," "ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com," "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com," "ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com" "\n" "AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES\n" "AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT\n" "AcceptEnv LC_IDENTIFICATION LC_ALL LC_LIBSSH\n" "\n" "PidFile %s\n" /* PID file */ "%s\n"; /* The space for test-specific options */ const char usepam_yes[] = "UsePAM yes\n" "KbdInteractiveAuthentication yes\n"; const char usepam_no[] = "UsePAM no\n" "KbdInteractiveAuthentication no\n"; size_t sftp_sl_size = ARRAY_SIZE(sftp_server_locations); const char *sftp_server, *usepam; size_t i; bool written = false; int rc; s->srv_pam = pam; if (pam) { usepam = usepam_yes; } else { usepam = usepam_no; } assert_non_null(s->socket_dir); snprintf(sshd_path, sizeof(sshd_path), "%s/sshd", s->socket_dir); rc = lstat(sshd_path, &sb); if (rc == 0 ) { /* The directory is already in place */ written = true; } if (!written) { rc = mkdir(sshd_path, 0755); assert_return_code(rc, errno); } snprintf(ed25519_hostkey, sizeof(ed25519_hostkey), "%s/sshd/ssh_host_ed25519_key", s->socket_dir); #ifdef HAVE_DSA snprintf(dsa_hostkey, sizeof(dsa_hostkey), "%s/sshd/ssh_host_dsa_key", s->socket_dir); #endif /* HAVE_DSA */ snprintf(rsa_hostkey, sizeof(rsa_hostkey), "%s/sshd/ssh_host_rsa_key", s->socket_dir); snprintf(ecdsa_hostkey, sizeof(ecdsa_hostkey), "%s/sshd/ssh_host_ecdsa_key", s->socket_dir); snprintf(trusted_ca_pubkey, sizeof(trusted_ca_pubkey), "%s/sshd/user_ca.pub", s->socket_dir); if (!written) { torture_write_file(ed25519_hostkey, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); #ifdef HAVE_DSA torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0)); #endif /* HAVE_DSA */ torture_write_file(rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(ecdsa_hostkey, torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); torture_write_file(trusted_ca_pubkey, torture_rsa_certauth_pub); } sftp_server = getenv("TORTURE_SFTP_SERVER"); if (sftp_server == NULL) { for (i = 0; i < sftp_sl_size; i++) { sftp_server = sftp_server_locations[i]; rc = lstat(sftp_server, &sb); if (rc == 0) { break; } } } assert_non_null(sftp_server); additional_config = (s->srv_additional_config != NULL ? s->srv_additional_config : ""); if (ssh_fips_mode()) { snprintf(sshd_config, sizeof(sshd_config), fips_config_string, "HostKey", rsa_hostkey, "HostKey", ecdsa_hostkey, trusted_ca_pubkey, sftp_server, usepam, s->srv_pidfile, additional_config); } else { snprintf(sshd_config, sizeof(sshd_config), config_string, "HostKey", ed25519_hostkey, #ifdef HAVE_DSA "HostKey", dsa_hostkey, #endif /* HAVE_DSA */ "HostKey", rsa_hostkey, "HostKey", ecdsa_hostkey, trusted_ca_pubkey, sftp_server, usepam, s->srv_pidfile, additional_config); } torture_write_file(s->srv_config, sshd_config); } static int torture_wait_for_daemon(unsigned int seconds) { struct ssh_timestamp start; int rc; ssh_timestamp_init(&start); while (!ssh_timeout_elapsed(&start, seconds * 1000)) { rc = system(SSH_PING_EXECUTABLE " " TORTURE_SSH_SERVER); if (rc == 0) { return 0; } /* Wait 200 ms before retrying */ usleep(200 * 1000); } return 1; } void torture_setup_sshd_server(void **state, bool pam) { struct torture_state *s; char sshd_start_cmd[1024]; int rc; torture_setup_socket_dir(state); torture_setup_create_sshd_config(state, pam); /* Set the default interface for the server */ setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1); setenv("PAM_WRAPPER", "1", 1); s = *state; snprintf(sshd_start_cmd, sizeof(sshd_start_cmd), SSHD_EXECUTABLE " -r -f %s -E %s/sshd/daemon.log 2> %s/sshd/cwrap.log", s->srv_config, s->socket_dir, s->socket_dir); rc = system(sshd_start_cmd); assert_return_code(rc, errno); setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1); unsetenv("PAM_WRAPPER"); /* Wait until the sshd is ready to accept connections */ rc = torture_wait_for_daemon(5); assert_int_equal(rc, 0); } void torture_teardown_socket_dir(void **state) { struct torture_state *s = *state; char *env = getenv("TORTURE_SKIP_CLEANUP"); int rc; if (env != NULL && env[0] == '1') { fprintf(stderr, "[ TORTURE ] >>> Skipping cleanup of %s\n", s->socket_dir); } else { rc = torture_rmdirs(s->socket_dir); if (rc < 0) { fprintf(stderr, "torture_rmdirs(%s) failed: %s", s->socket_dir, strerror(errno)); } } #ifdef WITH_PCAP if (s->plain_pcap != NULL) { ssh_pcap_file_free(s->plain_pcap); } s->plain_pcap = NULL; #endif /* WITH_PCAP */ free(s->srv_config); free(s->socket_dir); free(s->pcap_file); free(s->srv_pidfile); free(s->srv_additional_config); free(s); } static int torture_reload_sshd_server(void **state) { struct torture_state *s = *state; pid_t pid; int rc; /* read the pidfile */ pid = torture_read_pidfile(s->srv_pidfile); assert_int_not_equal(pid, -1); kill(pid, SIGHUP); /* 10 ms */ usleep(10 * 1000); rc = kill(pid, 0); if (rc != 0) { fprintf(stderr, "ERROR: SSHD process %u died during reload!\n", pid); return SSH_ERROR; } /* Wait until the sshd is ready to accept connections */ rc = torture_wait_for_daemon(5); assert_int_equal(rc, 0); return SSH_OK; } /* @brief: Updates SSHD server configuration with more options and * reloads the server to apply them. * Note, that this still uses the default configuration options specified * in this file and overwrites options previously specified by this function. */ int torture_update_sshd_config(void **state, const char *config) { struct torture_state *s = *state; int rc; /* Store the configuration in internal structure */ SAFE_FREE(s->srv_additional_config); s->srv_additional_config = strdup(config); assert_non_null(s->srv_additional_config); /* Rewrite the configuration file */ torture_setup_create_sshd_config(state, s->srv_pam); /* Reload the server */ rc = torture_reload_sshd_server(state); assert_int_equal(rc, SSH_OK); return SSH_OK; } void torture_teardown_sshd_server(void **state) { struct torture_state *s = *state; int rc; rc = torture_terminate_process(s->srv_pidfile); if (rc != 0) { fprintf(stderr, "XXXXXX Failed to terminate sshd\n"); } torture_teardown_socket_dir(state); } char *torture_make_temp_dir(const char *template) { char *new_dir = NULL; char *template_copy = NULL; if (template == NULL) { goto end; } template_copy = strdup(template); if (template_copy == NULL) { goto end; } new_dir = mkdtemp(template_copy); if (new_dir == NULL) { SAFE_FREE(template_copy); } end: return template_copy; } char *torture_create_temp_file(const char *template) { char *new_file = NULL; FILE *fp = NULL; mode_t mask; int fd; new_file = strdup(template); if (new_file == NULL) { goto end; } mask = umask(S_IRWXO | S_IRWXG); fd = mkstemp(new_file); umask(mask); if (fd == -1) { goto end; } fp = fdopen(fd, "w"); if (fp == NULL) { SAFE_FREE(new_file); close(fd); goto end; } fclose(fp); end: return new_file; } char *torture_get_current_working_dir(void) { char *cwd = NULL; char *result = NULL; cwd = (char *)malloc(PATH_MAX + 1); if (cwd == NULL) { goto end; } result = getcwd(cwd, PATH_MAX); if (result == NULL) { SAFE_FREE(cwd); goto end; } end: return cwd; } #else /* _WIN32 */ char *torture_make_temp_dir(const char *template) { DWORD rc = 0; char tmp_dir_path[MAX_PATH]; char tmp_file_name[MAX_PATH]; char *prefix = NULL; char *path = NULL; char *prefix_end = NULL; char *slash = NULL; BOOL created; if (template == NULL) { goto end; } prefix = strdup(template); if (prefix == NULL) { goto end; } /* Replace slashes with backslashes */ slash = strchr(prefix, '/'); for (; slash != NULL; slash = strchr(prefix, '/')) { *slash = '\\'; } prefix_end = strstr(prefix, "XXXXXX"); if (prefix_end != NULL) { *prefix_end = '\0'; } rc = GetTempPathA(MAX_PATH, tmp_dir_path); if ((rc > MAX_PATH) || (rc == 0)) { goto free_prefix; } rc = GetTempFileNameA(tmp_dir_path, TEXT(prefix), 0, tmp_file_name); if (rc == 0) { goto free_prefix; } path = strdup(tmp_file_name); if (path == NULL) { goto free_prefix; } /* GetTempFileNameA() creates a temporary file; we need to remove it */ rc = DeleteFileA(path); if (rc == 0) { rc = -1; SAFE_FREE(path); goto free_prefix; } created = CreateDirectoryA(path, NULL); if (!created) { SAFE_FREE(path); } free_prefix: SAFE_FREE(prefix); end: return path; } static int recursive_rm_dir_content(const char *path) { WIN32_FIND_DATA file_data; HANDLE file_handle; DWORD attributes; DWORD last_error = 0; char file_path[MAX_PATH]; int rc = 0; BOOL removed; strcpy(file_path, path); strcat(file_path, "\\*"); file_handle = FindFirstFile(file_path, &file_data); if (file_handle == INVALID_HANDLE_VALUE) { last_error = GetLastError(); /* Empty directory */ if (last_error == ERROR_FILE_NOT_FOUND) { rc = 0; } else { /*TODO print error message?*/ rc = last_error; } goto end; } else { do { rc = strcmp(file_data.cFileName, "."); if (rc == 0) { continue; } rc = strcmp(file_data.cFileName, ".."); if (rc == 0) { continue; } /* Create full file path */ strcpy(file_path, path); strcat(file_path, "\\"); strcat(file_path, file_data.cFileName); attributes = GetFileAttributes(file_path); if (attributes & FILE_ATTRIBUTE_DIRECTORY) { rc = recursive_rm_dir_content((const char *)file_path); if (rc != 0) { goto end; } removed = RemoveDirectoryA(file_path); if (!removed) { last_error = GetLastError(); /*TODO print error message?*/ rc = last_error; goto end; } } else { rc = remove(file_path); if (rc) { goto end; } } } while(FindNextFile(file_handle, &file_data)); FindClose(file_handle); } end: return rc; } int torture_rmdirs(const char *path) { int rc = 0; BOOL removed; rc = recursive_rm_dir_content(path); if (rc) { return rc; } removed = RemoveDirectoryA(path); if (!removed) { rc = -1; } return rc; } int torture_isdir(const char *path) { DWORD attributes = 0; attributes = GetFileAttributes(path); if (attributes & FILE_ATTRIBUTE_DIRECTORY) { return 1; } return 0; } char *torture_create_temp_file(const char *template) { DWORD rc = 0; char tmp_dir_path[MAX_PATH]; char tmp_file_name[MAX_PATH]; char *prefix = NULL; char *path = NULL; char *prefix_end = NULL; char *slash = NULL; if (template == NULL) { goto end; } prefix = strdup(template); if (prefix == NULL) { goto end; } /* Replace slashes with backslashes */ slash = strchr(prefix, '/'); for (; slash != NULL; slash = strchr(prefix, '/')) { *slash = '\\'; } prefix_end = strstr(prefix, "XXXXXX"); if (prefix_end != NULL) { *prefix_end = '\0'; } rc = GetTempPathA(MAX_PATH, tmp_dir_path); if ((rc > MAX_PATH) || (rc == 0)) { goto free_prefix; } /* Remark: this function creates the file */ rc = GetTempFileNameA(tmp_dir_path, TEXT(prefix), 0, tmp_file_name); if (rc == 0) { goto free_prefix; } path = strdup(tmp_file_name); free_prefix: SAFE_FREE(prefix); end: return path; } char *torture_get_current_working_dir(void) { char *cwd = NULL; char *result = NULL; cwd = (char *)malloc(_MAX_PATH + 1); if (cwd == NULL) { goto end; } result = _getcwd(cwd, _MAX_PATH); if (result == NULL) { SAFE_FREE(cwd); goto end; } end: return cwd; } #endif /* _WIN32 */ int torture_change_dir(char *path) { int rc = 0; if (path == NULL) { rc = -1; goto end; } rc = chdir(path); end: return rc; } int torture_libssh_verbosity(void){ return verbosity; } void _torture_filter_tests(struct CMUnitTest *tests, size_t ntests) { (void) tests; (void) ntests; return; } void torture_write_file(const char *filename, const char *data){ int fd; int rc; assert_non_null(filename); assert_true(filename[0] != '\0'); assert_non_null(data); fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600); assert_true(fd >= 0); rc = write(fd, data, strlen(data)); assert_int_equal(rc, strlen(data)); close(fd); } void torture_reset_config(ssh_session session) { memset(session->opts.options_seen, 0, sizeof(session->opts.options_seen)); } int main(int argc, char **argv) { struct argument_s arguments; char *env = getenv("LIBSSH_VERBOSITY"); arguments.verbose=0; arguments.pattern=NULL; torture_cmdline_parse(argc, argv, &arguments); verbosity=arguments.verbose; pattern=arguments.pattern; if (verbosity == 0 && env != NULL && env[0] != '\0') { if (env[0] > '0' && env[0] < '9') { verbosity = atoi(env); } } #if defined HAVE_CMOCKA_SET_TEST_FILTER cmocka_set_test_filter(pattern); #endif return torture_run_tests(); } ================================================ FILE: src/libssh/tests/torture.h ================================================ /* * torture.c - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2008-2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef _TORTURE_H #define _TORTURE_H #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include "libssh/priv.h" #include "libssh/server.h" #include "libssh/sftp.h" #include #include "torture_cmocka.h" #include "tests_config.h" #ifndef assert_return_code /* hack for older versions of cmocka */ #define assert_return_code(code, errno) \ assert_true(code >= 0) #endif /* assert_return_code */ #define TORTURE_SSH_SERVER "127.0.0.10" #define TORTURE_SSH_USER_BOB "bob" #define TORTURE_SSH_USER_BOB_PASSWORD "secret" #define TORTURE_SSH_USER_ALICE "alice" /* Used by main to communicate with parse_opt. */ struct argument_s { const char *pattern; int verbose; }; struct torture_sftp { ssh_session ssh; sftp_session sftp; char *testdir; }; struct torture_state { char *socket_dir; char *pcap_file; char *srv_pidfile; char *srv_config; bool srv_pam; char *srv_additional_config; struct { ssh_session session; struct torture_sftp *tsftp; } ssh; #ifdef WITH_PCAP ssh_pcap_file plain_pcap; #endif }; #ifndef ZERO_STRUCT #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) #endif void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments); int torture_rmdirs(const char *path); int torture_isdir(const char *path); int torture_terminate_process(const char *pidfile); /* * Returns the verbosity level asked by user */ int torture_libssh_verbosity(void); ssh_session torture_ssh_session(struct torture_state *s, const char *host, const unsigned int *port, const char *user, const char *password); ssh_bind torture_ssh_bind(const char *addr, const unsigned int port, enum ssh_keytypes_e key_type, const char *private_key_file); struct torture_sftp *torture_sftp_session(ssh_session session); void torture_sftp_close(struct torture_sftp *t); void torture_write_file(const char *filename, const char *data); #define torture_filter_tests(tests) _torture_filter_tests(tests, sizeof(tests) / sizeof(tests)[0]) void _torture_filter_tests(struct CMUnitTest *tests, size_t ntests); const char *torture_server_address(int domain); int torture_server_port(void); void torture_setup_socket_dir(void **state); void torture_setup_sshd_server(void **state, bool pam); void torture_teardown_socket_dir(void **state); void torture_teardown_sshd_server(void **state); int torture_update_sshd_config(void **state, const char *config); void torture_reset_config(ssh_session session); /* * This function must be defined in every unit test file. */ int torture_run_tests(void); char *torture_make_temp_dir(const char *template); char *torture_create_temp_file(const char *template); char *torture_get_current_working_dir(void); int torture_change_dir(char *path); #endif /* _TORTURE_H */ ================================================ FILE: src/libssh/tests/torture_cmocka.c ================================================ /* * torture.c - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2018 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" void _assert_ssh_return_code(ssh_session session, int rc, const char * const file, const int line) { char ssh_error[1024] = {0}; if (session != NULL) { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code - %s", ssh_get_error(session)); } else { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code"); } _assert_true(rc == SSH_OK, ssh_error, file, line); } void _assert_ssh_return_code_equal(ssh_session session, int rc, int expected_rc, const char * const file, const int line) { char ssh_error[1024] = {0}; if (session != NULL) { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code - %s", ssh_get_error(session)); } else { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code"); } _assert_true((rc == expected_rc), ssh_error, file, line); } void _assert_ssh_return_code_not_equal(ssh_session session, int rc, int unexpected_rc, const char * const file, const int line) { char ssh_error[1024] = {0}; if (session != NULL) { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code - %s", ssh_get_error(session)); } else { snprintf(ssh_error, sizeof(ssh_error), "ERROR: Invalid return code"); } _assert_true((rc != unexpected_rc), ssh_error, file, line); } ================================================ FILE: src/libssh/tests/torture_cmocka.h ================================================ /* * torture.c - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2018 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef _TORTURE_CMOCKA_H #define _TORTURE_CMOCKA_H #include "libssh/session.h" void _assert_ssh_return_code(ssh_session session, int rc, const char * const file, const int line); #define assert_ssh_return_code(session, rc) \ _assert_ssh_return_code((session), (rc), __FILE__, __LINE__) void _assert_ssh_return_code_equal(ssh_session session, int rc, int expected_rc, const char * const file, const int line); #define assert_ssh_return_code_equal(session, rc, expected_rc) \ _assert_ssh_return_code_equal((session), (rc), (expected_rc), __FILE__, __LINE__) void _assert_ssh_return_code_not_equal(ssh_session session, int rc, int expected_rc, const char * const file, const int line); #define assert_ssh_return_code_not_equal(session, rc, unexpected_rc) \ _assert_ssh_return_code_not_equal((session), (rc), (unexpected_rc), __FILE__, __LINE__) #endif /* _TORTURE_CMOCKA_H */ ================================================ FILE: src/libssh/tests/torture_key.c ================================================ /* * torture_key.c - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2008-2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #include #include "torture.h" #include "torture_key.h" /**************************************************************************** * DSA KEYS ****************************************************************************/ static const char torture_rsa_private_testkey[] = "-----BEGIN RSA PRIVATE KEY-----\n" "MIIEowIBAAKCAQEArAOREUWlBXJAKZ5hABYyxnRayDZP1bJeLbPVK+npxemrhHyZ\n" "gjdbY3ADot+JRyWjvll2w2GI+3blt0j+x/ZWwjMKu/QYcycYp5HL01goxOxuusZb\n" "i+KiHRGB6z0EMdXM7U82U7lA/j//HyZppyDjUDniWabXQJge8ksGXGTiFeAJ/687\n" "uV+JJcjGPxAGFQxzyjitf/FrL9S0WGKZbyqeGDzyeBZ1NLIuaiOORyLGSW4duHLD\n" "N78EmsJnwqg2gJQmRSaD4BNZMjtbfiFcSL9Uw4XQFTsWugUDEY1AU4c5g11nhzHz\n" "Bi9qMOt5DzrZQpD4j0gA2LOHpHhoOdg1ZuHrGQIDAQABAoIBAFJTaqy/jllq8vZ4\n" "TKiD900wBvrns5HtSlHJTe80hqQoT+Sa1cWSxPR0eekL32Hjy9igbMzZ83uWzh7I\n" "mtgNODy9vRdznfgO8CfTCaBfAzQsjFpr8QikMT6EUI/LpiRL1UaGsNOlSEvnSS0Z\n" "b1uDzAdrjL+nsEHEDJud+K9jwSkCRifVMy7fLfaum+YKpdeEz7K2Mgm5pJ/Vg+9s\n" "vI2V1q7HAOI4eUVTgJNHXy5ediRJlajQHf/lNUzHKqn7iH+JRl01gt62X8roG62b\n" "TbFylbheqMm9awuSF2ucOcx+guuwhkPir8BEMb08j3hiK+TfwPdY0F6QH4OhiKK7\n" "MTqTVgECgYEA0vmmu5GOBtwRmq6gVNCHhdLDQWaxAZqQRmRbzxVhFpbv0GjbQEF7\n" "tttq3fjDrzDf6CE9RtZWw2BUSXVq+IXB/bXb1kgWU2xWywm+OFDk9OXQs8ui+MY7\n" "FiP3yuq3YJob2g5CCsVQWl2CHvWGmTLhE1ODll39t7Y1uwdcDobJN+ECgYEA0LlR\n" "hfMjydWmwqooU9TDjXNBmwufyYlNFTH351amYgFUDpNf35SMCP4hDosUw/zCTDpc\n" "+1w04BJJfkH1SNvXSOilpdaYRTYuryDvGmWC66K2KX1nLErhlhs17CwzV997nYgD\n" "H3OOU4HfqIKmdGbjvWlkmY+mLHyG10bbpOTbujkCgYAc68xHejSWDCT9p2KjPdLW\n" "LYZGuOUa6y1L+QX85Vlh118Ymsczj8Z90qZbt3Zb1b9b+vKDe255agMj7syzNOLa\n" "/MseHNOyq+9Z9gP1hGFekQKDIy88GzCOYG/fiT2KKJYY1kuHXnUdbiQgSlghODBS\n" "jehD/K6DOJ80/FVKSH/dAQKBgQDJ+apTzpZhJ2f5k6L2jDq3VEK2ACedZEm9Kt9T\n" "c1wKFnL6r83kkuB3i0L9ycRMavixvwBfFDjuY4POs5Dh8ip/mPFCa0hqISZHvbzi\n" "dDyePJO9zmXaTJPDJ42kfpkofVAnfohXFQEy+cguTk848J+MmMIKfyE0h0QMabr9\n" "86BUsQKBgEVgoi4RXwmtGovtMew01ORPV9MOX3v+VnsCgD4/56URKOAngiS70xEP\n" "ONwNbTCWuuv43HGzJoVFiAMGnQP1BAJ7gkHkjSegOGKkiw12EPUWhFcMg+GkgPhc\n" "pOqNt/VMBPjJ/ysHJqmLfQK9A35JV6Cmdphe+OIl28bcKhAOz8Dw\n" "-----END RSA PRIVATE KEY-----\n"; static const char torture_rsa_private_testkey_passphrase[] = "-----BEGIN RSA PRIVATE KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: AES-128-CBC,5375534F40903DD66B3851A0DA03F6FA\n" "\n" "m5YYTNOMd1xCKfifwCX4R1iLJoAc4cn1aFiL7f2kBbfE2jF1LTQBJV1h1CqYZfAB\n" "WtM/7FkQPnKXqsMndP+v+1Xc+PYigE3AezJj/0g7xn/zIBwGjkLAp435AdL5i6Fg\n" "OhOL8LyolRrcGn17jE4S4iGbzw8PVyfzNzdj0Emwql5F6M7pgLbInRNKM/TF4z2h\n" "b6Pi9Bw43dwaJ7wiiy/vo/v4MyXsJBoeKbc4VCmxiYFvAYCvVFlDkyIw/QnR3MKQ\n" "g/Zsk7Pw3aOioxk6LJpZ5x0tO23nXDG1aOZHWykI0BpJV+LIpD2oSYOHJyVO83XT\n" "RQUMSTXc2K2+ejs0XQoLt/GxDDHe+8W8fWQK3C7Lyvl9oKjmb5sTWi3mdSv0C+zR\n" "n5KSVbUKNXrjix7qPKkv5rWqb84CKVnCMb7tWaPLR19nQqKVYBIs6v0OTTvS6Le7\n" "lz4lxBkcUy6vi0tWH9MvLuT+ugdHLJZ4UXBthCgV58pM1o+L+WMIl+SZXckiCAO3\n" "7ercA57695IA6iHskmr3eazJsYFEVFdR/cm+IDy2FPkKmJMjXeIWuh3yASBk7LBR\n" "EQq3CC7AioO+Vj8m/fEIiNZJSQ6p0NmgnPoO3rTYT/IobmE99/Ht6oNLmFX4Pr7e\n" "F4CGWKzwxWpCnw2vVolCFByASmZycbJvrIonZBKY1toU28lRm4tCM6eCNISVLMeE\n" "VtQ+1PH9/2KZspZl+SX/kjV3egggy0TFKRU8EcYPJFC3Vpy+shEai35KBVo44Z18\n" "apza7exm3igNEqOqe07hLs3Bjhvk1oS+WhMbAG9ARTOKuyBOJh/ZV9tFMNZ6v+q5\n" "TofgNcIhNYNascymU1io18xTW9c3RRcmRKqIWnj4EH8o7Aojv/l+zvdV7/GVlR4W\n" "pR9cuJEiyiEjS46axoc6dSOtdnvag+BpFQb+lGY97F9nNGyBdtLD5ASVh5OVG4fu\n" "Pf0O7Bdj1kIuBhV8axE/slf6UHANiodeqkR9B24+0Cy+miPiHazzUkbdSJ4r03g5\n" "J1Y5S8qbl9++sqhQMLMUkeK4pDWh1aocA9bDA2RcBNuXGiZeRFUiqxcBS+iO418n\n" "DFyWz4UfI/m1IRSjoo/PEpgu5GmosUzs3Dl4nAcf/REBEX6M/kKKxHTLjE8DxDsz\n" "fn/vfsXV3s0tbN7YyJdP8aU+ApZntw1OF2TS2qS8CPWHTcCGGTab5WEGC3xFXKp0\n" "uyonCxV7vNLOiIiHdQX+1bLu7ps7GBH92xGkPg7FrNNcMc07soP7jjjB578n9Gpl\n" "cIDBdgovTRFHiWu3yRspVt0zPfMJB/hqn+IAp98wfvjl8OZM1ZZkejnwXnQil5ZU\n" "wjEBEtx+nX56vdxipzKoHh5yDXmPbNajBYkg3rXJrLFh3Tsf0CzHcLdHNz/qJ9LO\n" "wH16grjR1Q0CzCW3FAv0Q0euqkXac+TfuIg3HiTPrBPnJQW1uivrx1F5tpO/uboG\n" "h28LwqJLYh+1T0V//uiy3SMATpYKvzg2byGct9VUib8QVop8LvVF/n42RaxtTCfw\n" "JSvUyxoaZUjQkT7iF94HsF+FVVJdI55UjgnMiZ0d5vKffWyTHYcYHkFYaSloAMWN\n" "-----END RSA PRIVATE KEY-----\n"; static const char torture_rsa_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI0RSm1ZXOBD8CAggA\n" "MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBS+59quuIVuxN/H9Wltk8TBIIE\n" "0J7OhRw35ANRyTU2qhlhS8NATcguoD1J4IMXpXpv38iCBWd2bjxvuWnEu4aBX7iU\n" "desfz9n6AoTVqURaOMLsv6EFV0tycf+mZsmdUmrD2270Wyj6TtQD8LO/7ibifCeL\n" "XCCKjxciueSggHp5lnfogZwn8wjSEDP7OqNVRTwm8QKNrE7J5m5giFrjXoyqKM7r\n" "DBa35UIZAXXY8z9CkI+GsyRtaZik3VD+xHShwUriOYg4x4VGZQLj24tjoUnqU4ml\n" "iRMhGyYpxN7CnfaIwHJr3T0dmbT/BIXOQ2B6sWakioZeUuA6OTBHbFTUN9TUHaF0\n" "rDMVmjL6BQcEiWwjvtw/3NLdkcKFjMiLTWA2GL71KPGCecpMmAMjo+ijnxeVhqpQ\n" "dnhowG92DhCSf/XZI0vaaYflrV54U9PgcSPDFWmTOVe5151Mi8eR9qrCanfyHmX1\n" "MLXs8Mw6xWedNj8AWLV3JGiWEeAEATuTAQfTqmBZbzaFKfSKp5PZjWxa5bZIomzS\n" "Q0AsONTeYmKK+Pv95RYlgR2kKqhwy3OmcOuepwnzSeAGh1BdBzd2raoipkq1fpY5\n" "8e75dJnTGvWfqfh0VXz/Wud+hMz/98Mh6Bnp9l+Ddxpp4RioWB2aH0HM8ZGTlbhf\n" "r5qFmDY7k+RfDDp7K7UYMA+2hHCxY1aFSHVYGRQKdYdKIugLtKx6YKLeGVCR7Gbm\n" "l/88qiGshF/qhdFbPb4K0Tz2Ug5uklveOQSkKX6RSZ30IW+N3E4nH/wvyOwbCPk7\n" "u+iHB2zzk2Hws4O52a0Gqj+RbeGzzhl1D9jH35GMHUsfhDSA3/mmrVC7hiN/Aplt\n" "2OmKFAkobZh/1UJAHBY9feIhLmQUy9dwy0E8G/0LEyyZYEizDC76jsvbh2cPg3jM\n" "JsI31qUaGggwh3wB034BvsYIf/ZqLCt8hAXF9U5U7T5y3r6FNNBla8zlj25ILog6\n" "t/bhOwFKYXamAVYMhhvUiA3YIYuBxT7MrgL7gDtKh3N/DleS/pLjmOFfMI3dfCd0\n" "KSQX46uw7aFbV0Has9uUuGle9Foq52QFvYnDHWJuIyOvJ5st1Hd3Mjjsl9t3JFVM\n" "I1aDZ17Z4LoThdezNQKGaAe5z7gGFMKKsm55CMT/7FxvConALeQKGAV6jA5xZzl4\n" "+QB14YlxlZTxYnXd/69KGV56wP8sb6uMVDC/f5Vd3oHsamJKpPgts8WCn11f9wFn\n" "Mx8YY/vBVVLQMw1aB+82Vk+Ix8YDYIPj5bJk2BkyCCUnMYkKswUOVzsdUq0xssEp\n" "PASw0YvQ9mY2aQ9exme99JuAj5t4qIXoYTSrX5iv6NXtzDHgTR1pl9gQQVQ0zAUO\n" "ZHKZXYAv5rLZKRcyeCLw0LkuthY2QtN3PsBlaRtfwZTaqUbBGbvEkcx5fxdEsasS\n" "yQkZKBBvIi42LUN9ZzywYNGbOanCZ04p/+QscmmnVGuDMZJyaDRaapW6f0nJQ+lQ\n" "CaVPRzLKGnHV5hWQDjTaPIh2s9rJSZJ3HyE8qshETHW/vQoYIcVB9TX5TnOY02Ak\n" "IINKfSZGgz/NBeJItjk30UuTcISk65ekoXZIHHgdxD9iHy9D0w6FXcPNLLsWQn7n\n" "jS4Bvt0VZ9zVAiyyVO4yAaMgP+saitYpjMgI8g67geD3\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_rsa_private_openssh_testkey_passphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDX\n" "ClCBeHgYyOEqmWpAanz9AAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAAB\n" "AQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP2PhOh5pyxa1VfGKe\n" "453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjOFvRRTLot5fPLNDOv\n" "9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpbJvTXSDipukpUy41d\n" "7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdcARyhix4RMWZZqVY2\n" "0H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1TjzkrBZ6B6thmZty\n" "eb9IsiB0tg2g0JN2VTAGkxqpAAADwG8gm8jZpx+GIKdhV+igcvYvIhzA+fz6UdXf\n" "d/8wnYzMXtg+Ys7XsKUsxtMD8HGPiuwYsTrd/YGiol7SpkJV0STqtW+UZrcKamJ5\n" "reFaDoIU8hhWTXCe/ogplTxH/zNNK7Xx5OAGnNWE3zsR1vbZaCv+Vwwa27eUCbpv\n" "V1+92nBwkah3FCKCbwYDvTVRn1TZHQwnuNxDCRrlwaMjf8eX2ssqLLX7jqrb3j1u\n" "c28GR3fNJ8ENaWshZ77tqexUQCnCx14/qtT434CMvENXnCP5BP/cRmbOlCFQ6Id7\n" "nLMW0uDIy/q3xBsAcdMyV0LJW7sJNXIjTnS4lyXd0XescXrqTAKxTkqd1E0VIBpc\n" "37+7vqv9A9Xxq74jy//L9L4Yrbijc9Vt+oNWFgOuakZGBLIQvm36Oqb0z0oWJcUt\n" "VdZcvkCNMeixBqCnrQ8egO3x0pnZwo6cwH586Me8FgFacOnzWjzuQT6vYJ4EK5ch\n" "YNRQpjtz5+T3rZK7eIF1ZUobM4S6di7A6lW9tycQVhjo5XlhalMfCfajhazgcIrY\n" "Qdaq8+AguP8H+3bvXPZmitL8/mv5uVjqxy1lYh2xLzViTmFnvfdbZ92BWI9C6JBI\n" "+mRWzXeEY71MjfeEaPStwBm5OYBMFwYrXPL7E3JjAXRxbB+LKUksj/lRk3K7aQp4\n" "IDKCzAACgkOixfP39BgKQkrLjAoi6mEDqu5Ajc3GoljXsJEkcbu0j+0tVth+41nV\n" "8yCkP5SVUQTCSKzoduE+0pk6oYO6vrwKLM62cQRPXLl/XNoUqETIe8dklIKojYo6\n" "3ho1RaHgYr9/NAS0029CFt/rGmONWF9ihKON6wMavJRcofZ25FeylKiP2rrqdDIb\n" "EiWULZi3MUJfKBwSeZMwaYYmSpaOZF1U/MgvEfeRkE1UmDp3FmBLSNHBYhAxNazH\n" "R393BTr1zk7h+8s7QK986ZtcKkyUNXEK1NkLLuKlqMwFnjiOdeAIGwz9NEn+Tj60\n" "jE5IcCE06B6ze/MOZcsPp1SoZv4kKmgWY5Gdqv/9O9SyFQ0Yh4MvBSD8l4x0epId\n" "8Xm54ISVWP1SZ1x3Oe8yvtwOGqDkZeOVjnP7EQ7R0+1PZzW5P/x47skACqadGChN\n" "ahbngIl+EhPOqhx+wIfDbtzTmGABgNhcI/d02b8py5MXFnA+uzeSucDREYRdm2TO\n" "TQQ2CtxB6lcatIYG4AhyouQbujLd/AwpZJ05S1i/Qt6NenTgK3YyTWdXLQnjZSMx\n" "FBRkf+Jj9eVXieT4PJKtWuvxNNrJVA==\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_rsa_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdz\n" "c2gtcnNhAAAAAwEAAQAAAQEA1717msM2gKxMJCyF08/xFssCzgrakC9z/cipK4c+\n" "gKZVz9j4ToeacsWtVXxinuOd4zXmASdETraNwbIV4GV26POqC105G3tIDucYt6+V\n" "o18Yzhb0UUy6LeXzyzQzr/fk57D5pDZ9IiHsj5363DyMo1rec0llH5DQvKDR8bIk\n" "rIY6Wyb010g4qbpKVMuNXe44OLlhrqJzExe8rux37h6qu5YW9FpcEqX26gG32AEQ\n" "XXXHXAEcoYseETFmWalWNtB91bI6vG4ygvjSVxXHtT0YPqnDlkHZVxHouHZMwLx7\n" "30EcdU485KwWegerYZmbcnm/SLIgdLYNoNCTdlUwBpMaqQAAA7iQHqVWkB6lVgAA\n" "AAdzc2gtcnNhAAABAQDXvXuawzaArEwkLIXTz/EWywLOCtqQL3P9yKkrhz6AplXP\n" "2PhOh5pyxa1VfGKe453jNeYBJ0ROto3BshXgZXbo86oLXTkbe0gO5xi3r5WjXxjO\n" "FvRRTLot5fPLNDOv9+TnsPmkNn0iIeyPnfrcPIyjWt5zSWUfkNC8oNHxsiSshjpb\n" "JvTXSDipukpUy41d7jg4uWGuonMTF7yu7HfuHqq7lhb0WlwSpfbqAbfYARBddcdc\n" "ARyhix4RMWZZqVY20H3Vsjq8bjKC+NJXFce1PRg+qcOWQdlXEei4dkzAvHvfQRx1\n" "TjzkrBZ6B6thmZtyeb9IsiB0tg2g0JN2VTAGkxqpAAAAAwEAAQAAAQAdjR3uQAkq\n" "LO+tENAwCE680YgL0x7HG0jnHWJWzQq5so8UjmLM1vRH/l3U1Nnpa8JHyi08QTWx\n" "Fn5qZstqVluoYyAKuHVHF2bya6NOHeYAX9lU+X3z2O+zs8jmL7tYwjr/pZU8ch5H\n" "25+8uGYRXtXg1mScJBSO81Y0UE8RrVYqr2Os583yB657kYiVYYYSZlRGd9wmfXnJ\n" "w0t8LaYcTn+i/lOvrJGa0Q0iV6+4rYmjwYd/D/vyNzF31hUEFrn3vDSgTnJdShgH\n" "VqW0OwNuEDe/4p8KkKR1EVVj6xv4zicwouY7aQI+zT3MwAzvNdvYwytsIj6bhT9x\n" "oyeAAIW0vaKVAAAAgQD6pPfu6tb7DiTlaH3/IPdGh3PTIf0zXHZ/ygxORXBZdoLY\n" "Fq2h/YnBd2Hs8vARAjGJYs78gTPP0FVXPV8ut38xct4DQ2hbPMrjWv5gdhDazq8Q\n" "qaFEa0+DeYONej8ItKwpsV2Rskkv5Pfm7M6EffVty1uzOpIcT8RYDAYUlc5D/wAA\n" "AIEA+44ykLho3BDWnUzshVEm6iNoqlZqcDVcNSpCuYDnCy5UrTDk0zj+OUG9M0Zx\n" "4c7kAmu/poXSimgAgMh9GNCzy3+a70WvH+fBqvG5tXLaSOQCswSdQjltANAnlt5L\n" "YDHzGGJBsS4pYxoz22MKhFbpYUCQJvotXnZJpTQU6hdFRX8AAACBANuNSlFq/vG8\n" "Vf9c2YsPiITmOrYxpUDMiMLvUGQOdyIIc45EAggOFHNF3AdPZEhinpD92EK+LiJc\n" "WYJ26muVcicZoddgmpcHRt2gByC+ckWOM4sLpih6EyQLFZfqTx2X+KOI0ZTt7zEi\n" "zfm1MJUNDFOr3DM0VBIf34Bn1hU/isPXAAAAAAEC\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_rsa_public_testkey[] = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsA5ERRaUFckApnmEAFjLGdFrIN" "k/Vsl4ts9Ur6enF6auEfJmCN1tjcAOi34lHJaO+WXbDYYj7duW3SP7H9lbCMwq79B" "hzJxinkcvTWCjE7G66xluL4qIdEYHrPQQx1cztTzZTuUD+P/8fJmmnIONQOeJZptd" "AmB7ySwZcZOIV4An/rzu5X4klyMY/EAYVDHPKOK1/8Wsv1LRYYplvKp4YPPJ4FnU0" "si5qI45HIsZJbh24csM3vwSawmfCqDaAlCZFJoPgE1kyO1t+IVxIv1TDhdAVOxa6B" "QMRjUBThzmDXWeHMfMGL2ow63kPOtlCkPiPSADYs4ekeGg52DVm4esZ " "aris@aris-air\n"; static const char torture_rsa_testkey_cert[] = "ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNz" "aC5jb20AAAAgL77S/SgY969FbEtNBsbLvvtGFgnEHaPb+V7ajwuf+R0AAAADAQABA" "AABAQCsA5ERRaUFckApnmEAFjLGdFrINk/Vsl4ts9Ur6enF6auEfJmCN1tjcAOi34" "lHJaO+WXbDYYj7duW3SP7H9lbCMwq79BhzJxinkcvTWCjE7G66xluL4qIdEYHrPQQ" "x1cztTzZTuUD+P/8fJmmnIONQOeJZptdAmB7ySwZcZOIV4An/rzu5X4klyMY/EAYV" "DHPKOK1/8Wsv1LRYYplvKp4YPPJ4FnU0si5qI45HIsZJbh24csM3vwSawmfCqDaAl" "CZFJoPgE1kyO1t+IVxIv1TDhdAVOxa6BQMRjUBThzmDXWeHMfMGL2ow63kPOtlCkP" "iPSADYs4ekeGg52DVm4esZAAAAAAAAAAAAAAABAAAADmxpYnNzaF90b3J0dXJlAAA" "AAAAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRp" "bmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtc" "G9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdX" "Nlci1yYwAAAAAAAAAAAAABFwAAAAdzc2gtcnNhAAAAAwEAAQAAAQEAoowcv2Gn8tO" "eDyw/lgdMpoBsLtHTTdVVOOo5HwMFvj/lFkbZlb6J2n9GIE64HNPE45vSnIdJZwz4" "UYfTvtnNKNHp1MgMrjK1Z6EjyZsGqDZ+BhmvcKA6IckkhBJnDV7U9dMrovAWha61Z" "9GpDqB1naRfbwqJQwSRHF1p71Cnf0fZKxOhAVx0ophmYGz3x3qq4PeOZv3Yl0AHTV" "dRmqmeELDUxeuXN2bgSyb881zEgdaKHH5oWySykP4uwjn6T7ETuL2MsDdG3HZHDhn" "LzLmfzOZ/cNadMCrgauMluQKc5dYF2TSeDaUxwun/NPMQBVZdETHLAMBgkGmhRUku" "flVDIQAAAQ8AAAAHc3NoLXJzYQAAAQADSp4b/Zta8zs6v47iwmxV2Gbucvt1kDrvT" "vKAKSbGN0+zoMyXiNfMHM/OvZObDS/WWGs4GMRqbJavwO3ja/dQY17oJss23lZ+Rc" "Lw4Rqsi3/ZEPCnX6ficiRS/yRN/LAkoXvx9vBx9QHfxlzF6JXq07wTt21zxW0tntd" "8dL+JI9ZZ9YylnxF3gHqfRFe2ahJpiywmxm0yOZgDmimOhep59i6BH5zHiPALvpge" "Mbk075oA5K9XKsHTflCcsQRQH+pXqaNQGL37z2CFz9oezxQYvIqqKF0w/eeRIARoA" "neB6OdgTpKFsmgPZVtqrvhjw+b5T8a4W4iWSl+6wg6gowAm " "rsa_privkey.pub\n"; /**************************************************************************** * DSA KEYS ****************************************************************************/ static const char torture_dsa_private_testkey[] = "-----BEGIN DSA PRIVATE KEY-----\n" "MIIBuwIBAAKBgQCUyvVPEkn3UnZDjzCzSzSHpTltzr0Ec+1mz/JACjHMBJ9C/W/P\n" "wvH3yjkfoFhhREvoY7IPnwAu5bcxw8TkISq7YROQ409PqwwPvy0N3GUp/+kKS268\n" "BIJ+VKN513XRf7eL1e4aHUJ+al9x1JxTmc6T0GBq1lyu+CTUUyh25aNDFwIVAK84\n" "j20GmU+zewjQwsIXuVb6C/PHAoGAXhuIVsJxUQJ5nWQRLf7o3XEGQ+EcVmHOzMB1\n" "xCsHjYnpEhhco+r/HDZSD31kzDeAZUycz31WqGL8yXr+OZRLqEsGC7dwEAzPiXDu\n" "l0zHcl0yiKPrRrLgNJHeKcT6JflBngK7jQRIVUg3F3104fbVa2rwaniLl4GSBZPX\n" "MpUdng8CgYB4roDQBfgf8AoSAJAb7y8OVvxt5cT7iqaRMQX2XgtW09Nu9RbUIVS7\n" "n2mw3iqZG0xnG3iv1oL9gwNXMLlf+gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM7b2u\n" "ADmhirI6dRZUVO+/iMGUvDxa66OI4hDV055pbwQhtxupUatThyDzIgIVAI1Hd8/i\n" "Pzsg7bTzoNvjQL+Noyiy\n" "-----END DSA PRIVATE KEY-----\n"; static const char torture_dsa_private_testkey_passphrase[] = "-----BEGIN DSA PRIVATE KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: AES-128-CBC,266023B64B1B814BCD0D0E477257F06D\n" "\n" "QJQErZrvYsfeMNMnU+6yVHH5Zze/zUFdPip7Bon4T1wCGlVasn4x/GQcMm1+mgmb\n" "PCK/qJ5qw9nCepLYJq2xh8gohbwF/XKxeaNGcRA2+ancTooDUjeRTlk1WRtS1+bq\n" "LBkwhxLXW26lIuQUHzfi93rRqQI2LC4McngY7L7WVJer7sH7hk5//4Gf6zHtPEl+\n" "Tr2ub1zNrVbh6e1Bitw7DaGZNX6XEWpyTTsAd42sQWh6o23MC6GyfS1YFsPGHzGe\n" "WYQbWn2AZ1mK32z2mLZfVg41qu9RKG20iCyaczZ2YmuYyOkoLHijOAHC8vZbHwYC\n" "+lN9Yc8/BoMuMMwDTMDaJD0TsBX02hi9YI7Gu88PMCJO+SRe5400MonUMXTwCa91\n" "Tt3RhYpBzx2XGOq5199+oLdTJAaXHJcuB6viKNdSLBuhx6RAEJXZnVexchaHs4Q6\n" "HweIv6Et8MjVoqwkaQDmcIGA73qZ0lbUJFZAu2YDJ6TpHc1lHZes763HoMYfuvkX\n" "HTSuHZ7edjoWqwnl/vkc3+nG//IEj8LqAacx0i4krDcQpGuQ6BnPfwPFco2NQQpw\n" "wHBOL6HrOnD+gGs6DUFwzA==\n" "-----END DSA PRIVATE KEY-----\n"; static const char torture_dsa_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIIBrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQI8001emUNAOECAggA\n" "MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBDgXXvQsVxY6zaAQVwzUwvDBIIB\n" "UOBQqqJs4rYK6R0rXFitkdUodOK3CdFAKodyCkSC5cgoW2+ht2ndRCepxuKB2X14\n" "Lvt1CIxPvu1k7bGnd25kePmNF85cJxG9wf0/+6vpptO3fTUdsUKyLcRKDqvxxOMB\n" "OSqQK1MLgvUxB5uBSGCsKqFkVUPYs46uihfozjqHH2IghHSQr+VczhFDoWtzgcgp\n" "nRNZiyXN5Thob5WOrL849TSlcaMyI3ssErEVP1G2t3ax5bLQ4AqDddumoRBed/XY\n" "lad5QGAS2XlwMFj8tR/Spi1fEWfamIsvh23ba5ksb35TT3SUJd2gf2NC7QEz3dUK\n" "YDSSeRSF24c4nXBsJ94TkVuUujo4X3QSaWQ2anYYBBwfQtrddVNVu95QS2sQGLov\n" "UWIhq1xXbnL/SGC6E5T1VGnAx3qwfDEZX5tTNzkwqeTZfkrb6vRk+O+Lxt67iP+n\n" "nw==\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_dsa_private_openssh_testkey_passphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBC\n" "UZK61oXs3uKMs4l7G0cpAAAAEAAAAAEAAAGxAAAAB3NzaC1kc3MAAACBAJTK9U8S\n" "SfdSdkOPMLNLNIelOW3OvQRz7WbP8kAKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+f\n" "AC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3cZSn/6QpLbrwEgn5Uo3nXddF/t4vV7hod\n" "Qn5qX3HUnFOZzpPQYGrWXK74JNRTKHblo0MXAAAAFQCvOI9tBplPs3sI0MLCF7lW\n" "+gvzxwAAAIBeG4hWwnFRAnmdZBEt/ujdcQZD4RxWYc7MwHXEKweNiekSGFyj6v8c\n" "NlIPfWTMN4BlTJzPfVaoYvzJev45lEuoSwYLt3AQDM+JcO6XTMdyXTKIo+tGsuA0\n" "kd4pxPol+UGeAruNBEhVSDcXfXTh9tVravBqeIuXgZIFk9cylR2eDwAAAIB4roDQ\n" "Bfgf8AoSAJAb7y8OVvxt5cT7iqaRMQX2XgtW09Nu9RbUIVS7n2mw3iqZG0xnG3iv\n" "1oL9gwNXMLlf+gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM7b2uADmhirI6dRZUVO+/\n" "iMGUvDxa66OI4hDV055pbwQhtxupUatThyDzIgAAAeAtGFEW6JZTeSumizZJI4T2\n" "Kha05Ze3juTeW+BMjqTcf77yAL2jvsljogCtu4+5CWWO4g+cr80vyVytji6IYTNM\n" "MPn1qe6dHXnfmgtiegHXxrjr5v5/i1cvD32Bxffy+yjR9kbV9GJYF+K5pfYVpQBa\n" "XVmq6AJUPd/yxKw6jRGZJi8GTcrKbCZAL+VYSPwc0veCrmGPjeeMCgYcEXPvhSui\n" "P0JnG1Ap12FeK+61rIbZBAr7qbTGJi5Z5HlDlgon2tmMZOkIuL1Oytgut4MpmYjP\n" "ph+qrzgwfSwOsjVIuHlb1L0phWRlgbT8lmysEE7McGKWiCOabxgl3NF9lClhDBb9\n" "nzupkK1cg/4p17USYMOdeNhTmJ0DkQT+8UenfBOmzV7kamLlEYXJdDZBN//dZ8UR\n" "KEzAzpaAVIyJQ+wvCUIh/VO8sJP+3q4XQUkv0QcIRlc0+r9qbW2Tqv3vajFcFtK6\n" "nrTmIJVL0pG+z/93Ncpy5susD+JvhJ4yfl7Jet3jy4fWwm3qkLl0WsobJ7Om+GyH\n" "DzHH9RgDk3XuUHS/fz+kTwmtyIH/Rq1jIt+s+T8iA9CzKSX6sBu2yfMo1w2/LbCx\n" "Xy1rHS42TePw28m1cQuUfjqdOC3IBgQ1m3x2f1on7hk=\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_dsa_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsQAAAAdz\n" "c2gtZHNzAAAAgQCUyvVPEkn3UnZDjzCzSzSHpTltzr0Ec+1mz/JACjHMBJ9C/W/P\n" "wvH3yjkfoFhhREvoY7IPnwAu5bcxw8TkISq7YROQ409PqwwPvy0N3GUp/+kKS268\n" "BIJ+VKN513XRf7eL1e4aHUJ+al9x1JxTmc6T0GBq1lyu+CTUUyh25aNDFwAAABUA\n" "rziPbQaZT7N7CNDCwhe5VvoL88cAAACAXhuIVsJxUQJ5nWQRLf7o3XEGQ+EcVmHO\n" "zMB1xCsHjYnpEhhco+r/HDZSD31kzDeAZUycz31WqGL8yXr+OZRLqEsGC7dwEAzP\n" "iXDul0zHcl0yiKPrRrLgNJHeKcT6JflBngK7jQRIVUg3F3104fbVa2rwaniLl4GS\n" "BZPXMpUdng8AAACAeK6A0AX4H/AKEgCQG+8vDlb8beXE+4qmkTEF9l4LVtPTbvUW\n" "1CFUu59psN4qmRtMZxt4r9aC/YMDVzC5X/oC5rKlN+/PI2hGfSIWfFXYBwKB5ulF\n" "jO29rgA5oYqyOnUWVFTvv4jBlLw8WuujiOIQ1dOeaW8EIbcbqVGrU4cg8yIAAAHY\n" "tbI937WyPd8AAAAHc3NoLWRzcwAAAIEAlMr1TxJJ91J2Q48ws0s0h6U5bc69BHPt\n" "Zs/yQAoxzASfQv1vz8Lx98o5H6BYYURL6GOyD58ALuW3McPE5CEqu2ETkONPT6sM\n" "D78tDdxlKf/pCktuvASCflSjedd10X+3i9XuGh1CfmpfcdScU5nOk9BgatZcrvgk\n" "1FModuWjQxcAAAAVAK84j20GmU+zewjQwsIXuVb6C/PHAAAAgF4biFbCcVECeZ1k\n" "ES3+6N1xBkPhHFZhzszAdcQrB42J6RIYXKPq/xw2Ug99ZMw3gGVMnM99Vqhi/Ml6\n" "/jmUS6hLBgu3cBAMz4lw7pdMx3JdMoij60ay4DSR3inE+iX5QZ4Cu40ESFVINxd9\n" "dOH21Wtq8Gp4i5eBkgWT1zKVHZ4PAAAAgHiugNAF+B/wChIAkBvvLw5W/G3lxPuK\n" "ppExBfZeC1bT0271FtQhVLufabDeKpkbTGcbeK/Wgv2DA1cwuV/6AuaypTfvzyNo\n" "Rn0iFnxV2AcCgebpRYztva4AOaGKsjp1FlRU77+IwZS8PFrro4jiENXTnmlvBCG3\n" "G6lRq1OHIPMiAAAAFQCNR3fP4j87IO2086Db40C/jaMosgAAAAABAg==\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_dsa_public_testkey[] = "ssh-dss AAAAB3NzaC1kc3MAAACBAJTK9U8SSfdSdkOPMLNLNIelOW3OvQRz7WbP8k" "AKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+fAC7ltzHDxOQhKrthE5DjT0+rDA+/LQ3c" "ZSn/6QpLbrwEgn5Uo3nXddF/t4vV7hodQn5qX3HUnFOZzpPQYGrWXK74JNRTKHblo0" "MXAAAAFQCvOI9tBplPs3sI0MLCF7lW+gvzxwAAAIBeG4hWwnFRAnmdZBEt/ujdcQZD" "4RxWYc7MwHXEKweNiekSGFyj6v8cNlIPfWTMN4BlTJzPfVaoYvzJev45lEuoSwYLt3" "AQDM+JcO6XTMdyXTKIo+tGsuA0kd4pxPol+UGeAruNBEhVSDcXfXTh9tVravBqeIuX" "gZIFk9cylR2eDwAAAIB4roDQBfgf8AoSAJAb7y8OVvxt5cT7iqaRMQX2XgtW09Nu9R" "bUIVS7n2mw3iqZG0xnG3iv1oL9gwNXMLlf+gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM" "7b2uADmhirI6dRZUVO+/iMGUvDxa66OI4hDV055pbwQhtxupUatThyDzIg==\n"; static const char torture_dsa_testkey_cert[] = "ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNza" "C5jb20AAAAgKAd9MpIBrzctQyJvCYYJ2WUD5fyWlXMSv1G/3VihbCAAAACBAJTK9U8" "SSfdSdkOPMLNLNIelOW3OvQRz7WbP8kAKMcwEn0L9b8/C8ffKOR+gWGFES+hjsg+fA" "C7ltzHDxOQhKrthE5DjT0+rDA+/LQ3cZSn/6QpLbrwEgn5Uo3nXddF/t4vV7hodQn5" "qX3HUnFOZzpPQYGrWXK74JNRTKHblo0MXAAAAFQCvOI9tBplPs3sI0MLCF7lW+gvzx" "wAAAIBeG4hWwnFRAnmdZBEt/ujdcQZD4RxWYc7MwHXEKweNiekSGFyj6v8cNlIPfWT" "MN4BlTJzPfVaoYvzJev45lEuoSwYLt3AQDM+JcO6XTMdyXTKIo+tGsuA0kd4pxPol+" "UGeAruNBEhVSDcXfXTh9tVravBqeIuXgZIFk9cylR2eDwAAAIB4roDQBfgf8AoSAJA" "b7y8OVvxt5cT7iqaRMQX2XgtW09Nu9RbUIVS7n2mw3iqZG0xnG3iv1oL9gwNXMLlf+" "gLmsqU3788jaEZ9IhZ8VdgHAoHm6UWM7b2uADmhirI6dRZUVO+/iMGUvDxa66OI4hD" "V055pbwQhtxupUatThyDzIgAAAAAAAAAAAAAAAQAAAA5saWJzc2hfdG9ydHVyZQAAA" "AAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5" "nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvc" "nQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXI" "tcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAKKMHL9hp/LTng8sP" "5YHTKaAbC7R003VVTjqOR8DBb4/5RZG2ZW+idp/RiBOuBzTxOOb0pyHSWcM+FGH077" "ZzSjR6dTIDK4ytWehI8mbBqg2fgYZr3CgOiHJJIQSZw1e1PXTK6LwFoWutWfRqQ6gd" "Z2kX28KiUMEkRxdae9Qp39H2SsToQFcdKKYZmBs98d6quD3jmb92JdAB01XUZqpnhC" "w1MXrlzdm4Esm/PNcxIHWihx+aFskspD+LsI5+k+xE7i9jLA3Rtx2Rw4Zy8y5n8zmf" "3DWnTAq4GrjJbkCnOXWBdk0ng2lMcLp/zTzEAVWXRExywDAYJBpoUVJLn5VQyEAAAE" "PAAAAB3NzaC1yc2EAAAEAAt4V9aGqeahOfUvhG7M8/Mn26aLB/HXbICYFJF7dY6urm" "SIoS2KBqISCFGXTituiwGlZeAJ+pVgCMYo07Nxtd6oqIjsgKfJqDNx7e4pGw/YJnkm" "BqMO/k/ygu2mLmQF0lnpmG2KyjKEljMibHaKlFkcVNbwfOb4p8N3OHm66g5mbCUTRZ" "DHqMSJb3YtnObLexD13RydwxkG5AfCnOWxy5O4agXGEYwr/48AQBHYg9obGtpD1qyF" "4mMXgzaLViFtcwah6wHGlW0UPQMvrq/RqigAkyUszSccfibkIXJ+wGAgsRYhVAMwME" "JqPZ6GHOEIjLBKUegsclHb7Pk0YO8Auaw== " "aris@aris-air\n"; /**************************************************************************** * ECDSA KEYS ****************************************************************************/ static const char torture_ecdsa256_private_testkey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MHcCAQEEIBCDeeYYAtX3EnsP0ratwVpNTaA/4K1N6VvHMiUZlVdhoAoGCCqGSM49\n" "AwEHoUQDQgAEx+9ud88Q5GWtLd+yMtYaapC85g+2ZLp7VtFHA0EbNHqBUQxoh+Ik\n" "89Mlr7AUxcFPd+kCo+NE6yq/mNQcL7E6iQ==\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa256_private_testkey_passphrase[] = "-----BEGIN EC PRIVATE KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: AES-128-CBC,5C825E6FE821D0DE99D8403F4B4020CB\n" "\n" "TaUq8Qenb52dKAYcQGIYfdT7Z2DroySk38w51kw/gd8o79ZHaAQv60GtaNoy0203\n" "2X1o29E6c0WsY9DKhSHKm/zzvZmL+ChZYqqh3sd1gp55aJsHNN4axiIu2YCbCavh\n" "8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa256_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhvndbkbElTnAICCAAw\n" "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEOu4ierPcQpcA9RJNHUbTCoEgZBe\n" "iusOkUYp4JZJEIpi98VlqnROzDXHpTTpEGiUDC/k+cuKvoPop5+Jx0qXp+A1NJxu\n" "kx3j+U0ISGY7J6b2Pqt1msC/FzqpeFM7ybuHDRz+c5ZBONTp8wrs52d5NdjrYguz\n" "UO6n9+yydSsO0FqbwPaqNZ6goBN0TfhYnToG4ZPJxlHa7gf7Su4KSMYKZdOtfx4=\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_ecdsa256_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNl\n" "Y2RzYS1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTH7253zxDkZa0t37Iy\n" "1hpqkLzmD7ZkuntW0UcDQRs0eoFRDGiH4iTz0yWvsBTFwU936QKj40TrKr+Y1Bwv\n" "sTqJAAAAmOuDchHrg3IRAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAy\n" "NTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPT\n" "Ja+wFMXBT3fpAqPjROsqv5jUHC+xOokAAAAgEIN55hgC1fcSew/Stq3BWk1NoD/g\n" "rU3pW8cyJRmVV2EAAAAA\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa256_private_openssh_testkey_pasphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABA+\n" "O0w3yPZF2q0FjVBhQjn2AAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAy\n" "NTYAAAAIbmlzdHAyNTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNB\n" "GzR6gVEMaIfiJPPTJa+wFMXBT3fpAqPjROsqv5jUHC+xOokAAACghvb4EX8M06UB\n" "zigxOn9bg5cZkZ2yWY8jzxtOWH4YJXsuhON/jePDJuI2ro5u4iKFD1u2JLfcshdh\n" "vKZyjixU9KdewykQQt/wFkrCfNUyCH8jFiQsAqhBfopRFyDJV9pmcUBL/3fJqwut\n" "ZeBSfA7tXORp3xrwFI1tXiiUCM+/nhxiCsFaCJXeiM3tN+kFtwQ8kamINqwaC8Vj\n" "lFLKHDfwJQ==\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa256_public_testkey[] = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNT" "YAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPTJa+w" "FMXBT3fpAqPjROsqv5jUHC+xOok= aris@kalix86\n"; static const char torture_ecdsa256_testkey_cert[] = "ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzd" "HAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgHvXWcdSrQeZL2/Z68V8ntbL7rDo" "Qwrsc+ps6HbMGZrkAAAAIbmlzdHAyNTYAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPt" "mS6e1bRRwNBGzR6gVEMaIfiJPPTJa+wFMXBT3fpAqPjROsqv5jUHC+xOokAAAAAAAA" "AAAAAAAEAAAAHbXlpZGVudAAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVc" "GVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGl" "uZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0e" "QAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1" "uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEx+9ud88Q5GWtLd+yMtYaapC85g+2ZLp7V" "tFHA0EbNHqBUQxoh+Ik89Mlr7AUxcFPd+kCo+NE6yq/mNQcL7E6iQAAAGQAAAATZWN" "kc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALDSBnmFF59tgTKDQ4meTJEI7/BP2Zgf1" "AKg1H3kIijQAAAAIFYrqSg6GI03ohXqUVsZ3lCB/XIism2aV5Vz2bg1d9zo " "./ec256.pub"; static const char torture_ecdsa384_private_testkey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MIGkAgEBBDBY8jEa5DtRy4AVeTWhPJ/TK257behiC3uafEi6YA2oHORibqX55EDN\n" "wz29MT40mQSgBwYFK4EEACKhZANiAARXc4BN6BrVo1QMi3+i/B85Lu7SMuzBi+1P\n" "bJti8xz+Szgq64gaBGOK9o+WOdLAd/w7p7DJLdztJ0bYoyT4V3B3ZqR9RyGq6mYC\n" "jkXlc5YbYHjueBbp0oeNXqsXHNAWQZo=\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa384_private_testkey_passphrase[] = "-----BEGIN EC PRIVATE KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: AES-128-CBC,5C825E6FE821D0DE99D8403F4B4020CB\n" "\n" "TaUq8Qenb52dKAYcQGIYfdT7Z2DroySk38w51kw/gd8o79ZHaAQv60GtaNoy0203\n" "2X1o29E6c0WsY9DKhSHKm/zzvZmL+ChZYqqh3sd1gp55aJsHNN4axiIu2YCbCavh\n" "8VZn2VJDaitLy8ARqA/lMGQfqHSa3EOqti9FzWG/P6s=\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa384_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIIBHDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIEuMnFkuHkDkCAggA\n" "MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBA/fjhqXxV/Dk7cg8XgPxzuBIHA\n" "TbiloDCPfKKlkm9ZguahtfJOxcVBbMtrFAK2vA/jMXGnbB9Qe13uLl8fTd6QB4tE\n" "Zbyucq4OA0L2HyhuEsJiLvf0ICX8APrBajNv3B8F7ZStrXx7hcJUg8qTlsbdovYq\n" "nCjOKoq/F6ax/r1F9Rr5PlXQDoSKDJ3mQkZc4n8VNKFfXOPQ7C4rEYzglSyzGwyQ\n" "2EwRwnkkJqcYotRyH4JWtXCRak7znLVDeGbavhpP6paSVsK8OpycAoJstfQb0L4q\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_ecdsa384_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNl\n" "Y2RzYS1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRXc4BN6BrVo1QMi3+i\n" "/B85Lu7SMuzBi+1PbJti8xz+Szgq64gaBGOK9o+WOdLAd/w7p7DJLdztJ0bYoyT4\n" "V3B3ZqR9RyGq6mYCjkXlc5YbYHjueBbp0oeNXqsXHNAWQZoAAADIITfDfiE3w34A\n" "AAATZWNkc2Etc2hhMi1uaXN0cDM4NAAAAAhuaXN0cDM4NAAAAGEEV3OATega1aNU\n" "DIt/ovwfOS7u0jLswYvtT2ybYvMc/ks4KuuIGgRjivaPljnSwHf8O6ewyS3c7SdG\n" "2KMk+Fdwd2akfUchqupmAo5F5XOWG2B47ngW6dKHjV6rFxzQFkGaAAAAMFjyMRrk\n" "O1HLgBV5NaE8n9Mrbntt6GILe5p8SLpgDagc5GJupfnkQM3DPb0xPjSZBAAAAAA=\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa384_private_openssh_testkey_passphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB4N\n" "dKGEoxFeg6dqiR2vTl6AAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzOD\n" "QAAAAIbmlzdHAzODQAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5\n" "LOCrriBoEY4r2j5Y50sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIarqZgKOReVzlhtg\n" "eO54FunSh41eqxcc0BZBmgAAANDOL7sWcylFf8SsjGVFvr36mpyUBpAJ/e7o4RbQg\n" "H8FDu1IxscOfbLDoB3CV7UEIgG58nVsDamfL6rXV/tzWnPxYxi6jUHcKT1BugO/Jt\n" "/ncelMeoAS6MAZhElaGKzU1cJMlMTV9ofmuKuAwllQULG7L8lwHs9whBK4JmWPaGL\n" "pU3i9ZoT33/g6pcvA83vicCNqj7ggl6Vb9MeO/zGW1+oV2HC3WiLTqBsYxEJu4YCM\n" "ewfx9pWeWaCllNy/F1rCBu3cxqzcge9hqIlNtpT7Dq3k\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa384_public_testkey[] = "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzOD" "QAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7MGL7U9sm2LzHP5LOCrriBoEY4r2j5Y5" "0sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIarqZgKOReVzlhtgeO54FunSh41eqxcc0B" "ZBmg== aris@kalix86"; static const char torture_ecdsa384_testkey_cert[] = "ecdsa-sha2-nistp384-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzd" "HAzODQtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgvggfi3v98HjOiqVi1O5aPy7JvMd" "rTZe68GZ0qCaAN5MAAAAIbmlzdHAzODQAAABhBFdzgE3oGtWjVAyLf6L8Hzku7tIy7" "MGL7U9sm2LzHP5LOCrriBoEY4r2j5Y50sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIar" "qZgKOReVzlhtgeO54FunSh41eqxcc0BZBmgAAAAAAAAAAAAAAAQAAAAdteWlkZW50A" "AAAAAAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmR" "pbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtc" "G9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXN" "lci1yYwAAAAAAAAAAAAAAiAAAABNlY2RzYS1zaGEyLW5pc3RwMzg0AAAACG5pc3RwM" "zg0AAAAYQRXc4BN6BrVo1QMi3+i/B85Lu7SMuzBi+1PbJti8xz+Szgq64gaBGOK9o+" "WOdLAd/w7p7DJLdztJ0bYoyT4V3B3ZqR9RyGq6mYCjkXlc5YbYHjueBbp0oeNXqsXH" "NAWQZoAAACEAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABpAAAAMQD5f0pF6U6eeBO" "PrOV7Y3w5NuTzvuyDAq0kTv6VYNMp83TYpIJw16+tMAplOSzPTvwAAAAwWD9StvMEP" "b+SDH2G5qqkMk+F5IaHI9fev8zcFzzdOlilLc/+CFM0NKMAFtOrrhv0 " "./ec384.pub"; static const char torture_ecdsa521_private_testkey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MIHbAgEBBEG83nSJ2SLoiBvEku1JteQKWx/Xt6THksgC7rrIaTUmNzk+60f0sCCm\n" "Gll0dgrZLmeIw+TtnG1E20VZflCKq+IdkaAHBgUrgQQAI6GBiQOBhgAEAc6D728d\n" "baQkHnSPtztaRwJw63CBl15cykB4SXXuwWdNOtPzBijUULMTTvBXbra8gL4ATd9d\n" "Qnuwn8KQUh2T/z+BARjWPKhcHcGx57XpXCEkawzMYaHUUnRdeFEmNRsbXypsf0mJ\n" "KATU3h8gzTMkbrx8DJTFHEIjXBShs44HsSYVl3Xy\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa521_private_testkey_passphrase[] = "-----BEGIN EC PRIVATE KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: AES-128-CBC,24C4F383915BC07D9C63209BF6AD3DEE\n" "\n" "M+JGfpGfoH3Wn6XWSoHrGGevaS6p2vJGQdkFEIgUfh16s+U/LcRhAhRnhX/MV6Ds\n" "OZTpusrjInlZXNUR97fJbmjr/600qUlh4y3U9ikiX3IXE+RI80TPNdishOOjKRF7\n" "aWDW8UxTlFfU2Zc1Ew0pTvMXXcuTpozW1NNVY+6S9uWfHwq1/EcR35dbnEmG0gId\n" "qsiEdVKh7p+9Qto8jcVWzMh7ANMcIwmxQ4zbvnqypwgAgpMbamWqBZ9q4egsVZKd\n" "uRzL95L05ctOBGYNYqpPNIX3UdQU07kzwNC+yaHOb2s=\n" "-----END EC PRIVATE KEY-----\n"; static const char torture_ecdsa521_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIIBXTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIY6X14D05Q7gCAggA\n" "MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBCmngDUX2/kg+45m4qoCBLiBIIB\n" "ANHV+GC6Hnend9cVScT5oNtOS2a/TD82N1h+9cYmxn953IRNk2rF7LFYFFeZzcZi\n" "e840YFYFRiTScm1GbKgwyFLYzYguvpUpS3qz3yZMygoX3xlvFw0l8FWsfeUmOzG1\n" "uQQPGeoFCus43D3k1iQCOafEe0DPbyfcF/IxajZ+P0N8A5ikgPsOfpTLAdWiYgFt\n" "wkafVfXx5ZH1u8S34+kmoKRhf5zBFQI1BHD6bCQDANPBkbP4KEjH5mHRO99nHK9r\n" "EhdLDBEXRo9xb1BhgPLdQA0AdPPqZ6Wugy3KyxkEiH/GB/oBoIpg0oALnowL129g\n" "BV6jZHwXHuO4/CLJ9rN2tdE=\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_ecdsa521_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNl\n" "Y2RzYS1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBzoPvbx1tpCQedI+3\n" "O1pHAnDrcIGXXlzKQHhJde7BZ0060/MGKNRQsxNO8FdutryAvgBN311Ce7CfwpBS\n" "HZP/P4EBGNY8qFwdwbHntelcISRrDMxhodRSdF14USY1GxtfKmx/SYkoBNTeHyDN\n" "MyRuvHwMlMUcQiNcFKGzjgexJhWXdfIAAAEAt6sYz7erGM8AAAATZWNkc2Etc2hh\n" "Mi1uaXN0cDUyMQAAAAhuaXN0cDUyMQAAAIUEAc6D728dbaQkHnSPtztaRwJw63CB\n" "l15cykB4SXXuwWdNOtPzBijUULMTTvBXbra8gL4ATd9dQnuwn8KQUh2T/z+BARjW\n" "PKhcHcGx57XpXCEkawzMYaHUUnRdeFEmNRsbXypsf0mJKATU3h8gzTMkbrx8DJTF\n" "HEIjXBShs44HsSYVl3XyAAAAQgC83nSJ2SLoiBvEku1JteQKWx/Xt6THksgC7rrI\n" "aTUmNzk+60f0sCCmGll0dgrZLmeIw+TtnG1E20VZflCKq+IdkQAAAAABAg==\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa521_private_openssh_testkey_passphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAj\n" "9WBFa/piJcPFEE4CGZTKAAAAEAAAAAEAAACsAAAAE2VjZHNhLXNoYTItbmlzdHA1\n" "MjEAAAAIbmlzdHA1MjEAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl1\n" "7sFnTTrT8wYo1FCzE07wV262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee1\n" "6VwhJGsMzGGh1FJ0XXhRJjUbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOO\n" "B7EmFZd18gAAAQDLjaKp+DLEHFb98f5WnVFg6LgDN847sfeuPZVfVjeSAiIv016O\n" "ld7DXb137B2xYVsuce6sHbypr10dJOvgMTLdzTl+crYNJL+8UufJP0rOIFaDenzQ\n" "RW8wydwiQxwt1ZqtD8ASqFmadxngufJKZzPLGfjCbCz3uATKa2sXN66nRXRZJbVA\n" "IlNYDY8ivAStNhfItUMqyM6PkYlKJECtJw7w7TYKpvts7t72JmtgqVjS45JI/YZ+\n" "kitIG0YmG8rzL9d1vBB5m+MH/fnFz2uJqbQYCH9Ctc8HZodAVoTNDzXHU2mYF9PE\n" "Z6+gi3jd+kOyUk3NifHcre9K6ie7LL33JayM\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ecdsa521_public_testkey[] = "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1Mj" "EAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwgZdeXMpAeEl17sFnTTrT8wYo1FCzE07w" "V262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee16VwhJGsMzGGh1FJ0XXhRJj" "UbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOOB7EmFZd18g== aris@kalix86"; static const char torture_ecdsa521_testkey_cert[] = "ecdsa-sha2-nistp521-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzd" "HA1MjEtY2VydC12MDFAb3BlbnNzaC5jb20AAAAggFIwlsx63C++kmCBDF4O14fvu5j" "Icsm8uMbMp0smOVwAAAAIbmlzdHA1MjEAAACFBAHOg+9vHW2kJB50j7c7WkcCcOtwg" "ZdeXMpAeEl17sFnTTrT8wYo1FCzE07wV262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jy" "oXB3Bsee16VwhJGsMzGGh1FJ0XXhRJjUbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI" "1wUobOOB7EmFZd18gAAAAAAAAAAAAAAAQAAAAdteWlkZW50AAAAAAAAAAAAAAAA///" "///////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blc" "m1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5" "nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAA" "AAArAAAABNlY2RzYS1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBzoPvbx1" "tpCQedI+3O1pHAnDrcIGXXlzKQHhJde7BZ0060/MGKNRQsxNO8FdutryAvgBN311Ce" "7CfwpBSHZP/P4EBGNY8qFwdwbHntelcISRrDMxhodRSdF14USY1GxtfKmx/SYkoBNT" "eHyDNMyRuvHwMlMUcQiNcFKGzjgexJhWXdfIAAACnAAAAE2VjZHNhLXNoYTItbmlzd" "HA1MjEAAACMAAAAQgCJzTxw/hz2qE8Qkd4XW9Qn7fPxML6Ebtttg9C18AguyGyE6Nk" "YH1NcToYxwQxrgzDXowXYm9eCbq9JEvaXDEtIfAAAAEIBk06LmKAYR2HDwwt4f5wVI" "PKJ0pHVLZEx3FMZI3SfwS9mVm+oojLkZ2hr8X0xn28zbN045d8daB7BB1mHMGNT+YA" "= ./ec521.pub"; /**************************************************************************** * ED25519 KEYS ****************************************************************************/ static const char torture_ed25519_private_pkcs8_testkey[] = "-----BEGIN PRIVATE KEY-----\n" "MC4CAQAwBQYDK2VwBCIEIGBhcqLe61tkqVjIHKEzwB3oINasSHWGbIWXQWcLPmGN\n" "-----END PRIVATE KEY-----\n"; static const char torture_ed25519_private_openssh_testkey[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n" "QyNTUxOQAAACAVlp8bgmIjsrzGC7ZIKBMhCpS1fpJTPgVOjYdz5gIqlwAAAJBzsDN1c7Az\n" "dQAAAAtzc2gtZWQyNTUxOQAAACAVlp8bgmIjsrzGC7ZIKBMhCpS1fpJTPgVOjYdz5gIqlw\n" "AAAEBgYXKi3utbZKlYyByhM8Ad6CDWrEh1hmyFl0FnCz5hjRWWnxuCYiOyvMYLtkgoEyEK\n" "lLV+klM+BU6Nh3PmAiqXAAAADGFyaXNAa2FsaXg4NgE=\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ed25519_private_openssh_testkey_passphrase[] = "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAACmFlczEyOC1jYmMAAAAGYmNyeXB0AAAAGAAAABDYuz+a8i\n" "nb/BgGjQjQtvkUAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIBWWnxuCYiOyvMYL\n" "tkgoEyEKlLV+klM+BU6Nh3PmAiqXAAAAkOBxqvzvPSns3TbhjkCayvANI66100OELnpDOm\n" "JBGgXr5q846NkAovH3pmJ4O7qzPLTQ/cm0+959VUODRhM1i96qBg5MTNtV33lf5Y57Klzu\n" "JegbiexcqkHIzriH42K0XSOEpfW8f/rTH7ffjbE/7l8HRNwf7AmcnxLx/d8J8FTBr+8aU7\n" "qMU3xAJ4ixnwhYFg==\n" "-----END OPENSSH PRIVATE KEY-----\n"; static const char torture_ed25519_private_pkcs8_testkey_passphrase[] = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAie1RBk/ub+EwICCAAw\n" "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEECRLkPChQx/sZPYLdNJhxMUEQFLj\n" "7nelAdOx3WXIBbCOfOqg3aAn8C5cXPtIQ+fiui1V8wlXXV8RBiuDCC97ScLs91D5\n" "qQhQtw0vgfnq1um/izg=\n" "-----END ENCRYPTED PRIVATE KEY-----\n"; static const char torture_ed25519_public_testkey[] = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBWWnxuCYiOyvMYLtkgoEyEKlLV+klM+" "BU6Nh3PmAiqX aris@kalix86"; static const char torture_ed25519_testkey_cert[] = "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQ" "G9wZW5zc2guY29tAAAAILrR4sPB+b6BRId/OkQha9nWwoACXqUTILz1TrmG4R9CAAA" "AIBWWnxuCYiOyvMYLtkgoEyEKlLV+klM+BU6Nh3PmAiqXAAAAAAAAAAAAAAABAAAAB" "215aWRlbnQAAAAAAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTE" "tZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAF" "nBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnB" "lcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIBWWnxuCY" "iOyvMYLtkgoEyEKlLV+klM+BU6Nh3PmAiqXAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB" "d8AogGWM6njfejbazFVyfnjNiWqatx6IV3Nnqc3LjCiPY19fqIPe2YJSzytHwLTD5X" "IjD2bJpq2ZfjQwXpO0J ./ed.pub"; static const char *torture_get_testkey_internal(enum ssh_keytypes_e type, bool with_passphrase, int pubkey, int format) { switch (type) { case SSH_KEYTYPE_DSS: if (pubkey) { return torture_dsa_public_testkey; } else if (with_passphrase) { if (format == 1) { return torture_dsa_private_openssh_testkey_passphrase; } if (format == 2) { return torture_dsa_private_pkcs8_testkey_passphrase; } else { return torture_dsa_private_testkey_passphrase; } } if (format == 1) { return torture_dsa_private_openssh_testkey; } return torture_dsa_private_testkey; case SSH_KEYTYPE_RSA: if (pubkey) { return torture_rsa_public_testkey; } else if (with_passphrase) { if (format == 1) { return torture_rsa_private_openssh_testkey_passphrase; } if (format == 2) { return torture_rsa_private_pkcs8_testkey_passphrase; } else { return torture_rsa_private_testkey_passphrase; } } if (format == 1) { return torture_rsa_private_openssh_testkey; } return torture_rsa_private_testkey; case SSH_KEYTYPE_ECDSA_P521: if (pubkey) { return torture_ecdsa521_public_testkey; } else if (with_passphrase) { if (format == 1) { return torture_ecdsa521_private_openssh_testkey_passphrase; } if (format == 2) { return torture_ecdsa521_private_pkcs8_testkey_passphrase; } else { return torture_ecdsa521_private_testkey_passphrase; } } if (format == 1) { return torture_ecdsa521_private_openssh_testkey; } return torture_ecdsa521_private_testkey; case SSH_KEYTYPE_ECDSA_P384: if (pubkey) { return torture_ecdsa384_public_testkey; } else if (with_passphrase){ if (format == 1) { return torture_ecdsa384_private_openssh_testkey_passphrase; } if (format == 2) { return torture_ecdsa384_private_pkcs8_testkey_passphrase; } else { return torture_ecdsa384_private_testkey_passphrase; } } if (format == 1) { return torture_ecdsa384_private_openssh_testkey; } return torture_ecdsa384_private_testkey; case SSH_KEYTYPE_ECDSA_P256: if (pubkey) { return torture_ecdsa256_public_testkey; } else if (with_passphrase){ if (format == 1) { return torture_ecdsa256_private_openssh_testkey_pasphrase; } if (format == 2) { return torture_ecdsa256_private_pkcs8_testkey_passphrase; } else { return torture_ecdsa256_private_testkey_passphrase; } } if (format == 1) { return torture_ecdsa256_private_openssh_testkey; } return torture_ecdsa256_private_testkey; case SSH_KEYTYPE_ED25519: if (pubkey) { return torture_ed25519_public_testkey; } else if (with_passphrase) { if (format == 1) { return torture_ed25519_private_openssh_testkey_passphrase; } if (format == 2) { return torture_ed25519_private_pkcs8_testkey_passphrase; } /* ed25519 keys are not available in legacy PEM format */ return NULL; } if (format == 1) { return torture_ed25519_private_openssh_testkey; } /* ed25519 keys are not available in legacy PEM format */ return torture_ed25519_private_pkcs8_testkey; case SSH_KEYTYPE_DSS_CERT01: return torture_dsa_testkey_cert; case SSH_KEYTYPE_RSA_CERT01: return torture_rsa_testkey_cert; case SSH_KEYTYPE_ECDSA_P256_CERT01: return torture_ecdsa256_testkey_cert; case SSH_KEYTYPE_ECDSA_P384_CERT01: return torture_ecdsa384_testkey_cert; case SSH_KEYTYPE_ECDSA_P521_CERT01: return torture_ecdsa521_testkey_cert; case SSH_KEYTYPE_ED25519_CERT01: return torture_ed25519_testkey_cert; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: return NULL; } return NULL; } /* Return the encrypted private key in a new OpenSSH format */ const char *torture_get_openssh_testkey(enum ssh_keytypes_e type, bool with_passphrase) { return torture_get_testkey_internal(type, with_passphrase, 0, 1); } /* Return the private key in PEM format */ const char *torture_get_testkey(enum ssh_keytypes_e type, bool with_passphrase) { #if defined(HAVE_LIBCRYPTO) return torture_get_testkey_internal(type, with_passphrase, 0, 2); #else return torture_get_testkey_internal(type, with_passphrase, 0, 0); #endif } const char *torture_get_testkey_pub(enum ssh_keytypes_e type) { return torture_get_testkey_internal(type, 0, 1, 0); } const char *torture_get_testkey_passphrase(void) { return TORTURE_TESTKEY_PASSWORD; } ================================================ FILE: src/libssh/tests/torture_key.h ================================================ /* * torture_key.h - torture library for testing libssh * * This file is part of the SSH Library * * Copyright (c) 2008-2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #ifndef _TORTURE_KEY_H #define _TORTURE_KEY_H #include #define TORTURE_TESTKEY_PASSWORD "libssh-rocks" /* Return the encrypted private key in a new OpenSSH format */ const char *torture_get_openssh_testkey(enum ssh_keytypes_e type, bool with_passphrase); /* Return the private key in the legacy PEM format */ const char *torture_get_testkey(enum ssh_keytypes_e type, bool with_passphrase); const char *torture_get_testkey_passphrase(void); const char *torture_get_testkey_pub(enum ssh_keytypes_e type); #endif /* _TORTURE_KEY_H */ ================================================ FILE: src/libssh/tests/torture_pki.c ================================================ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #elif (defined _WIN32) || (defined _WIN64) #include #define read _read #define open _open #define write _write #define close _close #endif #include "torture_pki.h" char *torture_pki_read_file(const char *filename) { char *key; int fd; int size; int rc; struct stat sb; if (filename == NULL || filename[0] == '\0') { return NULL; } fd = open(filename, O_RDONLY); if (fd < 0) { return NULL; } rc = fstat(fd, &sb); if (rc != 0) { close(fd); return NULL; } key = malloc(sb.st_size + 1); if (key == NULL) { close(fd); return NULL; } size = read(fd, key, sb.st_size); close(fd); if (size != sb.st_size) { free(key); return NULL; } key[size] = '\0'; return key; } int torture_read_one_line(const char *filename, char *buffer, size_t len) { FILE *fp; size_t nmemb; fp = fopen(filename, "r"); if (fp == NULL) { return -1; } nmemb = fread(buffer, len - 2, 1, fp); if (nmemb != 0 || ferror(fp)) { fclose(fp); return -1; } buffer[len - 1] = '\0'; fclose(fp); return 0; } /** * @internal * * Returns the character len of a public key string, omitting the comment part */ size_t torture_pubkey_len(const char *pubkey) { const char *ptr; ptr = strchr(pubkey, ' '); if (ptr != NULL) { ptr = strchr(ptr + 1, ' '); if (ptr != NULL) { return ptr - pubkey; } } return 0; } ================================================ FILE: src/libssh/tests/torture_pki.h ================================================ char *torture_pki_read_file(const char *filename); int torture_read_one_line(const char *filename, char *buffer, size_t len); size_t torture_pubkey_len(const char *pubkey); ================================================ FILE: src/libssh/tests/unittests/CMakeLists.txt ================================================ project(unittests C) include_directories(${OPENSSL_INCLUDE_DIR}) set(LIBSSH_UNIT_TESTS torture_buffer torture_bytearray torture_callbacks torture_crypto torture_init torture_list torture_misc torture_config torture_options torture_isipaddr torture_knownhosts_parsing torture_hashes torture_packet_filter torture_temp_dir torture_temp_file torture_push_pop_dir torture_session_keys torture_tokens ) set(LIBSSH_THREAD_UNIT_TESTS torture_rand torture_threads_init torture_threads_buffer torture_threads_crypto ) if (UNIX AND NOT WIN32) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} # this uses a socketpair torture_packet # requires ssh-keygen torture_keyfiles torture_pki torture_pki_rsa torture_pki_ed25519 # requires /dev/null torture_channel ) if (WITH_SERVER) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} torture_bind_config) if (WITH_GEX) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} torture_moduli) endif() endif() if (HAVE_DSA) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} torture_pki_dsa ) endif() if (HAVE_ECC) set(LIBSSH_UNIT_TESTS ${LIBSSH_UNIT_TESTS} torture_pki_ecdsa ) endif() set(LIBSSH_THREAD_UNIT_TESTS ${LIBSSH_THREAD_UNIT_TESTS} # requires pthread torture_threads_pki_rsa ) # Not working correctly #if (WITH_SERVER) # add_cmocka_test(torture_server_x11 torture_server_x11.c ${TEST_TARGET_LIBRARIES}) #endif (WITH_SERVER) endif (UNIX AND NOT WIN32) foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS}) add_cmocka_test(${_UNIT_TEST} SOURCES ${_UNIT_TEST}.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TEST_TARGET_LIBRARIES} ) endforeach() if (CMAKE_USE_PTHREADS_INIT) foreach(_UNIT_TEST ${LIBSSH_THREAD_UNIT_TESTS}) add_cmocka_test(${_UNIT_TEST} SOURCES ${_UNIT_TEST}.c COMPILE_OPTIONS ${DEFAULT_C_COMPILE_FLAGS} LINK_LIBRARIES ${TEST_TARGET_LIBRARIES} Threads::Threads ) endforeach() endif () ================================================ FILE: src/libssh/tests/unittests/torture_bind_config.c ================================================ /* * torture_bind_config.c - Tests for server side configuration * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include #include extern LIBSSH_THREAD int ssh_log_level; #define LOGLEVEL "verbose" #define LOGLEVEL2 "fatal" #define LOGLEVEL3 "DEBUG1" #define LOGLEVEL4 "DEBUG2" #define LISTEN_ADDRESS "::1" #define LISTEN_ADDRESS2 "::2" #define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1" #define KEXALGORITHMS2 "ecdh-sha2-nistp521" #define CIPHERS "aes128-ctr,aes192-ctr,aes256-ctr" #define CIPHERS2 "aes256-ctr" #define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa" #define HOSTKEYALGORITHMS_UNKNOWN "ssh-ed25519,ecdsa-sha2-nistp521,unknown,ssh-rsa" #define HOSTKEYALGORITHMS2 "rsa-sha2-256" #define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521" #define PUBKEYACCEPTEDTYPES_UNKNOWN "rsa-sha2-512,ssh-rsa,unknown,ecdsa-sha2-nistp521" #define PUBKEYACCEPTEDTYPES2 "rsa-sha2-256,ssh-rsa" #define MACS "hmac-sha1,hmac-sha2-256,hmac-sha2-512,hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com" #define MACS2 "hmac-sha1" #ifdef HAVE_DSA #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" #endif #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519" #ifdef HAVE_ECC #define LIBSSH_ECDSA_521_TESTKEY "libssh_testkey.id_ecdsa521" #endif #define LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS "libssh_test_bind_config_listenaddress" #define LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS2 "libssh_test_bind_config_listenaddress2" #define LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE "libssh_test_bind_config_listenaddress_twice" #define LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE_REC "libssh_test_bind_config_listenaddress_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_PORT "libssh_test_bind_config_port" #define LIBSSH_TEST_BIND_CONFIG_PORT2 "libssh_test_bind_config_port2" #define LIBSSH_TEST_BIND_CONFIG_PORT_TWICE "libssh_test_bind_config_port_twice" #define LIBSSH_TEST_BIND_CONFIG_PORT_TWICE_REC "libssh_test_bind_config_port_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY "libssh_test_bind_config_hostkey" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY2 "libssh_test_bind_config_hostkey2" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE "libssh_test_bind_config_hostkey_twice" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE_REC "libssh_test_bind_config_hostkey_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_LOGLEVEL "libssh_test_bind_config_loglevel" #define LIBSSH_TEST_BIND_CONFIG_LOGLEVEL2 "libssh_test_bind_config_loglevel2" #define LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE "libssh_test_bind_config_loglevel_twice" #define LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE_REC "libssh_test_bind_config_loglevel_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_CIPHERS "libssh_test_bind_config_ciphers" #define LIBSSH_TEST_BIND_CONFIG_CIPHERS2 "libssh_test_bind_config_ciphers2" #define LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE "libssh_test_bind_config_ciphers_twice" #define LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE_REC "libssh_test_bind_config_ciphers_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_MACS "libssh_test_bind_config_macs" #define LIBSSH_TEST_BIND_CONFIG_MACS2 "libssh_test_bind_config_macs2" #define LIBSSH_TEST_BIND_CONFIG_MACS_TWICE "libssh_test_bind_config_macs_twice" #define LIBSSH_TEST_BIND_CONFIG_MACS_TWICE_REC "libssh_test_bind_config_macs_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS "libssh_test_bind_config_kexalgorithms" #define LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS2 "libssh_test_bind_config_kexalgorithms2" #define LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE "libssh_test_bind_config_kexalgorithms_twice" #define LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE_REC "libssh_test_bind_config_kexalgorithms_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_FULL "libssh_test_bind_config_full" #define LIBSSH_TEST_BIND_CONFIG_INCLUDE "libssh_test_bind_config_include" #define LIBSSH_TEST_BIND_CONFIG_INCLUDE_RECURSIVE "libssh_test_bind_config_include_recursive" #define LIBSSH_TEST_BIND_CONFIG_CORNER_CASES "libssh_test_bind_config_corner_cases" #define LIBSSH_TEST_BIND_CONFIG_MATCH_ALL "libssh_test_bind_config_match_all" #define LIBSSH_TEST_BIND_CONFIG_MATCH_TWICE "libssh_test_bind_config_match_twice" #define LIBSSH_TEST_BIND_CONFIG_MATCH_UNSUPPORTED "libssh_test_bind_config_match_unsupported" #define LIBSSH_TEST_BIND_CONFIG_MATCH_NOT_ALLOWED "libssh_test_bind_config_match_not_allowed" #define LIBSSH_TEST_BIND_CONFIG_MATCH_CORNER_CASES "libssh_test_bind_config_match_corner_cases" #define LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID "libssh_test_bind_config_match_invalid" #define LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID2 "libssh_test_bind_config_match_invalid2" #define LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED "libssh_test_bind_config_pubkey" #define LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED2 "libssh_test_bind_config_pubkey2" #define LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE "libssh_test_bind_config_pubkey_twice" #define LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE_REC "libssh_test_bind_config_pubkey_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_UNKNOWN "libssh_test_bind_config_pubkey_unknown" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS "libssh_test_bind_config_hostkey_alg" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS2 "libssh_test_bind_config_hostkey_alg2" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE "libssh_test_bind_config_hostkey_alg_twice" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE_REC "libssh_test_bind_config_hostkey_alg_twice_rec" #define LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_UNKNOWN "libssh_test_bind_config_hostkey_alg_unknown" const char template[] = "temp_dir_XXXXXX"; struct bind_st { char *cwd; char *temp_dir; ssh_bind bind; }; static int setup_config_files(void **state) { struct bind_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct bind_st *)malloc(sizeof(struct bind_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); /* For ed25519 the test keys are not available in legacy PEM format. Using * the new OpenSSH format for all algorithms */ torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_ED25519_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); #ifdef HAVE_ECC torture_write_file(LIBSSH_ECDSA_521_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); #endif #ifdef HAVE_DSA torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0)); #endif torture_write_file(LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS, "ListenAddress "LISTEN_ADDRESS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS2, "ListenAddress "LISTEN_ADDRESS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE, "ListenAddress "LISTEN_ADDRESS"\n" "ListenAddress "LISTEN_ADDRESS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE_REC, "ListenAddress "LISTEN_ADDRESS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PORT, "Port 123\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PORT2, "Port 456\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PORT_TWICE, "Port 123\n" "Port 456\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PORT_TWICE_REC, "Port 123\n" "Include "LIBSSH_TEST_BIND_CONFIG_PORT2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY, "HostKey "LIBSSH_ECDSA_521_TESTKEY"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY2, "HostKey "LIBSSH_RSA_TESTKEY"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE, "HostKey "LIBSSH_ECDSA_521_TESTKEY"\n" "HostKey "LIBSSH_RSA_TESTKEY"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE_REC, "HostKey "LIBSSH_ECDSA_521_TESTKEY"\n" "Include "LIBSSH_TEST_BIND_CONFIG_HOSTKEY2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LOGLEVEL, "LogLevel "LOGLEVEL"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LOGLEVEL2, "LogLevel "LOGLEVEL2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE, "LogLevel "LOGLEVEL"\n" "LogLevel "LOGLEVEL2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE_REC, "LogLevel "LOGLEVEL"\n" "Include "LIBSSH_TEST_BIND_CONFIG_LOGLEVEL2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_CIPHERS, "Ciphers "CIPHERS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_CIPHERS2, "Ciphers "CIPHERS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE, "Ciphers "CIPHERS"\n" "Ciphers "CIPHERS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE_REC, "Ciphers "CIPHERS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_CIPHERS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MACS, "MACs "MACS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MACS2, "MACs "MACS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MACS_TWICE, "MACs "MACS"\n" "MACs "MACS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MACS_TWICE_REC, "MACs "MACS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_MACS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS, "KexAlgorithms "KEXALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS2, "KexAlgorithms "KEXALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE, "KexAlgorithms "KEXALGORITHMS"\n" "KexAlgorithms "KEXALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE_REC, "KexAlgorithms "KEXALGORITHMS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_FULL, "ListenAddress "LISTEN_ADDRESS"\n" "Port 123\n" "HostKey "LIBSSH_ECDSA_521_TESTKEY"\n" "LogLevel "LOGLEVEL"\n" "Ciphers "CIPHERS"\n" "MACs "MACS"\n" "KexAlgorithms "KEXALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_INCLUDE, "Include "LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_PORT"\n" "Include "LIBSSH_TEST_BIND_CONFIG_HOSTKEY"\n" "Include "LIBSSH_TEST_BIND_CONFIG_LOGLEVEL"\n" "Include "LIBSSH_TEST_BIND_CONFIG_CIPHERS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_MACS"\n" "Include "LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_INCLUDE_RECURSIVE, "Include "LIBSSH_TEST_BIND_CONFIG_INCLUDE"\n"); /* Unsupported options and corner cases */ torture_write_file(LIBSSH_TEST_BIND_CONFIG_CORNER_CASES, "\n" /* empty line */ "# comment line\n" " # comment line not starting with hash\n" "UnknownConfigurationOption yes\n" "Ciphers "CIPHERS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_ALL, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match All\n" "\tLogLevel "LOGLEVEL2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_TWICE, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match All\n" "\tLogLevel "LOGLEVEL2"\n" "Match All\n" "\tLogLevel "LOGLEVEL3"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_UNSUPPORTED, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match User alice\n" "\tLogLevel "LOGLEVEL2"\n" "Match Group sftp_users\n" "\tLogLevel "LOGLEVEL2"\n" "Match Host 192.168.0.*\n" "\tLogLevel "LOGLEVEL2"\n" "Match LocalAddress 172.30.1.5\n" "\tLogLevel "LOGLEVEL2"\n" "Match LocalPort 42\n" "\tLogLevel "LOGLEVEL2"\n" "Match Rdomain 4\n" "\tLogLevel "LOGLEVEL2"\n" "Match Address 10.0.0.10\n" "\tLogLevel "LOGLEVEL2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_NOT_ALLOWED, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match All\n" "\tListenAddress "LISTEN_ADDRESS2"\n" "\tPort 456\n" "\tHostKey "LIBSSH_RSA_TESTKEY"\n" "\tCiphers "CIPHERS2"\n" "\tMACs "MACS2"\n" "\tKexAlgorithms "KEXALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_CORNER_CASES, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match User alice\n" "\tLogLevel "LOGLEVEL2"\n" "Match All\n" "\tLogLevel "LOGLEVEL3"\n" "Match All\n" "\tLogLevel "LOGLEVEL"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match User alice All\n" "\tLogLevel "LOGLEVEL2"\n" "Match All\n" "\tLogLevel "LOGLEVEL3"\n" "Match All\n" "\tLogLevel "LOGLEVEL4"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID2, "Include "LIBSSH_TEST_BIND_CONFIG_FULL"\n" "Match All User alice\n" "\tLogLevel "LOGLEVEL2"\n" "Match All\n" "\tLogLevel "LOGLEVEL3"\n" "Match All\n" "\tLogLevel "LOGLEVEL4"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED2, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n" "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE_REC, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES2"\n" "Include "LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_UNKNOWN, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES_UNKNOWN"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS, "HostKeyAlgorithms "HOSTKEYALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS2, "HostKeyAlgorithms "HOSTKEYALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE, "HostKeyAlgorithms "HOSTKEYALGORITHMS"\n" "HostKeyAlgorithms "HOSTKEYALGORITHMS2"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE_REC, "HostKeyAlgorithms "HOSTKEYALGORITHMS2"\n" "Include "LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS"\n"); torture_write_file(LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_UNKNOWN, "HostKeyAlgorithms "HOSTKEYALGORITHMS_UNKNOWN"\n"); return 0; } static int sshbind_setup(void **state) { int rc; struct bind_st *test_state = NULL; rc = setup_config_files((void **)&test_state); assert_int_equal(rc, 0); assert_non_null(test_state); test_state->bind = ssh_bind_new(); assert_non_null(test_state->bind); *state = test_state; return 0; } static int sshbind_teardown(void **state) { struct bind_st *test_state = NULL; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); assert_non_null(test_state->bind); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); ssh_bind_free(test_state->bind); SAFE_FREE(test_state); return 0; } static void torture_bind_config_listen_address(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS); assert_int_equal(rc, 0); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, LISTEN_ADDRESS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, LISTEN_ADDRESS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, LISTEN_ADDRESS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LISTENADDRESS2); assert_int_equal(rc, 0); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, LISTEN_ADDRESS2); } static void torture_bind_config_port(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PORT); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 123); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PORT_TWICE); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 123); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PORT_TWICE_REC); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 123); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PORT2); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 456); } static void torture_bind_config_hostkey(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); assert_non_null(bind->rsakey); assert_string_equal(bind->rsakey, LIBSSH_RSA_TESTKEY); } static void torture_bind_config_hostkey_twice_rec(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); assert_non_null(bind->rsakey); assert_string_equal(bind->rsakey, LIBSSH_RSA_TESTKEY); } static void torture_bind_config_hostkey_separately(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY2); assert_int_equal(rc, 0); assert_non_null(bind->rsakey); assert_string_equal(bind->rsakey, LIBSSH_RSA_TESTKEY); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); } static void torture_bind_config_loglevel(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level, new_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LOGLEVEL); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 2); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 2); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LOGLEVEL_TWICE_REC); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 2); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_LOGLEVEL2); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 1); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_ciphers(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; char *fips_ciphers = NULL; char *fips_ciphers2 = NULL; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; if (ssh_fips_mode()) { fips_ciphers = ssh_keep_fips_algos(SSH_CRYPT_C_S, CIPHERS); assert_non_null(fips_ciphers); fips_ciphers2 = ssh_keep_fips_algos(SSH_CRYPT_C_S, CIPHERS2); assert_non_null(fips_ciphers2); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_CIPHERS); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], fips_ciphers); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], fips_ciphers); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_CIPHERS_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], fips_ciphers); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_CIPHERS2); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], fips_ciphers2); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], fips_ciphers2); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS2); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS2); } SAFE_FREE(fips_ciphers); SAFE_FREE(fips_ciphers2); } static void torture_bind_config_macs(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MACS); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], MACS); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], MACS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MACS_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], MACS); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], MACS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MACS_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], MACS); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], MACS); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MACS2); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], MACS2); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], MACS2); } static void torture_bind_config_kexalgorithms(void **state) { struct bind_st *test_state; ssh_bind bind; char *fips_kex = NULL; char *fips_kex2 = NULL; int rc; if (ssh_fips_mode()) { fips_kex = ssh_keep_fips_algos(SSH_KEX, KEXALGORITHMS); assert_non_null(fips_kex); fips_kex2 = ssh_keep_fips_algos(SSH_KEX, KEXALGORITHMS2); assert_non_null(fips_kex2); } assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], fips_kex); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], KEXALGORITHMS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], fips_kex); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], KEXALGORITHMS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], fips_kex); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], KEXALGORITHMS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_KEXALGORITHMS2); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], fips_kex2); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], KEXALGORITHMS2); } SAFE_FREE(fips_kex); SAFE_FREE(fips_kex2); } static void torture_bind_config_pubkey_accepted(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; char *fips_pubkeys = NULL; char *fips_pubkeys2 = NULL; if (ssh_fips_mode()) { fips_pubkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, PUBKEYACCEPTEDTYPES); assert_non_null(fips_pubkeys); fips_pubkeys2 = ssh_keep_fips_algos(SSH_HOSTKEYS, PUBKEYACCEPTEDTYPES2); assert_non_null(fips_pubkeys2); } assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, fips_pubkeys); } else { assert_string_equal(bind->pubkey_accepted_key_types, PUBKEYACCEPTEDTYPES); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED2); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, fips_pubkeys2); } else { assert_string_equal(bind->pubkey_accepted_key_types, PUBKEYACCEPTEDTYPES2); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, fips_pubkeys); } else { assert_string_equal(bind->pubkey_accepted_key_types, PUBKEYACCEPTEDTYPES); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, fips_pubkeys2); } else { assert_string_equal(bind->pubkey_accepted_key_types, PUBKEYACCEPTEDTYPES2); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_PUBKEY_ACCEPTED_UNKNOWN); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, fips_pubkeys); } else { assert_string_equal(bind->pubkey_accepted_key_types, PUBKEYACCEPTEDTYPES); } SAFE_FREE(fips_pubkeys); SAFE_FREE(fips_pubkeys2); } static void torture_bind_config_hostkey_algorithms(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; char *fips_hostkeys = NULL; char *fips_hostkeys2 = NULL; if (ssh_fips_mode()) { fips_hostkeys = ssh_keep_fips_algos(SSH_HOSTKEYS, HOSTKEYALGORITHMS); assert_non_null(fips_hostkeys); fips_hostkeys2 = ssh_keep_fips_algos(SSH_HOSTKEYS, HOSTKEYALGORITHMS2); assert_non_null(fips_hostkeys2); } assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], fips_hostkeys); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS2); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], fips_hostkeys2); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS2); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], fips_hostkeys); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_TWICE_REC); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], fips_hostkeys2); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS2); } rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_HOSTKEY_ALGORITHMS_UNKNOWN); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], fips_hostkeys); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS); } SAFE_FREE(fips_hostkeys); SAFE_FREE(fips_hostkeys2); } static int assert_full_bind_config(void **state) { struct bind_st *test_state; ssh_bind bind; int new_level; char *fips_ciphers = NULL; char *fips_kex = NULL; if (ssh_fips_mode()) { fips_ciphers = ssh_keep_fips_algos(SSH_CRYPT_C_S, CIPHERS); assert_non_null(fips_ciphers); fips_kex = ssh_keep_fips_algos(SSH_KEX, KEXALGORITHMS); assert_non_null(fips_kex); } assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; new_level = ssh_get_log_level(); assert_int_equal(new_level, 2); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, LISTEN_ADDRESS); assert_int_equal(bind->bindport, 123); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], fips_ciphers); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS); } assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], fips_ciphers); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS); } assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], MACS); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], MACS); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], fips_kex); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], KEXALGORITHMS); } SAFE_FREE(fips_ciphers); SAFE_FREE(fips_kex); return 0; } static void torture_bind_config_full(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_FULL); assert_int_equal(rc, 0); rc = assert_full_bind_config(state); assert_int_equal(rc, 0); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_include(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_INCLUDE); assert_int_equal(rc, 0); rc = assert_full_bind_config(state); assert_int_equal(rc, 0); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_include_recursive(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_INCLUDE_RECURSIVE); assert_int_equal(rc, 0); rc = assert_full_bind_config(state); assert_int_equal(rc, 0); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } /** * @brief Verify the configuration parser does not choke on unknown * or unsupported configuration options */ static void torture_bind_config_corner_cases(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_CORNER_CASES); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], CIPHERS2); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], CIPHERS2); } static void torture_bind_config_match_all(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level, new_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_ALL); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 1); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_match_twice(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level, new_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_TWICE); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 1); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_match_unsupported(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_UNSUPPORTED); assert_int_equal(rc, 0); rc = assert_full_bind_config(state); assert_int_equal(rc, 0); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_match_not_allowed(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_NOT_ALLOWED); assert_int_equal(rc, 0); rc = assert_full_bind_config(state); assert_int_equal(rc, 0); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_match_corner_cases(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level, new_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_CORNER_CASES); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, 3); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_config_match_invalid(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID); assert_int_equal(rc, -1); rc = ssh_bind_config_parse_file(bind, LIBSSH_TEST_BIND_CONFIG_MATCH_INVALID2); assert_int_equal(rc, -1); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_bind_config_listen_address, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_port, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_hostkey, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_hostkey_twice_rec, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_hostkey_separately, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_loglevel, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_ciphers, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_macs, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_kexalgorithms, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_full, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_include, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_include_recursive, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_corner_cases, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_all, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_twice, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_unsupported, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_not_allowed, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_corner_cases, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_match_invalid, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_pubkey_accepted, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_config_hostkey_algorithms, sshbind_setup, sshbind_teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_buffer.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #define DEBUG_BUFFER #include "buffer.c" #define LIMIT (8*1024*1024) static int setup(void **state) { ssh_buffer buffer; buffer = ssh_buffer_new(); if (buffer == NULL) { return -1; } ssh_buffer_set_secure(buffer); *state = (void *) buffer; return 0; } static int teardown(void **state) { SSH_BUFFER_FREE(*state); return 0; } /* * Test if the continuously growing buffer size never exceeds 2 time its * real capacity */ static void torture_growing_buffer(void **state) { ssh_buffer buffer = *state; int i; for(i=0;iused >= 128){ if(ssh_buffer_get_len(buffer) * 2 < buffer->allocated){ assert_true(ssh_buffer_get_len(buffer) * 2 >= buffer->allocated); } } } } /* * Test if the continuously growing buffer size never exceeds 2 time its * real capacity, when we remove 1 byte after each call (sliding window) */ static void torture_growing_buffer_shifting(void **state) { ssh_buffer buffer = *state; int i; unsigned char c; for(i=0; i<1024;++i){ ssh_buffer_add_data(buffer,"S",1); } for(i=0;iused >= 128){ if(ssh_buffer_get_len(buffer) * 4 < buffer->allocated){ assert_true(ssh_buffer_get_len(buffer) * 4 >= buffer->allocated); return; } } } } /* * Test the behavior of ssh_buffer_prepend_data */ static void torture_buffer_prepend(void **state) { ssh_buffer buffer = *state; uint32_t v; ssh_buffer_add_data(buffer,"abcdef",6); ssh_buffer_prepend_data(buffer,"xyz",3); assert_int_equal(ssh_buffer_get_len(buffer),9); assert_memory_equal(ssh_buffer_get(buffer), "xyzabcdef", 9); /* Now remove 4 bytes and see if we can replace them */ ssh_buffer_get_u32(buffer,&v); assert_int_equal(ssh_buffer_get_len(buffer),5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer,"aris",4); assert_int_equal(ssh_buffer_get_len(buffer),9); assert_memory_equal(ssh_buffer_get(buffer), "arisbcdef", 9); /* same thing but we add 5 bytes now */ ssh_buffer_get_u32(buffer,&v); assert_int_equal(ssh_buffer_get_len(buffer),5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer,"12345",5); assert_int_equal(ssh_buffer_get_len(buffer),10); assert_memory_equal(ssh_buffer_get(buffer), "12345bcdef", 10); } /* * Test the behavior of ssh_buffer_get_ssh_string with invalid data */ static void torture_ssh_buffer_get_ssh_string(void **state) { ssh_buffer buffer; int i,j,k,l, rc; /* some values that can go wrong */ uint32_t values[] = {0xffffffff, 0xfffffffe, 0xfffffffc, 0xffffff00, 0x80000000, 0x80000004, 0x7fffffff}; char data[128]; (void)state; memset(data,'X',sizeof(data)); for(i=0; i < (int)(sizeof(values)/sizeof(values[0]));++i){ for(j=0; j< (int)sizeof(data);++j){ for(k=1;k<5;++k){ buffer = ssh_buffer_new(); assert_non_null(buffer); for(l=0;l #include "torture.h" #include "libssh/bytearray.h" static void torture_pull_le_u8(void **state) { uint8_t data[2] = {0}; uint8_t result; (void)state; result = PULL_LE_U8(data, 0); assert_int_equal(result, 0); data[0] = 0x2a; result = PULL_LE_U8(data, 0); assert_int_equal(result, 42); data[0] = 0xf; result = PULL_LE_U8(data, 0); assert_int_equal(result, 0xf); data[0] = 0xff; result = PULL_LE_U8(data, 0); assert_int_equal(result, 0xff); data[1] = 0x2a; result = PULL_LE_U8(data, 1); assert_int_equal(result, 42); } static void torture_pull_le_u16(void **state) { uint8_t data[2] = {0, 0}; uint16_t result; (void)state; result = PULL_LE_U16(data, 0); assert_int_equal(result, 0); data[0] = 0x2a; data[1] = 0x00; result = PULL_LE_U16(data, 0); assert_int_equal(result, 42); data[0] = 0xff; data[1] = 0x00; result = PULL_LE_U16(data, 0); assert_int_equal(result, 0x00ff); data[0] = 0x00; data[1] = 0xff; result = PULL_LE_U16(data, 0); assert_int_equal(result, 0xff00); data[0] = 0xff; data[1] = 0xff; result = PULL_LE_U16(data, 0); assert_int_equal(result, 0xffff); } static void torture_pull_le_u32(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint32_t result; (void)state; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0); data[0] = 0x2a; data[1] = 0x00; data[2] = 0x00; data[3] = 0x00; result = PULL_LE_U32(data, 0); assert_int_equal(result, 42); data[0] = 0xff; data[1] = 0x00; data[2] = 0x00; data[3] = 0x00; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0x00ff); data[0] = 0x00; data[1] = 0xff; data[2] = 0x00; data[3] = 0x00; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0xff00); data[0] = 0x00; data[1] = 0x00; data[2] = 0xff; data[3] = 0x00; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0xff0000); data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; data[3] = 0xff; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0xff000000); data[0] = 0xff; data[1] = 0xff; data[2] = 0xff; data[3] = 0xff; result = PULL_LE_U32(data, 0); assert_int_equal(result, 0xffffffff); } static void torture_push_le_u8(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint8_t data2[4] = {42, 42, 42, 42}; (void)state; PUSH_LE_U8(data, 0, 42); PUSH_LE_U8(data, 1, 42); PUSH_LE_U8(data, 2, 42); PUSH_LE_U8(data, 3, 42); assert_memory_equal(data, data2, sizeof(data)); } static void torture_push_le_u16(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint8_t data2[4] = {0xa6, 0x7f, 0x2a, 0x00}; uint16_t result; (void)state; PUSH_LE_U16(data, 0, 32678); PUSH_LE_U16(data, 2, 42); assert_memory_equal(data, data2, sizeof(data)); result = PULL_LE_U16(data, 2); assert_int_equal(result, 42); result = PULL_LE_U16(data, 0); assert_int_equal(result, 32678); } static void torture_push_le_u32(void **state) { uint8_t data[8] = {0}; uint8_t data2[8] = {0xa6, 0x7f, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00}; uint32_t result; (void)state; PUSH_LE_U32(data, 0, 32678); PUSH_LE_U32(data, 4, 42); assert_memory_equal(data, data2, sizeof(data)); result = PULL_LE_U32(data, 4); assert_int_equal(result, 42); result = PULL_LE_U32(data, 0); assert_int_equal(result, 32678); PUSH_LE_U32(data, 0, 0xfffefffe); result = PULL_LE_U32(data, 0); assert_int_equal(result, 0xfffefffe); } static void torture_push_le_u64(void **state) { uint8_t data[16] = {0}; uint64_t result; (void)state; PUSH_LE_U64(data, 0, 32678); result = PULL_LE_U64(data, 0); assert_int_equal(result, 32678); PUSH_LE_U64(data, 0, 0xfffefffefffefffeUL); result = PULL_LE_U64(data, 0); assert_int_equal(result, 0xfffefffefffefffeUL); } /****************** BIG ENDIAN ********************/ static void torture_pull_be_u8(void **state) { uint8_t data[2] = {0}; uint8_t result; (void)state; result = PULL_BE_U8(data, 0); assert_int_equal(result, 0); data[0] = 0x2a; result = PULL_BE_U8(data, 0); assert_int_equal(result, 42); data[0] = 0xf; result = PULL_BE_U8(data, 0); assert_int_equal(result, 0xf); data[0] = 0xff; result = PULL_BE_U8(data, 0); assert_int_equal(result, 0xff); data[1] = 0x2a; result = PULL_BE_U8(data, 1); assert_int_equal(result, 42); } static void torture_pull_be_u16(void **state) { uint8_t data[2] = {0, 0}; uint16_t result; (void)state; result = PULL_BE_U16(data, 0); assert_int_equal(result, 0); data[0] = 0x00; data[1] = 0x2a; result = PULL_BE_U16(data, 0); assert_int_equal(result, 42); data[0] = 0x00; data[1] = 0xff; result = PULL_BE_U16(data, 0); assert_int_equal(result, 0x00ff); data[0] = 0xff; data[1] = 0x00; result = PULL_BE_U16(data, 0); assert_int_equal(result, 0xff00); data[0] = 0xff; data[1] = 0xff; result = PULL_BE_U16(data, 0); assert_int_equal(result, 0xffff); } static void torture_pull_be_u32(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint32_t result; (void)state; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0); data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; data[3] = 0x2a; result = PULL_BE_U32(data, 0); assert_int_equal(result, 42); data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; data[3] = 0xff; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0x00ff); data[0] = 0x00; data[1] = 0x00; data[2] = 0xff; data[3] = 0x00; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0xff00); data[0] = 0x00; data[1] = 0xff; data[2] = 0x00; data[3] = 0x00; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0xff0000); data[0] = 0xff; data[1] = 0x00; data[2] = 0x00; data[3] = 0x00; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0xff000000); data[0] = 0xff; data[1] = 0xff; data[2] = 0xff; data[3] = 0xff; result = PULL_BE_U32(data, 0); assert_int_equal(result, 0xffffffff); } static void torture_push_be_u8(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint8_t data2[4] = {42, 42, 42, 42}; (void)state; PUSH_BE_U8(data, 0, 42); PUSH_BE_U8(data, 1, 42); PUSH_BE_U8(data, 2, 42); PUSH_BE_U8(data, 3, 42); assert_memory_equal(data, data2, sizeof(data)); } static void torture_push_be_u16(void **state) { uint8_t data[4] = {0, 0, 0, 0}; uint8_t data2[4] = {0x7f, 0xa6, 0x00, 0x2a}; uint16_t result; (void)state; PUSH_BE_U16(data, 0, 32678); PUSH_BE_U16(data, 2, 42); assert_memory_equal(data, data2, sizeof(data)); result = PULL_BE_U16(data, 2); assert_int_equal(result, 42); result = PULL_BE_U16(data, 0); assert_int_equal(result, 32678); } static void torture_push_be_u32(void **state) { uint8_t data[8] = {0}; uint8_t data2[8] = {0x00, 0x00, 0x7f, 0xa6, 0x00, 0x00, 0x00, 0x2a}; uint32_t result; (void)state; PUSH_BE_U32(data, 0, 32678); PUSH_BE_U32(data, 4, 42); assert_memory_equal(data, data2, sizeof(data)); result = PULL_BE_U32(data, 4); assert_int_equal(result, 42); result = PULL_BE_U32(data, 0); assert_int_equal(result, 32678); PUSH_BE_U32(data, 0, 0xfffefffe); result = PULL_BE_U32(data, 0); assert_int_equal(result, 0xfffefffe); } static void torture_push_be_u64(void **state) { uint8_t data[16] = {0}; uint64_t result; (void)state; PUSH_BE_U64(data, 0, 32678); result = PULL_BE_U64(data, 0); assert_int_equal(result, 32678); PUSH_LE_U64(data, 8, 0xfffefffe); result = PULL_LE_U64(data, 8); assert_int_equal(result, 0xfffefffe); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_pull_le_u8), cmocka_unit_test(torture_pull_le_u16), cmocka_unit_test(torture_pull_le_u32), cmocka_unit_test(torture_push_le_u8), cmocka_unit_test(torture_push_le_u16), cmocka_unit_test(torture_push_le_u32), cmocka_unit_test(torture_push_le_u64), /* BIG ENDIAN */ cmocka_unit_test(torture_pull_be_u8), cmocka_unit_test(torture_pull_be_u16), cmocka_unit_test(torture_pull_be_u32), cmocka_unit_test(torture_push_be_u8), cmocka_unit_test(torture_push_be_u16), cmocka_unit_test(torture_push_be_u32), cmocka_unit_test(torture_push_be_u64), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_callbacks.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include #include #include static int myauthcallback (const char *prompt, char *buf, size_t len, int echo, int verify, void *userdata) { (void) prompt; (void) buf; (void) len; (void) echo; (void) verify; (void) userdata; return 0; } static int setup(void **state) { struct ssh_callbacks_struct *cb; cb = malloc(sizeof(struct ssh_callbacks_struct)); assert_non_null(cb); ZERO_STRUCTP(cb); cb->userdata = (void *) 0x0badc0de; cb->auth_function = myauthcallback; ssh_callbacks_init(cb); *state = cb; return 0; } static int teardown(void **state) { free(*state); return 0; } static void torture_callbacks_size(void **state) { struct ssh_callbacks_struct *cb = *state;; assert_int_not_equal(cb->size, 0); } static void torture_callbacks_exists(void **state) { struct ssh_callbacks_struct *cb = *state; assert_int_not_equal(ssh_callbacks_exists(cb, auth_function), 0); assert_int_equal(ssh_callbacks_exists(cb, log_function), 0); /* * We redefine size so auth_function is outside the range of * callbacks->size. */ cb->size = (unsigned char *) &cb->auth_function - (unsigned char *) cb; assert_int_equal(ssh_callbacks_exists(cb, auth_function), 0); /* Now make it one pointer bigger so we spill over the auth_function slot */ cb->size += sizeof(void *); assert_int_not_equal(ssh_callbacks_exists(cb, auth_function), 0); } struct test_mock_state { int executed; }; static void test_mock_ssh_logging_callback(int priority, const char *function, const char *buffer, void *userdata) { struct test_mock_state *t = (struct test_mock_state *)userdata; check_expected(priority); check_expected(function); check_expected(buffer); t->executed++; } static void torture_log_callback(void **state) { struct test_mock_state t = { .executed = 0, }; (void)state; /* unused */ ssh_set_log_callback(test_mock_ssh_logging_callback); ssh_set_log_userdata(&t); ssh_set_log_level(1); expect_value(test_mock_ssh_logging_callback, priority, 1); expect_string(test_mock_ssh_logging_callback, function, "torture_log_callback"); expect_string(test_mock_ssh_logging_callback, buffer, "torture_log_callback: test"); SSH_LOG(SSH_LOG_WARN, "test"); assert_int_equal(t.executed, 1); } static void cb1(ssh_session session, ssh_channel channel, void *userdata){ int *v = userdata; (void) session; (void) channel; *v += 1; } static void cb2(ssh_session session, ssh_channel channel, int status, void *userdata){ int *v = userdata; (void) session; (void) channel; (void) status; *v += 10; } static void torture_callbacks_execute_list(void **state){ struct ssh_list *list = ssh_list_new(); int v = 0, w = 0; struct ssh_channel_callbacks_struct c1 = { .channel_eof_function = cb1, .userdata = &v }; struct ssh_channel_callbacks_struct c2 = { .channel_exit_status_function = cb2, .userdata = &v }; struct ssh_channel_callbacks_struct c3 = { .channel_eof_function = cb1, .channel_exit_status_function = cb2, .userdata = &w }; (void)state; ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); ssh_callbacks_init(&c3); ssh_list_append(list, &c1); ssh_callbacks_execute_list(list, ssh_channel_callbacks, channel_eof_function, NULL, NULL); assert_int_equal(v, 1); v = 0; ssh_list_append(list, &c2); ssh_callbacks_execute_list(list, ssh_channel_callbacks, channel_eof_function, NULL, NULL); assert_int_equal(v, 1); ssh_callbacks_execute_list(list, ssh_channel_callbacks, channel_exit_status_function, NULL, NULL, 0); assert_int_equal(v, 11); v = 0; w = 0; ssh_list_append(list, &c3); ssh_callbacks_execute_list(list, ssh_channel_callbacks, channel_eof_function, NULL, NULL); assert_int_equal(v, 1); assert_int_equal(w, 1); ssh_callbacks_execute_list(list, ssh_channel_callbacks, channel_exit_status_function, NULL, NULL, 0); assert_int_equal(v, 11); assert_int_equal(w, 11); ssh_list_free(list); } static int cb3(ssh_session session, ssh_channel channel, void *userdata){ int *v = userdata; (void)session; (void)channel; *v = 1; return 10; } static void torture_callbacks_iterate(void **state){ struct ssh_list *list = ssh_list_new(); int v = 0, w = 0; struct ssh_channel_callbacks_struct c1 = { .channel_eof_function = cb1, .channel_shell_request_function = cb3, .userdata = &v }; struct ssh_channel_callbacks_struct c2 = { .channel_eof_function = cb1, .channel_shell_request_function = cb3, .userdata = &v }; (void)state; /* unused */ ssh_callbacks_init(&c1); ssh_callbacks_init(&c2); ssh_list_append(list, &c1); ssh_list_append(list, &c2); ssh_callbacks_iterate(list, ssh_channel_callbacks, channel_eof_function){ ssh_callbacks_iterate_exec(channel_eof_function, NULL, NULL); } ssh_callbacks_iterate_end(); assert_int_equal(v, 2); v = 0; ssh_callbacks_iterate(list, ssh_channel_callbacks, channel_shell_request_function){ w = ssh_callbacks_iterate_exec(channel_shell_request_function, NULL, NULL); if (w) { break; } } ssh_callbacks_iterate_end(); assert_int_equal(w, 10); assert_int_equal(v, 1); ssh_list_free(list); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_callbacks_size, setup, teardown), cmocka_unit_test_setup_teardown(torture_callbacks_exists, setup, teardown), cmocka_unit_test(torture_log_callback), cmocka_unit_test(torture_callbacks_execute_list), cmocka_unit_test(torture_callbacks_iterate) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_channel.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include #include #include "torture.h" #include "channels.c" static void torture_channel_select(void **state) { fd_set readfds; int fd; int rc; int i; (void)state; /* unused */ ZERO_STRUCT(readfds); fd = open("/dev/null", 0); assert_true(fd > 2); FD_ZERO(&readfds); FD_SET(fd, &readfds); for (i = 0; i < 10; i++) { ssh_channel cin[1] = { NULL, }; ssh_channel cout[1] = { NULL, }; struct timeval tv = { .tv_sec = 0, .tv_usec = 1000 }; rc = ssh_select(cin, cout, fd + 1, &readfds, &tv); assert_int_equal(rc, SSH_OK); } close(fd); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_channel_select), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_config.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/options.h" #include "libssh/session.h" #include "libssh/config_parser.h" #include "match.c" extern LIBSSH_THREAD int ssh_log_level; #define LIBSSH_TESTCONFIG1 "libssh_testconfig1.tmp" #define LIBSSH_TESTCONFIG2 "libssh_testconfig2.tmp" #define LIBSSH_TESTCONFIG3 "libssh_testconfig3.tmp" #define LIBSSH_TESTCONFIG4 "libssh_testconfig4.tmp" #define LIBSSH_TESTCONFIG5 "libssh_testconfig5.tmp" #define LIBSSH_TESTCONFIG6 "libssh_testconfig6.tmp" #define LIBSSH_TESTCONFIG7 "libssh_testconfig7.tmp" #define LIBSSH_TESTCONFIG8 "libssh_testconfig8.tmp" #define LIBSSH_TESTCONFIG9 "libssh_testconfig9.tmp" #define LIBSSH_TESTCONFIG10 "libssh_testconfig10.tmp" #define LIBSSH_TESTCONFIG11 "libssh_testconfig11.tmp" #define LIBSSH_TESTCONFIG12 "libssh_testconfig12.tmp" #define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp" #define LIBSSH_TEST_PUBKEYACCEPTEDKEYTYPES "libssh_test_PubkeyAcceptedKeyTypes.tmp" #define USERNAME "testuser" #define PROXYCMD "ssh -q -W %h:%p gateway.example.com" #define ID_FILE "/etc/xxx" #define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1" #define HOSTKEYALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp521,ssh-rsa" #define PUBKEYACCEPTEDTYPES "rsa-sha2-512,ssh-rsa,ecdsa-sha2-nistp521" #define MACS "hmac-sha1,hmac-sha2-256,hmac-sha2-512,hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com" #define USER_KNOWN_HOSTS "%d/my_known_hosts" #define GLOBAL_KNOWN_HOSTS "/etc/ssh/my_ssh_known_hosts" #define BIND_ADDRESS "::1" static int setup_config_files(void **state) { ssh_session session; int verbosity; unlink(LIBSSH_TESTCONFIG1); unlink(LIBSSH_TESTCONFIG2); unlink(LIBSSH_TESTCONFIG3); unlink(LIBSSH_TESTCONFIG4); unlink(LIBSSH_TESTCONFIG5); unlink(LIBSSH_TESTCONFIG6); unlink(LIBSSH_TESTCONFIG7); unlink(LIBSSH_TESTCONFIG8); unlink(LIBSSH_TESTCONFIG9); unlink(LIBSSH_TESTCONFIG10); unlink(LIBSSH_TESTCONFIG11); unlink(LIBSSH_TESTCONFIG12); unlink(LIBSSH_TEST_PUBKEYACCEPTEDKEYTYPES); torture_write_file(LIBSSH_TESTCONFIG1, "User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n"); torture_write_file(LIBSSH_TESTCONFIG2, "Include "LIBSSH_TESTCONFIG3"\n" "ProxyCommand "PROXYCMD"\n\n"); torture_write_file(LIBSSH_TESTCONFIG3, "\n\nIdentityFile "ID_FILE"\n" "\n\nKexAlgorithms "KEXALGORITHMS"\n" "\n\nHostKeyAlgorithms "HOSTKEYALGORITHMS"\n" "\n\nPubkeyAcceptedTypes "PUBKEYACCEPTEDTYPES"\n" "\n\nMACs "MACS"\n"); /* Multiple Port settings -> parsing returns early. */ torture_write_file(LIBSSH_TESTCONFIG4, "Port 123\nPort 456\n"); /* Testing glob include */ torture_write_file(LIBSSH_TESTCONFIG5, "User "USERNAME"\nInclude "LIBSSH_TESTCONFIGGLOB"\n\n"); torture_write_file(LIBSSH_TESTCONFIG6, "ProxyCommand "PROXYCMD"\n\n"); /* new options */ torture_write_file(LIBSSH_TESTCONFIG7, "\tBindAddress "BIND_ADDRESS"\n" "\tConnectTimeout 30\n" "\tLogLevel DEBUG3\n" "\tGlobalKnownHostsFile "GLOBAL_KNOWN_HOSTS"\n" "\tCompression yes\n" "\tStrictHostkeyChecking no\n" "\tGSSAPIDelegateCredentials yes\n" "\tGSSAPIServerIdentity example.com\n" "\tGSSAPIClientIdentity home.sweet\n" "\tUserKnownHostsFile "USER_KNOWN_HOSTS"\n"); /* authentication methods */ torture_write_file(LIBSSH_TESTCONFIG8, "Host gss\n" "\tGSSAPIAuthentication yes\n" "Host kbd\n" "\tKbdInteractiveAuthentication yes\n" "Host pass\n" "\tPasswordAuthentication yes\n" "Host pubkey\n" "\tPubkeyAuthentication yes\n" "Host nogss\n" "\tGSSAPIAuthentication no\n" "Host nokbd\n" "\tKbdInteractiveAuthentication no\n" "Host nopass\n" "\tPasswordAuthentication no\n" "Host nopubkey\n" "\tPubkeyAuthentication no\n"); /* unsupported options and corner cases */ torture_write_file(LIBSSH_TESTCONFIG9, "\n" /* empty line */ "# comment line\n" " # comment line not starting with hash\n" "UnknownConfigurationOption yes\n" "GSSAPIKexAlgorithms yes\n" "ControlMaster auto\n" /* SOC_NA */ "VisualHostkey yes\n" /* SOC_UNSUPPORTED */ ""); /* Match keyword */ torture_write_file(LIBSSH_TESTCONFIG10, "Match host example\n" "\tHostName example.com\n" "Match host example1,example2\n" "\tHostName exampleN\n" "Match user guest\n" "\tHostName guest.com\n" "Match user tester host testhost\n" "\tHostName testhost.com\n" "Match !user tester host testhost\n" "\tHostName nonuser-testhost.com\n" "Match all\n" "\tHostName all-matched.com\n" /* Unsupported options */ "Match originalhost example\n" "\tHostName original-example.com\n" "Match localuser guest\n" "\tHostName local-guest.com\n" ""); /* ProxyJump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host simple\n" "\tProxyJump jumpbox\n" "Host user\n" "\tProxyJump user@jumpbox\n" "Host port\n" "\tProxyJump jumpbox:2222\n" "Host two-step\n" "\tProxyJump u1@first:222,u2@second:33\n" "Host none\n" "\tProxyJump none\n" "Host only-command\n" "\tProxyCommand "PROXYCMD"\n" "\tProxyJump jumpbox\n" "Host only-jump\n" "\tProxyJump jumpbox\n" "\tProxyCommand "PROXYCMD"\n" "Host ipv6\n" "\tProxyJump [2620:52:0::fed]\n" ""); /* RekeyLimit combinations */ torture_write_file(LIBSSH_TESTCONFIG12, "Host default\n" "\tRekeyLimit default none\n" "Host data1\n" "\tRekeyLimit 42G\n" "Host data2\n" "\tRekeyLimit 31M\n" "Host data3\n" "\tRekeyLimit 521K\n" "Host time1\n" "\tRekeyLimit default 3D\n" "Host time2\n" "\tRekeyLimit default 2h\n" "Host time3\n" "\tRekeyLimit default 160m\n" "Host time4\n" "\tRekeyLimit default 9600\n" ""); torture_write_file(LIBSSH_TEST_PUBKEYACCEPTEDKEYTYPES, "PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n"); session = ssh_new(); verbosity = torture_libssh_verbosity(); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); *state = session; return 0; } static int teardown(void **state) { unlink(LIBSSH_TESTCONFIG1); unlink(LIBSSH_TESTCONFIG2); unlink(LIBSSH_TESTCONFIG3); unlink(LIBSSH_TESTCONFIG4); unlink(LIBSSH_TESTCONFIG5); unlink(LIBSSH_TESTCONFIG6); unlink(LIBSSH_TESTCONFIG7); unlink(LIBSSH_TESTCONFIG8); unlink(LIBSSH_TESTCONFIG9); unlink(LIBSSH_TESTCONFIG10); unlink(LIBSSH_TESTCONFIG11); unlink(LIBSSH_TESTCONFIG12); unlink(LIBSSH_TEST_PUBKEYACCEPTEDKEYTYPES); ssh_free(*state); return 0; } /** * @brief tests ssh_config_parse_file with Include directives */ static void torture_config_from_file(void **state) { ssh_session session = *state; int ret; char *v = NULL; char *fips_algos = NULL; ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG1); assert_true(ret == 0); /* Test the variable presence */ ret = ssh_options_get(session, SSH_OPTIONS_PROXYCOMMAND, &v); assert_true(ret == 0); assert_non_null(v); assert_string_equal(v, PROXYCMD); SSH_STRING_FREE_CHAR(v); ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v); assert_true(ret == 0); assert_non_null(v); assert_string_equal(v, ID_FILE); SSH_STRING_FREE_CHAR(v); ret = ssh_options_get(session, SSH_OPTIONS_USER, &v); assert_true(ret == 0); assert_non_null(v); assert_string_equal(v, USERNAME); SSH_STRING_FREE_CHAR(v); if (ssh_fips_mode()) { fips_algos = ssh_keep_fips_algos(SSH_KEX, KEXALGORITHMS); assert_non_null(fips_algos); assert_string_equal(session->opts.wanted_methods[SSH_KEX], fips_algos); SAFE_FREE(fips_algos); fips_algos = ssh_keep_fips_algos(SSH_HOSTKEYS, HOSTKEYALGORITHMS); assert_non_null(fips_algos); assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], fips_algos); SAFE_FREE(fips_algos); fips_algos = ssh_keep_fips_algos(SSH_HOSTKEYS, PUBKEYACCEPTEDTYPES); assert_non_null(fips_algos); assert_string_equal(session->opts.pubkey_accepted_types, fips_algos); SAFE_FREE(fips_algos); fips_algos = ssh_keep_fips_algos(SSH_MAC_C_S, MACS); assert_non_null(fips_algos); assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], fips_algos); SAFE_FREE(fips_algos); fips_algos = ssh_keep_fips_algos(SSH_MAC_S_C, MACS); assert_non_null(fips_algos); assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], fips_algos); SAFE_FREE(fips_algos); } else { assert_non_null(session->opts.wanted_methods[SSH_KEX]); assert_string_equal(session->opts.wanted_methods[SSH_KEX], KEXALGORITHMS); assert_non_null(session->opts.wanted_methods[SSH_HOSTKEYS]); assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], HOSTKEYALGORITHMS); assert_non_null(session->opts.pubkey_accepted_types); assert_string_equal(session->opts.pubkey_accepted_types, PUBKEYACCEPTEDTYPES); assert_non_null(session->opts.wanted_methods[SSH_MAC_S_C]); assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], MACS); assert_non_null(session->opts.wanted_methods[SSH_MAC_S_C]); assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], MACS); } } /** * @brief tests ssh_config_parse_file with multiple Port settings. */ static void torture_config_double_ports(void **state) { ssh_session session = *state; int ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG4); assert_true(ret == 0); } static void torture_config_glob(void **state) { ssh_session session = *state; int ret; #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) char *v; #endif /* HAVE_GLOB && HAVE_GLOB_GL_FLAGS_MEMBER */ ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG5); assert_true(ret == 0); /* non-existing files should not error */ /* Test the variable presence */ #if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER) ret = ssh_options_get(session, SSH_OPTIONS_PROXYCOMMAND, &v); assert_true(ret == 0); assert_non_null(v); assert_string_equal(v, PROXYCMD); SSH_STRING_FREE_CHAR(v); ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v); assert_true(ret == 0); assert_non_null(v); assert_string_equal(v, ID_FILE); SSH_STRING_FREE_CHAR(v); #endif /* HAVE_GLOB && HAVE_GLOB_GL_FLAGS_MEMBER */ } /** * @brief Verify the new options are passed from configuration */ static void torture_config_new(void **state) { ssh_session session = *state; int ret = 0; ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG7); assert_true(ret == 0); assert_string_equal(session->opts.knownhosts, USER_KNOWN_HOSTS); assert_string_equal(session->opts.global_knownhosts, GLOBAL_KNOWN_HOSTS); assert_int_equal(session->opts.timeout, 30); assert_string_equal(session->opts.bindaddr, BIND_ADDRESS); #ifdef WITH_ZLIB assert_string_equal(session->opts.wanted_methods[SSH_COMP_C_S], "zlib@openssh.com,zlib"); assert_string_equal(session->opts.wanted_methods[SSH_COMP_S_C], "zlib@openssh.com,zlib"); #else assert_null(session->opts.wanted_methods[SSH_COMP_C_S]); assert_null(session->opts.wanted_methods[SSH_COMP_S_C]); #endif /* WITH_ZLIB */ assert_int_equal(session->opts.StrictHostKeyChecking, 0); assert_int_equal(session->opts.gss_delegate_creds, 1); assert_string_equal(session->opts.gss_server_identity, "example.com"); assert_string_equal(session->opts.gss_client_identity, "home.sweet"); assert_int_equal(ssh_get_log_level(), SSH_LOG_TRACE); assert_int_equal(session->common.log_verbosity, SSH_LOG_TRACE); } /** * @brief Verify the authentication methods from configuration are effective */ static void torture_config_auth_methods(void **state) { ssh_session session = *state; int ret = 0; /* gradually disable all the methods based on different hosts */ ssh_options_set(session, SSH_OPTIONS_HOST, "nogss"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_false(session->opts.flags & SSH_OPT_FLAG_GSSAPI_AUTH); assert_true(session->opts.flags & SSH_OPT_FLAG_KBDINT_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "nokbd"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_false(session->opts.flags & SSH_OPT_FLAG_KBDINT_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "nopass"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_false(session->opts.flags & SSH_OPT_FLAG_PASSWORD_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "nopubkey"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_false(session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH); /* no method should be left enabled */ assert_int_equal(session->opts.flags, 0); /* gradually enable them again */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "gss"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_true(session->opts.flags & SSH_OPT_FLAG_GSSAPI_AUTH); assert_false(session->opts.flags & SSH_OPT_FLAG_KBDINT_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "kbd"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_true(session->opts.flags & SSH_OPT_FLAG_KBDINT_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "pass"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_true(session->opts.flags & SSH_OPT_FLAG_PASSWORD_AUTH); ssh_options_set(session, SSH_OPTIONS_HOST, "pubkey"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG8); assert_true(ret == 0); assert_true(session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH); } /** * @brief Verify the configuration parser does not choke on unknown * or unsupported configuration options */ static void torture_config_unknown(void **state) { ssh_session session = *state; int ret = 0; /* test corner cases */ ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG9); assert_true(ret == 0); ret = ssh_config_parse_file(session, "/etc/ssh/ssh_config"); assert_true(ret == 0); ret = ssh_config_parse_file(session, GLOBAL_CLIENT_CONFIG); assert_true(ret == 0); } /** * @brief Verify the configuration parser accepts Match keyword with * full OpenSSH syntax. */ static void torture_config_match(void **state) { ssh_session session = *state; char *localuser = NULL; char config[1024]; int ret = 0; /* Without any settings we should get all-matched.com hostname */ ssh_options_set(session, SSH_OPTIONS_HOST, "unmatched"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "all-matched.com"); /* Hostname example does simple hostname matching */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "example"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "example.com"); /* We can match also both hosts from a comma separated list */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "example1"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "exampleN"); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "example2"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "exampleN"); /* We can match by user */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_USER, "guest"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "guest.com"); /* We can combine two options on a single line to match both of them */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_USER, "tester"); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "testhost.com"); /* We can also negate conditions */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_USER, "not-tester"); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "nonuser-testhost.com"); /* Match final is not completely supported, but should do quite much the * same as "match all". The trailing "all" is not mandatory. */ torture_write_file(LIBSSH_TESTCONFIG10, "Match final all\n" "\tHostName final-all.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "final-all.com"); torture_write_file(LIBSSH_TESTCONFIG10, "Match final\n" "\tHostName final.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "final.com"); /* Match canonical is not completely supported, but should do quite much the * same as "match all". The trailing "all" is not mandatory. */ torture_write_file(LIBSSH_TESTCONFIG10, "Match canonical all\n" "\tHostName canonical-all.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "canonical-all.com"); torture_write_file(LIBSSH_TESTCONFIG10, "Match canonical all\n" "\tHostName canonical.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "canonical.com"); localuser = ssh_get_local_username(); assert_non_null(localuser); snprintf(config, sizeof(config), "Match localuser %s\n" "\tHostName otherhost\n" "", localuser); free(localuser); torture_write_file(LIBSSH_TESTCONFIG10, config); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.host, "otherhost"); /* Try to create some invalid configurations */ /* Missing argument to Match*/ torture_write_file(LIBSSH_TESTCONFIG10, "Match\n" "\tHost missing.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing argument to unsupported option originalhost */ torture_write_file(LIBSSH_TESTCONFIG10, "Match originalhost\n" "\tHost originalhost.com\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing argument to option localuser */ torture_write_file(LIBSSH_TESTCONFIG10, "Match localuser\n" "\tUser localuser2\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing argument to option user */ torture_write_file(LIBSSH_TESTCONFIG10, "Match user\n" "\tUser user2\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing argument to option host */ torture_write_file(LIBSSH_TESTCONFIG10, "Match host\n" "\tUser host2\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing argument to unsupported option exec */ torture_write_file(LIBSSH_TESTCONFIG10, "Match exec\n" "\tUser exec\n" ""); torture_reset_config(session); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG10); assert_ssh_return_code_equal(session, ret, SSH_ERROR); } /** * @brief Verify we can parse ProxyJump configuration option */ static void torture_config_proxyjump(void **state) { ssh_session session = *state; int ret = 0; /* Simplest version with just a hostname */ ssh_options_set(session, SSH_OPTIONS_HOST, "simple"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -W [%h]:%p jumpbox"); /* With username */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "user"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -l user -W [%h]:%p jumpbox"); /* With port */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "port"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -p 2222 -W [%h]:%p jumpbox"); /* Two step jump */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "two-step"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -l u1 -p 222 -J u2@second:33 -W [%h]:%p first"); /* none */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "none"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_true(session->opts.ProxyCommand == NULL); /* If also ProxyCommand is specifed, the first is applied */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "only-command"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, PROXYCMD); /* If also ProxyCommand is specifed, the first is applied */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "only-jump"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -W [%h]:%p jumpbox"); /* IPv6 address */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "ipv6"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code(session, ret); assert_string_equal(session->opts.ProxyCommand, "ssh -W [%h]:%p 2620:52:0::fed"); /* Try to create some invalid configurations */ /* Non-numeric port */ torture_write_file(LIBSSH_TESTCONFIG11, "Host bad-port\n" "\tProxyJump jumpbox:22bad22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Too many @ */ torture_write_file(LIBSSH_TESTCONFIG11, "Host bad-hostname\n" "\tProxyJump user@principal.com@jumpbox:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Braces mismatch in hostname */ torture_write_file(LIBSSH_TESTCONFIG11, "Host mismatch\n" "\tProxyJump [::1\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "mismatch"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Bad host-port separator */ torture_write_file(LIBSSH_TESTCONFIG11, "Host beef\n" "\tProxyJump [dead::beef]::22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "beef"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing hostname */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-host\n" "\tProxyJump user@:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-host"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing user */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-user\n" "\tProxyJump @host:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-user"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing port */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-port\n" "\tProxyJump host:\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-port"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Non-numeric port in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host bad-port-2\n" "\tProxyJump localhost,jumpbox:22bad22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "bad-port-2"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Too many @ in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host bad-hostname\n" "\tProxyJump localhost,user@principal.com@jumpbox:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "bad-hostname"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Braces mismatch in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host mismatch\n" "\tProxyJump localhost,[::1:20\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "mismatch"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Bad host-port separator in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host beef\n" "\tProxyJump localhost,[dead::beef]::22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "beef"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing hostname in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-host\n" "\tProxyJump localhost,user@:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-host"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing user in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-user\n" "\tProxyJump localhost,@host:22\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-user"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); /* Missing port in second jump */ torture_write_file(LIBSSH_TESTCONFIG11, "Host no-port\n" "\tProxyJump localhost,host:\n" ""); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "no-port"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG11); assert_ssh_return_code_equal(session, ret, SSH_ERROR); } /** * @brief Verify the configuration parser handles all the possible * versions of RekeyLimit configuration option. */ static void torture_config_rekey(void **state) { ssh_session session = *state; int ret = 0; /* Default values */ ssh_options_set(session, SSH_OPTIONS_HOST, "default"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 0); assert_int_equal(session->opts.rekey_time, 0); /* 42 GB */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "data1"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, (uint64_t) 42 * 1024 * 1024 * 1024); assert_int_equal(session->opts.rekey_time, 0); /* 41 MB */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "data2"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 31 * 1024 * 1024); assert_int_equal(session->opts.rekey_time, 0); /* 521 KB */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "data3"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 521 * 1024); assert_int_equal(session->opts.rekey_time, 0); /* default 3D */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "time1"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 0); assert_int_equal(session->opts.rekey_time, 3 * 24 * 60 * 60 * 1000); /* default 2h */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "time2"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 0); assert_int_equal(session->opts.rekey_time, 2 * 60 * 60 * 1000); /* default 160m */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "time3"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 0); assert_int_equal(session->opts.rekey_time, 160 * 60 * 1000); /* default 9600 [s] */ torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "time4"); ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG12); assert_ssh_return_code(session, ret); assert_int_equal(session->opts.rekey_data, 0); assert_int_equal(session->opts.rekey_time, 9600 * 1000); } /** * @brief test ssh_config_parse_file with PubkeyAcceptedKeyTypes */ static void torture_config_pubkeyacceptedkeytypes(void **state) { ssh_session session = *state; int rc; char *fips_algos; rc = ssh_config_parse_file(session, LIBSSH_TEST_PUBKEYACCEPTEDKEYTYPES); assert_int_equal(rc, SSH_OK); if (ssh_fips_mode()) { fips_algos = ssh_keep_fips_algos(SSH_HOSTKEYS, PUBKEYACCEPTEDTYPES); assert_non_null(fips_algos); assert_string_equal(session->opts.pubkey_accepted_types, fips_algos); SAFE_FREE(fips_algos); } else { assert_string_equal(session->opts.pubkey_accepted_types, PUBKEYACCEPTEDTYPES); } } /* match_pattern() sanity tests */ static void torture_config_match_pattern(void **state) { int rv = 0; (void) state; /* Simple test "a" matches "a" */ rv = match_pattern("a", "a", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); /* Simple test "a" does not match "b" */ rv = match_pattern("a", "b", MAX_MATCH_RECURSION); assert_int_equal(rv, 0); /* NULL arguments are correctly handled */ rv = match_pattern("a", NULL, MAX_MATCH_RECURSION); assert_int_equal(rv, 0); rv = match_pattern(NULL, "a", MAX_MATCH_RECURSION); assert_int_equal(rv, 0); /* Simple wildcard ? is handled in pattern */ rv = match_pattern("a", "?", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("aa", "?", MAX_MATCH_RECURSION); assert_int_equal(rv, 0); rv = match_pattern("?", "a", MAX_MATCH_RECURSION); /* Wildcard in search string */ assert_int_equal(rv, 0); rv = match_pattern("?", "?", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); /* Simple wildcard * is handled in pattern */ rv = match_pattern("a", "*", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("aa", "*", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("*", "a", MAX_MATCH_RECURSION); /* Wildcard in search string */ assert_int_equal(rv, 0); rv = match_pattern("*", "*", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); /* More complicated patterns */ rv = match_pattern("a", "*a", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("a", "a*", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("abababc", "*abc", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("ababababca", "*abc", MAX_MATCH_RECURSION); assert_int_equal(rv, 0); rv = match_pattern("ababababca", "*abc*", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); /* Multiple wildcards in row */ rv = match_pattern("aa", "??", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("bba", "??a", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("aaa", "**a", MAX_MATCH_RECURSION); assert_int_equal(rv, 1); rv = match_pattern("bbb", "**a", MAX_MATCH_RECURSION); assert_int_equal(rv, 0); /* Consecutive asterisks do not make sense and do not need to recurse */ rv = match_pattern("hostname", "**********pattern", 5); assert_int_equal(rv, 0); rv = match_pattern("hostname", "pattern**********", 5); assert_int_equal(rv, 0); rv = match_pattern("pattern", "***********pattern", 5); assert_int_equal(rv, 1); rv = match_pattern("pattern", "pattern***********", 5); assert_int_equal(rv, 1); /* Limit the maximum recursion */ rv = match_pattern("hostname", "*p*a*t*t*e*r*n*", 5); assert_int_equal(rv, 0); rv = match_pattern("pattern", "*p*a*t*t*e*r*n*", 5); /* Too much recursion */ assert_int_equal(rv, 0); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_config_from_file), cmocka_unit_test(torture_config_double_ports), cmocka_unit_test(torture_config_glob), cmocka_unit_test(torture_config_new), cmocka_unit_test(torture_config_auth_methods), cmocka_unit_test(torture_config_unknown), cmocka_unit_test(torture_config_match), cmocka_unit_test(torture_config_proxyjump), cmocka_unit_test(torture_config_rekey), cmocka_unit_test(torture_config_pubkeyacceptedkeytypes), cmocka_unit_test(torture_config_match_pattern), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, setup_config_files, teardown); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_crypto.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/crypto.h" uint8_t key[32] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d" "\x1e\x1f"; uint8_t IV[16] = "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" "\x1f"; uint8_t cleartext[144] = "\xb4\xfc\x5d\xc2\x49\x8d\x2c\x29\x4a\xc9\x9a\xb0\x1b\xf8\x29" "\xee\x85\x6d\x8c\x04\x34\x7c\x65\xf4\x89\x97\xc5\x71\x70\x41" "\x91\x40\x19\x60\xe1\xf1\x8f\x4d\x8c\x17\x51\xd6\xbc\x69\x6e" "\xf2\x21\x87\x18\x6c\xef\xc4\xf4\xd9\xe6\x1b\x94\xf7\xd8\xb2" "\xe9\x24\xb9\xe7\xe6\x19\xf5\xec\x55\x80\x9a\xc8\x7d\x70\xa3" "\x50\xf8\x03\x10\x35\x49\x9b\x53\x58\xd7\x4c\xfc\x5f\x02\xd6" "\x28\xea\xcc\x43\xee\x5e\x2b\x8a\x7a\x66\xf7\x00\xee\x09\x18" "\x30\x1b\x47\xa2\x16\x69\xc4\x6e\x44\x3f\xbd\xec\x52\xce\xe5" "\x41\xf2\xe0\x04\x4f\x5a\x55\x58\x37\xba\x45\x8d\x15\x53\xf6" "\x31\x91\x13\x8c\x51\xed\x08\x07\xdb"; uint8_t aes256_cbc_encrypted[144] = "\x7f\x1b\x92\xac\xc5\x16\x05\x55\x74\xac\xb4\xe0\x91\x8c\xf8" "\x0d\xa9\x72\xa5\x09\xb8\x44\xee\x55\x02\x13\xb7\x52\x0a\xf0" "\xac\xd0\x21\x0e\x58\x7b\x34\xfe\xdb\x36\x01\x60\x7d\x18\x3a" "\xa9\x15\x18\x5b\x13\xca\xdd\x77\x7d\xdf\x64\xc6\xd5\x75\x4b" "\x02\x02\x37\xb1\xf4\x33\xff\x93\xe6\x32\x08\xda\xcb\x5d\xa2" "\x8f\x17\x1f\x99\x92\x60\x22\x9d\x6b\xe6\xb2\x5e\xb0\x5d\x26" "\x3f\xde\xb8\xc1\xb0\x70\x80\x1c\x00\xd0\x93\x2b\xeb\x0f\xd7" "\x70\x7a\x9a\x7a\xa6\x21\x23\x2c\x02\xb7\xcd\x88\x10\x9c\x2d" "\x0c\xd3\xfa\xc1\x33\x5b\xe1\xa1\xd4\x3d\x8f\xb8\x50\xc5\xb5" "\x72\xdd\x6d\x32\x1f\x58\x00\x48\xbe"; static int get_cipher(struct ssh_cipher_struct *cipher, const char *ciphername) { struct ssh_cipher_struct *ciphers = ssh_get_ciphertab(); size_t i; int cmp; assert_non_null(cipher); for (i = 0; ciphers[i].name != NULL; i++) { cmp = strcmp(ciphername, ciphers[i].name); if (cmp == 0){ memcpy(cipher, &ciphers[i], sizeof(*cipher)); return SSH_OK; } } return SSH_ERROR; } static void torture_crypto_aes256_cbc(void **state) { uint8_t output[sizeof(cleartext)] = {0}; uint8_t iv[16] = {0}; struct ssh_cipher_struct cipher = {0}; int rc; (void)state; rc = get_cipher(&cipher, "aes256-cbc"); assert_int_equal(rc, SSH_OK); assert_non_null(cipher.set_encrypt_key); assert_non_null(cipher.encrypt); memcpy(iv, IV, sizeof(IV)); cipher.set_encrypt_key(&cipher, key, iv ); cipher.encrypt(&cipher, cleartext, output, sizeof(cleartext) ); assert_memory_equal(output, aes256_cbc_encrypted, sizeof(aes256_cbc_encrypted)); ssh_cipher_clear(&cipher); rc = get_cipher(&cipher, "aes256-cbc"); assert_int_equal(rc, SSH_OK); assert_non_null(cipher.set_decrypt_key); assert_non_null(cipher.decrypt); memcpy(iv, IV, sizeof(IV)); cipher.set_decrypt_key(&cipher, key, iv ); memset(output, '\0', sizeof(output)); cipher.decrypt(&cipher, aes256_cbc_encrypted, output, sizeof(aes256_cbc_encrypted) ); assert_memory_equal(output, cleartext, sizeof(cleartext)); ssh_cipher_clear(&cipher); } int torture_run_tests(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(torture_crypto_aes256_cbc), }; ssh_init(); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_hashes.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include "legacy.c" #include "dh.c" static int setup_rsa_key(void **state) { int rc=0; enum ssh_keytypes_e type; char *b64_key, *p; ssh_key key; const char *q; b64_key = strdup(torture_get_testkey_pub(SSH_KEYTYPE_RSA)); assert_non_null(b64_key); q = p = b64_key; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } type = ssh_key_type_from_name(q); assert_true(type == SSH_KEYTYPE_RSA); q = ++p; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); free(b64_key); *state = key; return 0; } static int teardown(void **state) { SSH_KEY_FREE(*state); return 0; } static void torture_md5_hash(void **state) { ssh_key pubkey = *state; char *hash = NULL; char *hexa = NULL; size_t hlen; int rc = 0; if (ssh_fips_mode()) { skip(); } rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, (unsigned char **)&hash, &hlen); if (ssh_fips_mode()) { /* When in FIPS mode, expect the call to fail */ assert_int_equal(rc, SSH_ERROR); } else { assert_int_equal(rc, SSH_OK); hexa = ssh_get_hexa((unsigned char *)hash, hlen); SSH_STRING_FREE_CHAR(hash); assert_string_equal(hexa, "50:15:a0:9b:92:bf:33:1c:01:c5:8c:fe:18:fa:ce:78"); SSH_STRING_FREE_CHAR(hexa); } } static void torture_sha1_hash(void **state) { ssh_key pubkey = *state; char *hash = NULL; char *sha1 = NULL; int rc = 0; size_t hlen; rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA1, (unsigned char **)&hash, &hlen); assert_true(rc == 0); sha1 = ssh_get_b64_unpadded((unsigned char *)hash, hlen); SSH_STRING_FREE_CHAR(hash); assert_string_equal(sha1, "6wP+houujQmxLBiFugTcoeoODCM"); SSH_STRING_FREE_CHAR(sha1); } static void torture_sha256_hash(void **state) { ssh_key pubkey = *state; char *hash = NULL; char *sha256 = NULL; int rc = 0; size_t hlen; rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, (unsigned char **)&hash, &hlen); assert_true(rc == 0); sha256 = ssh_get_b64_unpadded((unsigned char *)hash, hlen); SSH_STRING_FREE_CHAR(hash); assert_string_equal(sha256, "jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII"); SSH_STRING_FREE_CHAR(sha256); } static void torture_sha256_fingerprint(void **state) { ssh_key pubkey = *state; char *hash = NULL; char *sha256 = NULL; int rc = 0; size_t hlen; rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, (unsigned char **)&hash, &hlen); assert_true(rc == 0); sha256 = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256, (unsigned char *)hash, hlen); SSH_STRING_FREE_CHAR(hash); assert_string_equal(sha256, "SHA256:jXstVLLe84fSDo1kEYGn6iumnPCSorhaiWxnJz8VTII"); SSH_STRING_FREE_CHAR(sha256); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_md5_hash, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_sha1_hash, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_sha256_hash, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_sha256_fingerprint, setup_rsa_key, teardown), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_init.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include "torture.h" #include "libssh/libssh.h" static void torture_ssh_init(void **state) { int rc; (void) state; rc = ssh_init(); assert_int_equal(rc, SSH_OK); rc = ssh_finalize(); assert_int_equal(rc, SSH_OK); } static void torture_ssh_init_after_finalize(void **state) { int rc; (void) state; rc = ssh_init(); assert_int_equal(rc, SSH_OK); rc = ssh_finalize(); assert_int_equal(rc, SSH_OK); rc = ssh_init(); assert_int_equal(rc, SSH_OK); rc = ssh_finalize(); assert_int_equal(rc, SSH_OK); } static void torture_is_ssh_initialized(UNUSED_PARAM(void **state)) { int rc; bool initialized = false; /* Make sure the library is not initialized */ while (is_ssh_initialized()) { rc = ssh_finalize(); assert_return_code(rc, errno); } rc = ssh_init(); assert_return_code(rc, errno); initialized = is_ssh_initialized(); assert_true(initialized); rc = ssh_finalize(); assert_return_code(rc, errno); initialized = is_ssh_initialized(); assert_false(initialized); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_ssh_init), cmocka_unit_test(torture_ssh_init_after_finalize), cmocka_unit_test(torture_is_ssh_initialized), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_isipaddr.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "misc.c" #include "error.c" /* * Test the behavior of ssh_is_ipaddr() */ static void torture_ssh_is_ipaddr(void **state) { (void)state; assert_int_equal(ssh_is_ipaddr("127.0.0.1"),1); assert_int_equal(ssh_is_ipaddr("0.0.0.0"),1); assert_int_equal(ssh_is_ipaddr("1.1.1.1"),1); assert_int_equal(ssh_is_ipaddr("255.255.255.255"),1); assert_int_equal(ssh_is_ipaddr("128.128.128.128"),1); assert_int_equal(ssh_is_ipaddr("1.10.100.1"),1); assert_int_equal(ssh_is_ipaddr("0.1.10.100"),1); assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),1); assert_int_equal(ssh_is_ipaddr("fe80:0000:0000:0000:0202:b3ff:fe1e:8329"),1); assert_int_equal(ssh_is_ipaddr("fe80:0:0:0:202:b3ff:fe1e:8329"),1); assert_int_equal(ssh_is_ipaddr("fe80::202:b3ff:fe1e:8329"),1); assert_int_equal(ssh_is_ipaddr("::1"),1); assert_int_equal(ssh_is_ipaddr("::ffff:192.0.2.128"),1); assert_int_equal(ssh_is_ipaddr("0.0.0.0.0"),0); assert_int_equal(ssh_is_ipaddr("0.0.0.0.a"),0); assert_int_equal(ssh_is_ipaddr("a.0.0.0"),0); assert_int_equal(ssh_is_ipaddr("0a.0.0.0.0"),0); assert_int_equal(ssh_is_ipaddr(""),0); assert_int_equal(ssh_is_ipaddr("0.0.0."),0); assert_int_equal(ssh_is_ipaddr("0.0"),0); assert_int_equal(ssh_is_ipaddr("0"),0); /* * FIXME: Temporary workaround for Wine bug */ #ifndef _WIN32 assert_int_equal(ssh_is_ipaddr("255.255.255"),0); #endif assert_int_equal(ssh_is_ipaddr("2001:0db8:85a3:0000:0000:8a2e:0370:7334:1002"), 0); assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0); assert_int_equal(ssh_is_ipaddr("fe80:x:202:b3ff:fe1e:8329"), 0); assert_int_equal(ssh_is_ipaddr(":1"), 0); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_ssh_is_ipaddr) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_keyfiles.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include "legacy.c" #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #ifdef HAVE_DSA #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" #endif static int setup_rsa_key(void **state) { ssh_session session; unlink(LIBSSH_RSA_TESTKEY); unlink(LIBSSH_RSA_TESTKEY ".pub"); torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); session = ssh_new(); *state = session; return 0; } #ifdef HAVE_DSA static int setup_dsa_key(void **state) { ssh_session session; unlink(LIBSSH_DSA_TESTKEY); unlink(LIBSSH_DSA_TESTKEY ".pub"); torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_DSS, 0)); torture_write_file(LIBSSH_DSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS)); session = ssh_new(); *state = session; return 0; } #endif static int setup_both_keys(void **state) { int rc; rc = setup_rsa_key(state); if (rc != 0) { return rc; } #ifdef HAVE_DSA ssh_free(*state); rc = setup_dsa_key(state); #endif return rc; } static int setup_both_keys_passphrase(void **state) { ssh_session session; torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_RSA, 1)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); #ifdef HAVE_DSA torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_DSS, 1)); torture_write_file(LIBSSH_DSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS)); #endif session = ssh_new(); *state = session; return 0; } static int teardown(void **state) { #ifdef HAVE_DSA unlink(LIBSSH_DSA_TESTKEY); unlink(LIBSSH_DSA_TESTKEY ".pub"); #endif unlink(LIBSSH_RSA_TESTKEY); unlink(LIBSSH_RSA_TESTKEY ".pub"); ssh_free(*state); return 0; } static void torture_pubkey_from_file(void **state) { ssh_session session = *state; ssh_string pubkey = NULL; int type, rc; rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type); assert_true(rc == 0); SSH_STRING_FREE(pubkey); /* test if it returns 1 if pubkey doesn't exist */ unlink(LIBSSH_RSA_TESTKEY ".pub"); rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type); assert_true(rc == 1); /* This free is unnecessary, but the static analyser does not know */ SSH_STRING_FREE(pubkey); /* test if it returns -1 if privkey doesn't exist */ unlink(LIBSSH_RSA_TESTKEY); rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey, &type); assert_true(rc == -1); /* This free is unnecessary, but the static analyser does not know */ SSH_STRING_FREE(pubkey); } static int torture_read_one_line(const char *filename, char *buffer, size_t len) { FILE *fp; size_t nmemb; fp = fopen(filename, "r"); if (fp == NULL) { return -1; } nmemb = fread(buffer, len - 2, 1, fp); if (nmemb != 0 || ferror(fp)) { fclose(fp); return -1; } buffer[len - 1] = '\0'; fclose(fp); return 0; } static void torture_pubkey_generate_from_privkey(void **state) { ssh_session session = *state; ssh_private_key privkey = NULL; ssh_public_key pubkey = NULL; ssh_string pubkey_orig = NULL; ssh_string pubkey_new = NULL; char pubkey_line_orig[512] = {0}; char pubkey_line_new[512] = {0}; char *p; int type_orig = 0; int type_new = 0; int rc; /* read the publickey */ rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey_orig, &type_orig); assert_true(rc == 0); assert_non_null(pubkey_orig); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_orig, sizeof(pubkey_line_orig)); assert_true(rc == 0); /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_RSA_TESTKEY ".pub"); privkey = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL); assert_non_null(privkey); pubkey = publickey_from_privatekey(privkey); assert_non_null(pubkey); type_new = privkey->type; privatekey_free(privkey); pubkey_new = publickey_to_string(pubkey); publickey_free(pubkey); assert_non_null(pubkey_new); assert_true(ssh_string_len(pubkey_orig) == ssh_string_len(pubkey_new)); assert_memory_equal(ssh_string_data(pubkey_orig), ssh_string_data(pubkey_new), ssh_string_len(pubkey_orig)); rc = ssh_publickey_to_file(session, LIBSSH_RSA_TESTKEY ".pub", pubkey_new, type_new); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_new, sizeof(pubkey_line_new)); assert_true(rc == 0); /* do not compare hostname */ p = strrchr(pubkey_line_orig, ' '); if (p != NULL) { *p = '\0'; } p = strrchr(pubkey_line_new, ' '); if (p != NULL) { *p = '\0'; } assert_string_equal(pubkey_line_orig, pubkey_line_new); SSH_STRING_FREE(pubkey_orig); SSH_STRING_FREE(pubkey_new); } /** * @brief tests the privatekey_from_file function without passphrase */ static void torture_privatekey_from_file(void **state) { ssh_session session = *state; ssh_private_key key = NULL; key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, SSH_KEYTYPE_RSA, NULL); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #ifdef HAVE_DSA key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, SSH_KEYTYPE_DSS, NULL); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #endif /* Test the automatic type discovery */ key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #ifdef HAVE_DSA key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, 0, NULL); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #endif } /** * @brief tests the privatekey_from_file function with passphrase */ static void torture_privatekey_from_file_passphrase(void **state) { ssh_session session = *state; ssh_private_key key = NULL; key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, SSH_KEYTYPE_RSA, TORTURE_TESTKEY_PASSWORD); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #ifdef HAVE_DSA key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, SSH_KEYTYPE_DSS, TORTURE_TESTKEY_PASSWORD); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #endif /* Test the automatic type discovery */ key = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, TORTURE_TESTKEY_PASSWORD); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #ifdef HAVE_DSA key = privatekey_from_file(session, LIBSSH_DSA_TESTKEY, 0, TORTURE_TESTKEY_PASSWORD); assert_non_null(key); if (key != NULL) { privatekey_free(key); key = NULL; } #endif } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pubkey_from_file, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pubkey_generate_from_privkey, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_privatekey_from_file, setup_both_keys, teardown), cmocka_unit_test_setup_teardown(torture_privatekey_from_file_passphrase, setup_both_keys_passphrase, teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_knownhosts_parsing.c ================================================ #include "config.h" #include #define LIBSSH_STATIC #include #include "torture.h" #include "knownhosts.c" #if (defined _WIN32) || (defined _WIN64) #ifndef S_IRWXO #define S_IRWXO 0 #endif #ifndef S_IRWXG #define S_IRWXG 0 #endif #endif #define LOCALHOST_RSA_LINE "localhost,127.0.0.1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDD7g+vV5cvxxGN0Ldmda4WZCPgRaxV1tV+1KRZoGUNUI61h0X4bmmGaAPRQBCz4G1d9bawqDqEqnpFWazrxBU5cQtISSjzuDJKovLGliky/ShTszee1Thszg3qVNk9gGOWj7jn/HDaOxRlp003Bp47MOdnMnK/oftllFDfY2fF5IRpE6sSIGtg2ZDtF95TV5/9W2oMOIAy8u/83tuibYlNPa1X/von5LgdaPLn6Bk16bQKIhAhlMtFZH8MBYEWe4ZtOGaSWKOsK9MM/RTMlwPi6PkfoHNl4MCMupjx+CdLXwbQEt9Ww+bBIaCui2VWBEiruVbIgJh0W2Tal0e2BzYZ What a Wurst!" #define LOCALHOST_ECDSA_SHA1_NISTP256_LINE "localhost ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFWmI0n0Tn5+zR7pPGcKYszRbJ/T0T3QfzRBSMMiyebGKRY8tjkU5h2l/UMugzOrOyWqMGQDgQn+a0aMunhKMg0=" #define LOCALHOST_DEFAULT_ED25519 "localhost ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define LOCALHOST_PORT_ED25519 "[localhost]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define LOCALHOST_PATTERN_ED25519 "local* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define LOCALHOST_HASHED_ED25519 "|1|ayWjmTf9mYgj7PuQNVOa7Lqkj5s=|hkbEh8FN6IkLo6t6GQGuBwamgsM= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define LOCALHOST_PORT_WILDCARD "[localhost]:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define LOCALHOST_STANDARD_PORT "[localhost]:22 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA7M22fXD7OiS7kGMXP+OoIjCa+J+5sq8SgAZfIOmDgM" #define TMP_FILE_NAME "/tmp/known_hosts_XXXXXX" const char template[] = "temp_dir_XXXXXX"; static int setup_knownhosts_file(void **state) { char *tmp_file = NULL; size_t nwritten; FILE *fp = NULL; int rc = 0; tmp_file = torture_create_temp_file(TMP_FILE_NAME); assert_non_null(tmp_file); *state = tmp_file; fp = fopen(tmp_file, "w"); assert_non_null(fp); nwritten = fwrite(LOCALHOST_PATTERN_ED25519, sizeof(char), strlen(LOCALHOST_PATTERN_ED25519), fp); if (nwritten != strlen(LOCALHOST_PATTERN_ED25519)) { rc = -1; goto close_fp; } nwritten = fwrite("\n", sizeof(char), 1, fp); if (nwritten != 1) { rc = -1; goto close_fp; } nwritten = fwrite(LOCALHOST_RSA_LINE, sizeof(char), strlen(LOCALHOST_RSA_LINE), fp); if (nwritten != strlen(LOCALHOST_RSA_LINE)) { rc = -1; goto close_fp; } close_fp: fclose(fp); return rc; } static int setup_knownhosts_file_duplicate(void **state) { char *tmp_file = NULL; size_t nwritten; FILE *fp = NULL; int rc = 0; tmp_file = torture_create_temp_file(TMP_FILE_NAME); assert_non_null(tmp_file); *state = tmp_file; fp = fopen(tmp_file, "w"); assert_non_null(fp); /* ed25519 key */ nwritten = fwrite(LOCALHOST_PATTERN_ED25519, sizeof(char), strlen(LOCALHOST_PATTERN_ED25519), fp); if (nwritten != strlen(LOCALHOST_PATTERN_ED25519)) { rc = -1; goto close_fp; } nwritten = fwrite("\n", sizeof(char), 1, fp); if (nwritten != 1) { rc = -1; goto close_fp; } /* RSA key */ nwritten = fwrite(LOCALHOST_RSA_LINE, sizeof(char), strlen(LOCALHOST_RSA_LINE), fp); if (nwritten != strlen(LOCALHOST_RSA_LINE)) { rc = -1; goto close_fp; } nwritten = fwrite("\n", sizeof(char), 1, fp); if (nwritten != 1) { rc = -1; goto close_fp; } /* ed25519 key again */ nwritten = fwrite(LOCALHOST_PATTERN_ED25519, sizeof(char), strlen(LOCALHOST_PATTERN_ED25519), fp); if (nwritten != strlen(LOCALHOST_PATTERN_ED25519)) { rc = -1; goto close_fp; } nwritten = fwrite("\n", sizeof(char), 1, fp); if (nwritten != 1) { rc = -1; goto close_fp; } close_fp: fclose(fp); return rc; } static int teardown_knownhosts_file(void **state) { char *tmp_file = *state; if (tmp_file == NULL) { return -1; } unlink(tmp_file); SAFE_FREE(tmp_file); return 0; } static void torture_knownhosts_parse_line_rsa(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_RSA_LINE, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_RSA); assert_string_equal(entry->comment, "What a Wurst!"); SSH_KNOWNHOSTS_ENTRY_FREE(entry); rc = ssh_known_hosts_parse_line("127.0.0.1", LOCALHOST_RSA_LINE, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "127.0.0.1"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_RSA); assert_string_equal(entry->comment, "What a Wurst!"); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_ecdsa(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_ECDSA_SHA1_NISTP256_LINE, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ECDSA_P256); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_default_ed25519(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_DEFAULT_ED25519, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_port_ed25519(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("[localhost]:2222", LOCALHOST_PORT_ED25519, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "[localhost]:2222"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_port_wildcard(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_PORT_WILDCARD, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_standard_port(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_STANDARD_PORT, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_pattern_ed25519(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_PATTERN_ED25519, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_parse_line_hashed_ed25519(void **state) { struct ssh_knownhosts_entry *entry = NULL; int rc; (void) state; rc = ssh_known_hosts_parse_line("localhost", LOCALHOST_HASHED_ED25519, &entry); assert_int_equal(rc, SSH_OK); assert_string_equal(entry->hostname, "localhost"); assert_non_null(entry->unparsed); assert_non_null(entry->publickey); assert_int_equal(ssh_key_type(entry->publickey), SSH_KEYTYPE_ED25519); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } static void torture_knownhosts_read_file(void **state) { const char *knownhosts_file = *state; struct ssh_list *entry_list = NULL; struct ssh_iterator *it = NULL; struct ssh_knownhosts_entry *entry = NULL; enum ssh_keytypes_e type; int rc; rc = ssh_known_hosts_read_entries("localhost", knownhosts_file, &entry_list); assert_int_equal(rc, SSH_OK); assert_non_null(entry_list); it = ssh_list_get_iterator(entry_list); assert_non_null(it); /* First key in known hosts file is ED25519 */ entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); assert_non_null(entry); assert_string_equal(entry->hostname, "localhost"); type = ssh_key_type(entry->publickey); assert_int_equal(type, SSH_KEYTYPE_ED25519); assert_non_null(it->next); it = it->next; /* Second key in known hosts file is RSA */ entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); assert_non_null(entry); assert_string_equal(entry->hostname, "localhost"); type = ssh_key_type(entry->publickey); assert_int_equal(type, SSH_KEYTYPE_RSA); assert_null(it->next); it = ssh_list_get_iterator(entry_list); for (;it != NULL; it = it->next) { entry = ssh_iterator_value(struct ssh_knownhosts_entry *, it); SSH_KNOWNHOSTS_ENTRY_FREE(entry); } ssh_list_free(entry_list); } static void torture_knownhosts_get_algorithms_names(void **state) { const char *knownhosts_file = *state; ssh_session session; const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa"; char *names = NULL; bool process_config = false; session = ssh_new(); assert_non_null(session); /* This makes sure the global configuration file is not processed */ ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file); names = ssh_known_hosts_get_algorithms_names(session); assert_non_null(names); assert_string_equal(names, expect); SAFE_FREE(names); ssh_free(session); } static void torture_knownhosts_algorithms_wanted(void **state) { const char *knownhosts_file = *state; char *algo_list = NULL; ssh_session session; bool process_config = false; const char *wanted = "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256," "rsa-sha2-256,ecdsa-sha2-nistp521"; const char *expect = "rsa-sha2-256,ecdsa-sha2-nistp384," "ecdsa-sha2-nistp256,ecdsa-sha2-nistp521"; int verbose = 4; session = ssh_new(); assert_non_null(session); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbose); /* This makes sure the global configuration file is not processed */ ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); /* Set the wanted list of hostkeys, ordered by preference */ ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, wanted); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file); algo_list = ssh_client_select_hostkeys(session); assert_non_null(algo_list); assert_string_equal(algo_list, expect); free(algo_list); ssh_free(session); } static void torture_knownhosts_algorithms_negative(UNUSED_PARAM(void **state)) { const char *wanted = NULL; const char *expect = NULL; char *algo_list = NULL; char *cwd = NULL; char *tmp_dir = NULL; bool process_config = false; int verbose = 4; int rc = 0; ssh_session session; /* Create temporary directory */ cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); session = ssh_new(); assert_non_null(session); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbose); ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); /* Test with unknown key type in known_hosts */ wanted = "rsa-sha2-256"; ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, wanted); torture_write_file("unknown_key_type", "localhost unknown AAAABBBBCCCC"); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "unknown_key_type"); algo_list = ssh_client_select_hostkeys(session); assert_non_null(algo_list); assert_string_equal(algo_list, wanted); SAFE_FREE(algo_list); /* Test with unsupported, but existing types */ wanted = "rsa-sha2-256-cert-v01@openssh.com," "rsa-sha2-512-cert-v01@openssh.com"; ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, wanted); algo_list = ssh_client_select_hostkeys(session); assert_null(algo_list); /* In FIPS mode, test filtering keys not allowed */ if (ssh_fips_mode()) { wanted = "ssh-ed25519,rsa-sha2-256,ssh-rsa"; expect = "rsa-sha2-256"; ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, wanted); torture_write_file("no_fips", LOCALHOST_DEFAULT_ED25519); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "no_fips"); algo_list = ssh_client_select_hostkeys(session); assert_non_null(algo_list); assert_string_equal(algo_list, expect); SAFE_FREE(algo_list); } ssh_free(session); /* Teardown */ rc = torture_change_dir(cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(tmp_dir); assert_int_equal(rc, 0); SAFE_FREE(tmp_dir); SAFE_FREE(cwd); } #ifndef _WIN32 /* There is no /dev/null on Windows */ static void torture_knownhosts_host_exists(void **state) { const char *knownhosts_file = *state; enum ssh_known_hosts_e found; ssh_session session; session = ssh_new(); assert_non_null(session); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file); /* This makes sure the system's known_hosts are not used */ ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/dev/null"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* This makes sure the check will not fail when the system's known_hosts is * not accessible*/ ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "./unaccessible"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* This makes sure the check will fail for an unknown host */ ssh_options_set(session, SSH_OPTIONS_HOST, "wurstbrot"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_UNKNOWN); ssh_free(session); } static void torture_knownhosts_host_exists_global(void **state) { const char *knownhosts_file = *state; enum ssh_known_hosts_e found; ssh_session session; session = ssh_new(); assert_non_null(session); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, knownhosts_file); /* This makes sure the user's known_hosts are not used */ ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* This makes sure the check will not fail when the user's known_hosts is * not accessible*/ ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "./unaccessible"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_OK); /* This makes sure the check will fail for an unknown host */ ssh_options_set(session, SSH_OPTIONS_HOST, "wurstbrot"); found = ssh_session_has_known_hosts_entry(session); assert_int_equal(found, SSH_KNOWN_HOSTS_UNKNOWN); ssh_free(session); } static void torture_knownhosts_algorithms(void **state) { const char *knownhosts_file = *state; char *algo_list = NULL; ssh_session session; bool process_config = false; const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa," "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," "ecdsa-sha2-nistp256" #ifdef HAVE_DSA ",ssh-dss" #endif ; const char *expect_fips = "rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp521," "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"; session = ssh_new(); assert_non_null(session); /* This makes sure the global configuration file is not processed */ ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, knownhosts_file); /* This makes sure the system's known_hosts are not used */ ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/dev/null"); algo_list = ssh_client_select_hostkeys(session); assert_non_null(algo_list); if (ssh_fips_mode()) { assert_string_equal(algo_list, expect_fips); } else { assert_string_equal(algo_list, expect); } free(algo_list); ssh_free(session); } static void torture_knownhosts_algorithms_global(void **state) { const char *knownhosts_file = *state; char *algo_list = NULL; ssh_session session; bool process_config = false; const char *expect = "ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa," "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384," "ecdsa-sha2-nistp256" #ifdef HAVE_DSA ",ssh-dss" #endif ; const char *expect_fips = "rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp521," "ecdsa-sha2-nistp384,ecdsa-sha2-nistp256"; session = ssh_new(); assert_non_null(session); /* This makes sure the global configuration file is not processed */ ssh_options_set(session, SSH_OPTIONS_PROCESS_CONFIG, &process_config); ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); /* This makes sure the current-user's known hosts are not used */ ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/dev/null"); ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, knownhosts_file); algo_list = ssh_client_select_hostkeys(session); assert_non_null(algo_list); if (ssh_fips_mode()) { assert_string_equal(algo_list, expect_fips); } else { assert_string_equal(algo_list, expect); } free(algo_list); ssh_free(session); } #endif /* _WIN32 There is no /dev/null on Windows */ int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_knownhosts_parse_line_rsa), cmocka_unit_test(torture_knownhosts_parse_line_ecdsa), cmocka_unit_test(torture_knownhosts_parse_line_default_ed25519), cmocka_unit_test(torture_knownhosts_parse_line_port_ed25519), cmocka_unit_test(torture_knownhosts_parse_line_port_wildcard), cmocka_unit_test(torture_knownhosts_parse_line_standard_port), cmocka_unit_test(torture_knownhosts_parse_line_pattern_ed25519), cmocka_unit_test(torture_knownhosts_parse_line_hashed_ed25519), cmocka_unit_test_setup_teardown(torture_knownhosts_read_file, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_read_file, setup_knownhosts_file_duplicate, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_get_algorithms_names, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms_wanted, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test(torture_knownhosts_algorithms_negative), #ifndef _WIN32 cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_host_exists_global, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms, setup_knownhosts_file, teardown_knownhosts_file), cmocka_unit_test_setup_teardown(torture_knownhosts_algorithms_global, setup_knownhosts_file, teardown_knownhosts_file), #endif }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_list.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "error.c" #include "misc.c" static void torture_ssh_list_new(void **state) { struct ssh_list *xlist; (void) state; xlist = ssh_list_new(); assert_non_null(xlist); assert_null(xlist->root); assert_null(xlist->end); assert_int_equal(ssh_list_count(xlist), 0); ssh_list_free(xlist); } static void torture_ssh_list_append(void **state) { struct ssh_list *xlist; int rc; (void) state; xlist = ssh_list_new(); assert_non_null(xlist); rc = ssh_list_append(xlist, "item1"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item1"); assert_string_equal((const char *) xlist->end->data, "item1"); rc = ssh_list_append(xlist, "item2"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item1"); assert_string_equal((const char *) xlist->end->data, "item2"); rc = ssh_list_append(xlist, "item3"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->root->next); assert_non_null(xlist->root->next->data); assert_non_null(xlist->root->next->next); assert_non_null(xlist->root->next->next->data); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item1"); assert_string_equal((const char *) xlist->root->next->data, "item2"); assert_string_equal((const char *) xlist->root->next->next->data, "item3"); assert_string_equal((const char *) xlist->end->data, "item3"); assert_int_equal(ssh_list_count(xlist), 3); ssh_list_free(xlist); } static void torture_ssh_list_prepend(void **state) { struct ssh_list *xlist; int rc; (void) state; xlist = ssh_list_new(); assert_non_null(xlist); rc = ssh_list_prepend(xlist, "item1"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item1"); assert_string_equal((const char *) xlist->end->data, "item1"); rc = ssh_list_append(xlist, "item2"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item1"); assert_string_equal((const char *) xlist->end->data, "item2"); rc = ssh_list_prepend(xlist, "item3"); assert_true(rc == 0); assert_non_null(xlist->root); assert_non_null(xlist->root->data); assert_non_null(xlist->root->next); assert_non_null(xlist->root->next->data); assert_non_null(xlist->root->next->next); assert_non_null(xlist->end); assert_non_null(xlist->end->data); assert_string_equal((const char *) xlist->root->data, "item3"); assert_string_equal((const char *) xlist->root->next->data, "item1"); assert_string_equal((const char *) xlist->root->next->next->data, "item2"); assert_string_equal((const char *) xlist->end->data, "item2"); assert_int_equal(ssh_list_count(xlist), 3); ssh_list_free(xlist); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_ssh_list_new), cmocka_unit_test(torture_ssh_list_append), cmocka_unit_test(torture_ssh_list_prepend), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_misc.c ================================================ #include "config.h" #ifdef HAVE_UNISTD_H #include #endif #include #ifndef _WIN32 #define _POSIX_PTHREAD_SEMANTICS #include #endif #define LIBSSH_STATIC #include #include "torture.h" #include "misc.c" #include "error.c" #define TORTURE_TEST_DIR "/usr/local/bin/truc/much/.." const char template[] = "temp_dir_XXXXXX"; static int setup(void **state) { ssh_session session = ssh_new(); *state = session; return 0; } static int teardown(void **state) { ssh_free(*state); return 0; } static void torture_get_user_home_dir(void **state) { #ifndef _WIN32 struct passwd *pwd = getpwuid(getuid()); #endif /* _WIN32 */ char *user; (void) state; user = ssh_get_user_home_dir(); assert_non_null(user); #ifndef _WIN32 assert_string_equal(user, pwd->pw_dir); #endif /* _WIN32 */ SAFE_FREE(user); } static void torture_basename(void **state) { char *path; (void) state; path=ssh_basename(TORTURE_TEST_DIR "/test"); assert_non_null(path); assert_string_equal(path, "test"); SAFE_FREE(path); path=ssh_basename(TORTURE_TEST_DIR "/test/"); assert_non_null(path); assert_string_equal(path, "test"); SAFE_FREE(path); } static void torture_dirname(void **state) { char *path; (void) state; path=ssh_dirname(TORTURE_TEST_DIR "/test"); assert_non_null(path); assert_string_equal(path, TORTURE_TEST_DIR ); SAFE_FREE(path); path=ssh_dirname(TORTURE_TEST_DIR "/test/"); assert_non_null(path); assert_string_equal(path, TORTURE_TEST_DIR); SAFE_FREE(path); } static void torture_ntohll(void **state) { uint64_t value = 0x0123456789abcdef; uint32_t sample = 1; unsigned char *ptr = (unsigned char *) &sample; uint64_t check; (void) state; if (ptr[0] == 1){ /* we're in little endian */ check = 0xefcdab8967452301; } else { /* big endian */ check = value; } value = ntohll(value); assert_true(value == check); } #ifdef _WIN32 static void torture_path_expand_tilde_win(void **state) { char *d; (void) state; d = ssh_path_expand_tilde("~\\.ssh"); assert_non_null(d); print_message("Expanded path: %s\n", d); free(d); d = ssh_path_expand_tilde("/guru/meditation"); assert_string_equal(d, "/guru/meditation"); free(d); } #else /* _WIN32 */ static void torture_path_expand_tilde_unix(void **state) { char h[256]; char *d; char *user; char *home; (void) state; user = getenv("USER"); if (user == NULL){ user = getenv("LOGNAME"); } /* in certain CIs there no such variables */ if (!user){ struct passwd *pw = getpwuid(getuid()); if (pw){ user = pw->pw_name; } } home = getenv("HOME"); assert_non_null(home); snprintf(h, 256 - 1, "%s/.ssh", home); d = ssh_path_expand_tilde("~/.ssh"); assert_non_null(d); assert_string_equal(d, h); free(d); d = ssh_path_expand_tilde("/guru/meditation"); assert_non_null(d); assert_string_equal(d, "/guru/meditation"); free(d); snprintf(h, 256 - 1, "~%s/.ssh", user); d = ssh_path_expand_tilde(h); assert_non_null(d); snprintf(h, 256 - 1, "%s/.ssh", home); assert_string_equal(d, h); free(d); } #endif /* _WIN32 */ static void torture_path_expand_escape(void **state) { ssh_session session = *state; const char *s = "%d/%h/by/%r"; char *e; session->opts.sshdir = strdup("guru"); session->opts.host = strdup("meditation"); session->opts.username = strdup("root"); e = ssh_path_expand_escape(session, s); assert_non_null(e); assert_string_equal(e, "guru/meditation/by/root"); free(e); } static void torture_path_expand_known_hosts(void **state) { ssh_session session = *state; char *tmp; session->opts.sshdir = strdup("/home/guru/.ssh"); tmp = ssh_path_expand_escape(session, "%d/known_hosts"); assert_non_null(tmp); assert_string_equal(tmp, "/home/guru/.ssh/known_hosts"); free(tmp); } static void torture_path_expand_percent(void **state) { ssh_session session = *state; char *tmp; session->opts.sshdir = strdup("/home/guru/.ssh"); tmp = ssh_path_expand_escape(session, "%d/config%%1"); assert_non_null(tmp); assert_string_equal(tmp, "/home/guru/.ssh/config%1"); free(tmp); } static void torture_timeout_elapsed(void **state){ struct ssh_timestamp ts; (void) state; ssh_timestamp_init(&ts); usleep(50000); assert_true(ssh_timeout_elapsed(&ts,25)); assert_false(ssh_timeout_elapsed(&ts,30000)); assert_false(ssh_timeout_elapsed(&ts,75)); assert_true(ssh_timeout_elapsed(&ts,0)); assert_false(ssh_timeout_elapsed(&ts,-1)); } static void torture_timeout_update(void **state){ struct ssh_timestamp ts; (void) state; ssh_timestamp_init(&ts); usleep(50000); assert_int_equal(ssh_timeout_update(&ts,25), 0); assert_in_range(ssh_timeout_update(&ts,30000),29000,29960); assert_in_range(ssh_timeout_update(&ts,75),1,40); assert_int_equal(ssh_timeout_update(&ts,0),0); assert_int_equal(ssh_timeout_update(&ts,-1),-1); } static void torture_ssh_analyze_banner(void **state) { int rc = 0; ssh_session session = NULL; (void) state; #define reset_banner_test() \ do { \ rc = 0; \ ssh_free(session); \ session = ssh_new(); \ assert_non_null(session); \ } while (0) #define assert_banner_rejected(is_server) \ do { \ rc = ssh_analyze_banner(session, is_server); \ assert_int_not_equal(0, rc); \ } while (0); #define assert_client_banner_rejected(banner) \ do { \ reset_banner_test(); \ session->clientbanner = strdup(banner); \ assert_non_null(session->clientbanner); \ assert_banner_rejected(1 /*server*/); \ SAFE_FREE(session->clientbanner); \ } while (0) #define assert_server_banner_rejected(banner) \ do { \ reset_banner_test(); \ session->serverbanner = strdup(banner); \ assert_non_null(session->serverbanner); \ assert_banner_rejected(0 /*client*/); \ SAFE_FREE(session->serverbanner); \ } while (0) #define assert_banner_accepted(is_server) \ do { \ rc = ssh_analyze_banner(session, is_server); \ assert_int_equal(0, rc); \ } while (0) #define assert_client_banner_accepted(banner) \ do { \ reset_banner_test(); \ session->clientbanner = strdup(banner); \ assert_non_null(session->clientbanner); \ assert_banner_accepted(1 /*server*/); \ SAFE_FREE(session->clientbanner); \ } while (0) #define assert_server_banner_accepted(banner) \ do { \ reset_banner_test(); \ session->serverbanner = strdup(banner); \ assert_non_null(session->serverbanner); \ assert_banner_accepted(0 /*client*/); \ SAFE_FREE(session->serverbanner); \ } while (0) /* no banner is set */ reset_banner_test(); assert_banner_rejected(0 /*client*/); reset_banner_test(); assert_banner_rejected(1 /*server*/); /* banner is too short */ assert_client_banner_rejected("abc"); assert_server_banner_rejected("abc"); /* banner doesn't start "SSH-" */ assert_client_banner_rejected("abc-2.0"); assert_server_banner_rejected("abc-2.0"); /* SSH v1 */ assert_client_banner_rejected("SSH-1.0"); assert_server_banner_rejected("SSH-1.0"); /* SSH v1.9 gets counted as both v1 and v2 */ assert_client_banner_accepted("SSH-1.9"); assert_server_banner_accepted("SSH-1.9"); /* SSH v2 */ assert_client_banner_accepted("SSH-2.0"); assert_server_banner_accepted("SSH-2.0"); /* OpenSSH banners: too short to extract major and minor versions */ assert_client_banner_accepted("SSH-2.0-OpenSSH"); assert_int_equal(0, session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH"); assert_int_equal(0, session->openssh); /* OpenSSH banners: big enough to extract major and minor versions */ assert_client_banner_accepted("SSH-2.0-OpenSSH_5.9p1"); assert_int_equal(SSH_VERSION_INT(5, 9, 0), session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH_5.9p1"); assert_int_equal(SSH_VERSION_INT(5, 9, 0), session->openssh); assert_client_banner_accepted("SSH-2.0-OpenSSH_1.99"); assert_int_equal(SSH_VERSION_INT(1, 99, 0), session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH_1.99"); assert_int_equal(SSH_VERSION_INT(1, 99, 0), session->openssh); /* OpenSSH banners: major, minor version limits result in zero */ assert_client_banner_accepted("SSH-2.0-OpenSSH_0.99p1"); assert_int_equal(0, session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH_0.99p1"); assert_int_equal(0, session->openssh); assert_client_banner_accepted("SSH-2.0-OpenSSH_1.101p1"); assert_int_equal(0, session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH_1.101p1"); assert_int_equal(0, session->openssh); /* OpenSSH banners: bogus major results in zero */ assert_client_banner_accepted("SSH-2.0-OpenSSH_X.9p1"); assert_int_equal(0, session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH_X.9p1"); assert_int_equal(0, session->openssh); /* OpenSSH banners: bogus minor results in zero */ assert_server_banner_accepted("SSH-2.0-OpenSSH_5.Yp1"); assert_int_equal(0, session->openssh); assert_client_banner_accepted("SSH-2.0-OpenSSH_5.Yp1"); assert_int_equal(0, session->openssh); /* OpenSSH banners: ssh-keyscan(1) */ assert_client_banner_accepted("SSH-2.0-OpenSSH-keyscan"); assert_int_equal(0, session->openssh); assert_server_banner_accepted("SSH-2.0-OpenSSH-keyscan"); assert_int_equal(0, session->openssh); ssh_free(session); } static void torture_ssh_dir_writeable(UNUSED_PARAM(void **state)) { char *tmp_dir = NULL; int rc = 0; FILE *file = NULL; char buffer[256]; tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); rc = ssh_dir_writeable(tmp_dir); assert_int_equal(rc, 1); /* Create a file */ snprintf(buffer, sizeof(buffer), "%s/a", tmp_dir); file = fopen(buffer, "w"); assert_non_null(file); fprintf(file, "Hello world!\n"); fclose(file); /* Negative test for checking a normal file */ rc = ssh_dir_writeable(buffer); assert_int_equal(rc, 0); /* Negative test for non existent file */ snprintf(buffer, sizeof(buffer), "%s/b", tmp_dir); rc = ssh_dir_writeable(buffer); assert_int_equal(rc, 0); #ifndef _WIN32 /* Negative test for directory without write permission */ rc = ssh_mkdir(buffer, 0400); assert_return_code(rc, errno); rc = ssh_dir_writeable(buffer); assert_int_equal(rc, 0); #endif torture_rmdirs(tmp_dir); SAFE_FREE(tmp_dir); } static void torture_ssh_mkdirs(UNUSED_PARAM(void **state)) { char *tmp_dir = NULL; char *cwd = NULL; char buffer[256]; ssize_t count = 0; int rc; /* Get current working directory */ cwd = torture_get_current_working_dir(); assert_non_null(cwd); /* Create a base disposable directory */ tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); /* Create a single directory */ count = snprintf(buffer, sizeof(buffer), "%s/a", tmp_dir); assert_return_code(count, errno); rc = ssh_mkdirs(buffer, 0700); assert_return_code(rc, errno); rc = ssh_dir_writeable(buffer); assert_int_equal(rc, 1); /* Create directories recursively */ count = snprintf(buffer, sizeof(buffer), "%s/b/c/d", tmp_dir); assert_return_code(count, errno); rc = ssh_mkdirs(buffer, 0700); assert_return_code(rc, errno); rc = ssh_dir_writeable(buffer); assert_int_equal(rc, 1); /* Change directory */ rc = torture_change_dir(tmp_dir); assert_return_code(rc, errno); /* Create single local directory */ rc = ssh_mkdirs("e", 0700); assert_return_code(rc, errno); rc = ssh_dir_writeable("e"); assert_int_equal(rc, 1); /* Create local directories recursively */ rc = ssh_mkdirs("f/g/h", 0700); assert_return_code(rc, errno); rc = ssh_dir_writeable("f/g/h"); assert_int_equal(rc, 1); /* Negative test for creating "." directory */ rc = ssh_mkdirs(".", 0700); assert_int_equal(rc, -1); assert_int_equal(errno, EINVAL); /* Negative test for creating "/" directory */ rc = ssh_mkdirs("/", 0700); assert_int_equal(rc, -1); assert_int_equal(errno, EINVAL); /* Negative test for creating "" directory */ rc = ssh_mkdirs("", 0700); assert_int_equal(rc, -1); assert_int_equal(errno, EINVAL); /* Negative test for creating NULL directory */ rc = ssh_mkdirs(NULL, 0700); assert_int_equal(rc, -1); assert_int_equal(errno, EINVAL); /* Negative test for creating existing directory */ rc = ssh_mkdirs("a", 0700); assert_int_equal(rc, -1); assert_int_equal(errno, EEXIST); /* Return to original directory */ rc = torture_change_dir(cwd); assert_return_code(rc, errno); /* Cleanup */ torture_rmdirs(tmp_dir); SAFE_FREE(tmp_dir); SAFE_FREE(cwd); } static void torture_ssh_quote_file_name(UNUSED_PARAM(void **state)) { char buffer[2048]; int rc; /* Only ordinary chars */ rc = ssh_quote_file_name("a b", buffer, 2048); assert_int_equal(rc, 5); assert_string_equal(buffer, "'a b'"); /* Single quote in file name */ rc = ssh_quote_file_name("a'b", buffer, 2048); assert_int_equal(rc, 9); assert_string_equal(buffer, "'a'\"'\"'b'"); /* Exclamation in file name */ rc = ssh_quote_file_name("a!b", buffer, 2048); assert_int_equal(rc, 8); assert_string_equal(buffer, "'a'\\!'b'"); /* All together */ rc = ssh_quote_file_name("'a!b'", buffer, 2048); assert_int_equal(rc, 14); assert_string_equal(buffer, "\"'\"'a'\\!'b'\"'\""); rc = ssh_quote_file_name("a'!b", buffer, 2048); assert_int_equal(rc, 11); assert_string_equal(buffer, "'a'\"'\"\\!'b'"); rc = ssh_quote_file_name("a'$b", buffer, 2048); assert_int_equal(rc, 10); assert_string_equal(buffer, "'a'\"'\"'$b'"); rc = ssh_quote_file_name("a'`b", buffer, 2048); assert_int_equal(rc, 10); assert_string_equal(buffer, "'a'\"'\"'`b'"); rc = ssh_quote_file_name(" ", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "' '"); rc = ssh_quote_file_name(" ", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "' '"); rc = ssh_quote_file_name("\r", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "'\r'"); rc = ssh_quote_file_name("\n", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "'\n'"); rc = ssh_quote_file_name("\r\n", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "'\r\n'"); rc = ssh_quote_file_name("\\r", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "'\\r'"); rc = ssh_quote_file_name("\\n", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "'\\n'"); rc = ssh_quote_file_name("\\r\\n", buffer, 2048); assert_int_equal(rc, 6); assert_string_equal(buffer, "'\\r\\n'"); rc = ssh_quote_file_name("\t", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "'\t'"); rc = ssh_quote_file_name("\v", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "'\v'"); rc = ssh_quote_file_name("\t\v", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "'\t\v'"); rc = ssh_quote_file_name("'", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "\"'\""); rc = ssh_quote_file_name("''", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "\"''\""); rc = ssh_quote_file_name("\"", buffer, 2048); assert_int_equal(rc, 3); assert_string_equal(buffer, "'\"'"); rc = ssh_quote_file_name("\"\"", buffer, 2048); assert_int_equal(rc, 4); assert_string_equal(buffer, "'\"\"'"); rc = ssh_quote_file_name("'\"", buffer, 2048); assert_int_equal(rc, 6); assert_string_equal(buffer, "\"'\"'\"'"); rc = ssh_quote_file_name("\"'", buffer, 2048); assert_int_equal(rc, 6); assert_string_equal(buffer, "'\"'\"'\""); /* Worst case */ rc = ssh_quote_file_name("a'b'", buffer, 3 * 4 + 1); assert_int_equal(rc, 12); assert_string_equal(buffer, "'a'\"'\"'b'\"'\""); /* Negative tests */ /* NULL params */ rc = ssh_quote_file_name(NULL, buffer, 3 * 4 + 1); assert_int_equal(rc, SSH_ERROR); /* NULL params */ rc = ssh_quote_file_name("a b", NULL, 3 * 4 + 1); assert_int_equal(rc, SSH_ERROR); /* Small buffer size */ rc = ssh_quote_file_name("a b", buffer, 0); assert_int_equal(rc, SSH_ERROR); /* Worst case and small buffer size */ rc = ssh_quote_file_name("a'b'", buffer, 3 * 4); assert_int_equal(rc, SSH_ERROR); } static void torture_ssh_newline_vis(UNUSED_PARAM(void **state)) { int rc; char buffer[1024]; rc = ssh_newline_vis("\n", buffer, 1024); assert_int_equal(rc, 2); assert_string_equal(buffer, "\\n"); rc = ssh_newline_vis("\n\n\n\n", buffer, 1024); assert_int_equal(rc, 8); assert_string_equal(buffer, "\\n\\n\\n\\n"); rc = ssh_newline_vis("a\nb\n", buffer, 1024); assert_int_equal(rc, 6); assert_string_equal(buffer, "a\\nb\\n"); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_get_user_home_dir), cmocka_unit_test(torture_basename), cmocka_unit_test(torture_dirname), cmocka_unit_test(torture_ntohll), #ifdef _WIN32 cmocka_unit_test(torture_path_expand_tilde_win), #else cmocka_unit_test(torture_path_expand_tilde_unix), #endif cmocka_unit_test_setup_teardown(torture_path_expand_escape, setup, teardown), cmocka_unit_test_setup_teardown(torture_path_expand_known_hosts, setup, teardown), cmocka_unit_test_setup_teardown(torture_path_expand_percent, setup, teardown), cmocka_unit_test(torture_timeout_elapsed), cmocka_unit_test(torture_timeout_update), cmocka_unit_test(torture_ssh_analyze_banner), cmocka_unit_test(torture_ssh_dir_writeable), cmocka_unit_test(torture_ssh_newline_vis), cmocka_unit_test(torture_ssh_mkdirs), cmocka_unit_test(torture_ssh_quote_file_name), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_moduli.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "dh-gex.c" static const char moduli_content[] = "# Time Type Tests Tries Size Generator Modulus\n" "20120821044040 2 6 100 1023 5 D9277DAA27DB131C03B108D41A76B4DA8ACEECCCAE73" "D2E48CEDAAA70B09EF9F04FB020DCF36C51B8E485B26FABE0337E24232BE4F4E6935483102" "44937433FB1A5758195DC73B84ADEF8237472C46747D79DC0A2CF8A57CE8DBD8F466A20F85" "51E7B1B824B2E4987A8816D9BC0741C2798F3EBAD3ADEBCC78FCE6A770E2EC9F\n" "20120821044502 2 6 100 1535 5 D1391174233D315398FE2830AC6B2B66BCCD01B0A634" "899F339B7879F1DB85712E9DC4E4B1C6C8355570C1D2DCB53493DF18175A9C53D1128B592B" "4C72D97136F5542FEB981CBFE8012FDD30361F288A42BD5EBB08BAB0A5640E1AC48763B2AB" "D1945FEE36B2D55E1D50A1C86CED9DD141C4E7BE2D32D9B562A0F8E2E927020E91F58B57EB" "9ACDDA106A59302D7E92AD5F6E851A45FA1CFE86029A0F727F65A8F475F33572E2FDAB6073" "F0C21B8B54C3823DB2EF068927E5D747498F96361507\n" "20120821050636 2 6 100 2047 2 DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D" "8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E5828" "1FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00" "C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA4" "5C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4" "FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231B" "BE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116" "B8119892C604293683DF582B\n" "20120821053137 2 6 100 3071 5 DFAA35D35531E0F524F0099877A482D2AC8D589F3743" "94A262A8E81A8A4FB2F65FADBAB395E05D147B29D486DFAA41F41597A256DA82A8B6F76401" "AED53D0253F956CEC610D417E42E3B287F7938FC24D8821B40BFA218A956EB7401BED6C96C" "68C7FD64F8170A8A76B953DD2F05420118F6B144D8FE48060A2BCB85056B478EDEF96DBC70" "427053ECD2958C074169E9550DD877779A3CF17C5AC850598C7586BEEA9DCFE9DD2A5FB62D" "F5F33EA7BC00CDA31B9D2DD721F979EA85B6E63F0C4E30BDDCD3A335522F9004C4ED50B15D" "C537F55324DD4FA119FB3F101467C6D7E1699DE4B3E3C478A8679B8EB3FA5C9B826B44530F" "D3BE9AD3063B240B0C853EBDDBD68DD940332D98F148D5D9E1DC977D60A0D23D0CA1198637" "FEAE4E7FAAC173AF2B84313A666CFB4EE6972811921D0AD867CE57F3BBC8D6CB057E3B6675" "7BB46C9F72662624D44E14528327E3A7100E81A12C43C4E236118318CD90C8AA185BBB0C76" "4826DAEAEE8DD245C5B451B4944E6122CC522D1C335C2EEF942284EA9F\n"; const char modulus_2048[] = "DD2047CBDBB6F8E919BC63DE885B34D0FD6E3DB2887D" "8B46FE249886ACED6B46DFCD5553168185FD376122171CD8927E60120FA8D01F01D03E5828" "1FEA9A1ABE97631C828E41815F34FDCDF787419FE13A3137649AA93D2584230DF5F24B5C00" "C88B7D7DE4367693428C730376F218A53E853B0851BAB7C53C15DA7839CBE1285DB63F6FA4" "5C1BB59FE1C5BB918F0F8459D7EF60ACFF5C0FA0F3FCAD1C5F4CE4416D4F4B36B05CDCEBE4" "FB879E95847EFBC6449CD190248843BC7EDB145FBFC4EDBB1A3C959298F08F3BA2CFBE231B" "BE204BE6F906209D28BD4820AB3E7BE96C26AE8A809ADD8D1A5A0B008E9570FA4C4697E116" "B8119892C604293683DF582B"; /* test if the best dhgroup size is chosen out of lists */ static void torture_dhgroup_better_size(UNUSED_PARAM(void **state)) { /* series of group sizes, as they are read in the file, along with expected * value at every moment. */ size_t groups[][5][2] = { {{1024,1024}, {2048, 1024}, {1500, 1024}, {1023,1024}, {512, 1024}}, {{512, 512}, {1023, 1023}, {1025, 1025}, {1500, 1025}, {2000, 1025}}, {{512, 512}, {2049, 512}, {768, 768}, {4096, 768}, {1024, 1024}} }; size_t i, j, best; for (i = 0; i < 3; ++i) { best = 0; for (j = 0; j < 5; ++j) { bool ok; ok = dhgroup_better_size(512, 1024, 2048, best, groups[i][j][0]); if (ok) { best = groups[i][j][0]; assert_int_equal(best, groups[i][j][1]); } assert_int_equal(best, groups[i][j][1]); } } } static void torture_retrieve_dhgroup_file(UNUSED_PARAM(void **state)) { FILE *moduli = tmpfile(); size_t size = 0; char *generator = NULL, *modulus = NULL; int rc; fwrite(moduli_content, 1, sizeof(moduli_content), moduli); rewind(moduli); rc = ssh_retrieve_dhgroup_file(moduli, 1024, 2048, 4096, &size, &generator, &modulus); assert_int_equal(rc, SSH_OK); assert_int_equal(size, 2048); assert_string_equal(modulus, modulus_2048); SAFE_FREE(generator); SAFE_FREE(modulus); fclose(moduli); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_dhgroup_better_size), cmocka_unit_test(torture_retrieve_dhgroup_file) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_options.c ================================================ #include "config.h" #define LIBSSH_STATIC #ifndef _WIN32 #define _POSIX_PTHREAD_SEMANTICS # include #endif #include "torture.h" #include "torture_key.h" #include #include #include #include #ifdef WITH_SERVER #include #define LIBSSH_CUSTOM_BIND_CONFIG_FILE "my_bind_config" #endif #ifdef HAVE_DSA #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" #endif #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519" #ifdef HAVE_ECC #define LIBSSH_ECDSA_521_TESTKEY "libssh_testkey.id_ecdsa521" #endif static int setup(void **state) { ssh_session session; int verbosity; session = ssh_new(); verbosity = torture_libssh_verbosity(); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); session->client = 1; *state = session; return 0; } static int teardown(void **state) { ssh_free(*state); return 0; } static void torture_options_set_host(void **state) { ssh_session session = *state; int rc; rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); assert_true(rc == 0); assert_non_null(session->opts.host); assert_string_equal(session->opts.host, "localhost"); rc = ssh_options_set(session, SSH_OPTIONS_HOST, "guru@meditation"); assert_true(rc == 0); assert_non_null(session->opts.host); assert_string_equal(session->opts.host, "meditation"); assert_non_null(session->opts.username); assert_string_equal(session->opts.username, "guru"); } static void torture_options_set_ciphers(void **state) { ssh_session session = *state; int rc; /* Test known ciphers */ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, "aes128-ctr,aes192-ctr,aes256-ctr"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_CRYPT_C_S]); if (ssh_fips_mode()) { assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes256-ctr"); } else { assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes192-ctr,aes256-ctr"); } /* Test one unknown cipher */ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, "aes128-ctr,unknown-crap@example.com,aes256-ctr"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_CRYPT_C_S]); assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes256-ctr"); /* Test all unknown ciphers */ rc = ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, "unknown-crap@example.com,more-crap@example.com"); assert_false(rc == 0); } static void torture_options_set_key_exchange(void **state) { ssh_session session = *state; int rc; /* Test known kexes */ rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "curve25519-sha256,curve25519-sha256@libssh.org," "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256," "diffie-hellman-group14-sha1"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(session->opts.wanted_methods[SSH_KEX], "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256"); } else { assert_string_equal(session->opts.wanted_methods[SSH_KEX], "curve25519-sha256,curve25519-sha256@libssh.org," "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256," "diffie-hellman-group14-sha1"); } /* Test one unknown kex */ rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "diffie-hellman-group16-sha512," "unknown-crap@example.com," "diffie-hellman-group18-sha512"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_KEX]); assert_string_equal(session->opts.wanted_methods[SSH_KEX], "diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512"); /* Test all unknown kexes */ rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "unknown-crap@example.com,more-crap@example.com"); assert_false(rc == 0); } static void torture_options_set_hostkey(void **state) { ssh_session session = *state; int rc; /* Test known host keys */ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp384"); } else { assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); } /* Test one unknown host key */ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "ecdsa-sha2-nistp521," "unknown-crap@example.com," "rsa-sha2-256"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_HOSTKEYS]); assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp521," "rsa-sha2-256"); /* Test all unknown host keys */ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "unknown-crap@example.com,more-crap@example.com"); assert_false(rc == 0); } static void torture_options_set_pubkey_accepted_types(void **state) { ssh_session session = *state; int rc; enum ssh_digest_e type; /* Test known public key algorithms */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); assert_true(rc == 0); assert_non_null(session->opts.pubkey_accepted_types); if (ssh_fips_mode()) { assert_string_equal(session->opts.pubkey_accepted_types, "ecdsa-sha2-nistp384"); } else { assert_string_equal(session->opts.pubkey_accepted_types, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); } if (!ssh_fips_mode()) { /* Test one unknown public key algorithms */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "ssh-ed25519,unknown-crap@example.com,ssh-rsa"); assert_true(rc == 0); assert_non_null(session->opts.pubkey_accepted_types); assert_string_equal(session->opts.pubkey_accepted_types, "ssh-ed25519,ssh-rsa"); /* Test all unknown public key algorithms */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "unknown-crap@example.com,more-crap@example.com"); assert_false(rc == 0); /* Test that the option affects the algorithm selection for RSA keys */ /* simulate the SHA2 extension was negotiated */ session->extensions = SSH_EXT_SIG_RSA_SHA256; /* previous configuration did not list the SHA2 extension algoritms, so * it should not be used */ type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA); assert_int_equal(type, SSH_DIGEST_SHA1); } /* now, lets allow the signature from SHA2 extension and expect * it to be used */ rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, "rsa-sha2-256,ssh-rsa"); assert_true(rc == 0); assert_non_null(session->opts.pubkey_accepted_types); if (ssh_fips_mode()) { assert_string_equal(session->opts.pubkey_accepted_types, "rsa-sha2-256"); } else { assert_string_equal(session->opts.pubkey_accepted_types, "rsa-sha2-256,ssh-rsa"); } /* Test that the option affects the algorithm selection for RSA keys */ /* simulate the SHA2 extension was negotiated */ session->extensions = SSH_EXT_SIG_RSA_SHA256; type = ssh_key_type_to_hash(session, SSH_KEYTYPE_RSA); assert_int_equal(type, SSH_DIGEST_SHA256); } static void torture_options_set_macs(void **state) { ssh_session session = *state; int rc; /* Test known MACs */ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "hmac-sha1"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_MAC_S_C]); assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], "hmac-sha1"); /* Test multiple known MACs */ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha1,hmac-sha2-256"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_MAC_S_C]); assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], "hmac-sha1-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha1,hmac-sha2-256"); /* Test unknown MACs */ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "unknown-crap@example.com,hmac-sha1-etm@openssh.com,unknown@example.com"); assert_true(rc == 0); assert_non_null(session->opts.wanted_methods[SSH_MAC_S_C]); assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], "hmac-sha1-etm@openssh.com"); /* Test all unknown MACs */ rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "unknown-crap@example.com"); assert_false(rc == 0); } static void torture_options_get_host(void **state) { ssh_session session = *state; int rc; char* host = NULL; rc = ssh_options_set(session, SSH_OPTIONS_HOST, "localhost"); assert_true(rc == 0); assert_string_equal(session->opts.host, "localhost"); assert_false(ssh_options_get(session, SSH_OPTIONS_HOST, &host)); assert_string_equal(host, "localhost"); free(host); } static void torture_options_set_port(void **state) { ssh_session session = *state; int rc; unsigned int port = 42; rc = ssh_options_set(session, SSH_OPTIONS_PORT, &port); assert_true(rc == 0); assert_true(session->opts.port == port); rc = ssh_options_set(session, SSH_OPTIONS_PORT_STR, "23"); assert_true(rc == 0); assert_true(session->opts.port == 23); rc = ssh_options_set(session, SSH_OPTIONS_PORT_STR, "five"); assert_true(rc == -1); rc = ssh_options_set(session, SSH_OPTIONS_PORT, NULL); assert_true(rc == -1); } static void torture_options_get_port(void **state) { ssh_session session = *state; unsigned int given_port = 1234; unsigned int port_container; int rc; rc = ssh_options_set(session, SSH_OPTIONS_PORT, &given_port); assert_true(rc == 0); rc = ssh_options_get_port(session, &port_container); assert_true(rc == 0); assert_int_equal(port_container, 1234); } static void torture_options_get_user(void **state) { ssh_session session = *state; char* user = NULL; int rc; rc = ssh_options_set(session, SSH_OPTIONS_USER, "magicaltrevor"); assert_int_equal(rc, SSH_OK); rc = ssh_options_get(session, SSH_OPTIONS_USER, &user); assert_int_equal(rc, SSH_OK); assert_non_null(user); assert_string_equal(user, "magicaltrevor"); free(user); } static void torture_options_set_fd(void **state) { ssh_session session = *state; socket_t fd = 42; int rc; rc = ssh_options_set(session, SSH_OPTIONS_FD, &fd); assert_true(rc == 0); assert_true(session->opts.fd == fd); rc = ssh_options_set(session, SSH_OPTIONS_FD, NULL); assert_true(rc == SSH_ERROR); assert_true(session->opts.fd == SSH_INVALID_SOCKET); } static void torture_options_set_user(void **state) { ssh_session session = *state; int rc; #ifndef _WIN32 # ifndef NSS_BUFLEN_PASSWD # define NSS_BUFLEN_PASSWD 4096 # endif /* NSS_BUFLEN_PASSWD */ struct passwd pwd; struct passwd *pwdbuf; char buf[NSS_BUFLEN_PASSWD]; /* get local username */ rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); assert_true(rc == 0); #endif /* _WIN32 */ rc = ssh_options_set(session, SSH_OPTIONS_USER, "guru"); assert_true(rc == 0); assert_string_equal(session->opts.username, "guru"); rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL); assert_true(rc == 0); #ifndef _WIN32 assert_string_equal(session->opts.username, pwd.pw_name); #endif } /* TODO */ #if 0 static voidtorture_options_set_sshdir) { } END_TEST #endif static void torture_options_set_identity(void **state) { ssh_session session = *state; int rc; rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1"); assert_true(rc == 0); assert_string_equal(session->opts.identity->root->data, "identity1"); rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2"); assert_true(rc == 0); assert_string_equal(session->opts.identity->root->data, "identity2"); assert_string_equal(session->opts.identity->root->next->data, "identity1"); } static void torture_options_get_identity(void **state) { ssh_session session = *state; char *identity = NULL; int rc; rc = ssh_options_set(session, SSH_OPTIONS_ADD_IDENTITY, "identity1"); assert_true(rc == 0); rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity); assert_int_equal(rc, SSH_OK); assert_non_null(identity); assert_string_equal(identity, "identity1"); SAFE_FREE(identity); rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, "identity2"); assert_int_equal(rc, SSH_OK); assert_string_equal(session->opts.identity->root->data, "identity2"); rc = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &identity); assert_int_equal(rc, SSH_OK); assert_non_null(identity); assert_string_equal(identity, "identity2"); free(identity); } static void torture_options_set_global_knownhosts(void **state) { ssh_session session = *state; int rc; rc = ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/etc/libssh/known_hosts"); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.global_knownhosts, "/etc/libssh/known_hosts"); } static void torture_options_get_global_knownhosts(void **state) { ssh_session session = *state; char *str = NULL; int rc; rc = ssh_options_set(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, "/etc/libssh/known_hosts"); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.global_knownhosts, "/etc/libssh/known_hosts"); rc = ssh_options_get(session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS, &str); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.global_knownhosts, "/etc/libssh/known_hosts"); SSH_STRING_FREE_CHAR(str); } static void torture_options_set_knownhosts(void **state) { ssh_session session = *state; int rc; rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/home/libssh/.ssh/known_hosts"); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.knownhosts, "/home/libssh/.ssh/known_hosts"); /* The NULL value should not crash the libssh */ rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL); assert_ssh_return_code(session, rc); assert_null(session->opts.knownhosts); /* ssh_options_apply() should set the path to correct value */ rc = ssh_options_apply(session); assert_ssh_return_code(session, rc); assert_non_null(session->opts.knownhosts); } static void torture_options_get_knownhosts(void **state) { ssh_session session = *state; char *str = NULL; int rc; rc = ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, "/home/libssh/.ssh/known_hosts"); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.knownhosts, "/home/libssh/.ssh/known_hosts"); rc = ssh_options_get(session, SSH_OPTIONS_KNOWNHOSTS, &str); assert_ssh_return_code(session, rc); assert_string_equal(session->opts.knownhosts, "/home/libssh/.ssh/known_hosts"); SSH_STRING_FREE_CHAR(str); } static void torture_options_proxycommand(void **state) { ssh_session session = *state; int rc; /* Enable ProxyCommand */ rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "ssh -q -A -X -W %h:%p JUMPHOST"); assert_int_equal(rc, 0); assert_string_equal(session->opts.ProxyCommand, "ssh -q -A -X -W %h:%p JUMPHOST"); /* Disable ProxyCommand */ rc = ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, "none"); assert_int_equal(rc, 0); assert_null(session->opts.ProxyCommand); } static void torture_options_config_host(void **state) { ssh_session session = *state; FILE *config = NULL; /* create a new config file */ config = fopen("test_config", "w"); assert_non_null(config); fputs("Host testhost1\nPort 42\n" "Host testhost2,testhost3\nPort 43\n" "Host testhost4 testhost5\nPort 44\n", config); fclose(config); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1"); ssh_options_parse_config(session, "test_config"); assert_int_equal(session->opts.port, 42); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost2"); ssh_options_parse_config(session, "test_config"); assert_int_equal(session->opts.port, 43); session->opts.port = 0; torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost3"); ssh_options_parse_config(session, "test_config"); assert_int_equal(session->opts.port, 43); torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost4"); ssh_options_parse_config(session, "test_config"); assert_int_equal(session->opts.port, 44); session->opts.port = 0; torture_reset_config(session); ssh_options_set(session, SSH_OPTIONS_HOST, "testhost5"); ssh_options_parse_config(session, "test_config"); assert_int_equal(session->opts.port, 44); unlink("test_config"); } static void torture_options_config_match(void **state) { ssh_session session = *state; char *localuser = NULL; FILE *config = NULL; int rv; /* Required for options_parse_config() */ ssh_options_set(session, SSH_OPTIONS_HOST, "testhost1"); /* The Match keyword requires argument */ config = fopen("test_config", "w"); assert_non_null(config); fputs("Match\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_ERROR); /* The Match all keyword needs to be the only one (start) */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match all host local\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_ERROR); /* The Match all keyword needs to be the only one (end) */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match host local all\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_ERROR); /* The Match host keyword requires an argument */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match host\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_ERROR); /* The Match user keyword requires an argument */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match user\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_ERROR); /* The Match canonical keyword is the same as match all */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match canonical\n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code_equal(session, rv, SSH_OK); assert_int_equal(session->opts.port, 33); session->opts.port = 0; /* The Match originalhost keyword is ignored */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match originalhost origin\n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); assert_int_equal(session->opts.port, 34); session->opts.port = 0; /* The Match localuser keyword */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match localuser ", config); localuser = ssh_get_local_username(); assert_non_null(localuser); fputs(localuser, config); free(localuser); fputs("\n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); assert_int_equal(session->opts.port, 33); session->opts.port = 0; /* The Match exec keyword is ignored */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match exec /bin/true\n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); assert_int_equal(session->opts.port, 34); session->opts.port = 0; /* The Match exec keyword can accept more arguments */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match exec /bin/true 1 \n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); assert_int_equal(session->opts.port, 34); session->opts.port = 0; /* Commands containing whitespace characters must be quoted. */ torture_reset_config(session); config = fopen("test_config", "w"); assert_non_null(config); fputs("Match exec \"/bin/true 1\"\n" "\tPort 33\n" "Match all\n" "\tPort 34\n", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); assert_int_equal(session->opts.port, 34); session->opts.port = 0; unlink("test_config"); } static void torture_options_copy(void **state) { ssh_session session = *state, new = NULL; struct ssh_iterator *it = NULL, *it2 = NULL; FILE *config = NULL; int i, level = 9; int rv; /* Required for options_parse_config() */ ssh_options_set(session, SSH_OPTIONS_HOST, "example"); /* Impossible to set through the configuration */ rv = ssh_options_set(session, SSH_OPTIONS_COMPRESSION_LEVEL, &level); assert_ssh_return_code(session, rv); level = 1; rv = ssh_options_set(session, SSH_OPTIONS_NODELAY, &level); assert_ssh_return_code(session, rv); /* The Match keyword requires argument */ config = fopen("test_config", "w"); assert_non_null(config); fputs("IdentityFile ~/.ssh/id_ecdsa\n" "User tester\n" "Hostname example.com\n" "BindAddress 127.0.0.2\n" "GlobalKnownHostsFile /etc/ssh/known_hosts2\n" "UserKnownHostsFile ~/.ssh/known_hosts2\n" "KexAlgorithms curve25519-sha256,ecdh-sha2-nistp521\n" "Ciphers aes256-ctr\n" "MACs hmac-sha2-256\n" "HostKeyAlgorithms ssh-ed25519,ecdsa-sha2-nistp521\n" "Compression yes\n" "PubkeyAcceptedTypes ssh-ed25519,ecdsa-sha2-nistp521\n" "ProxyCommand nc 127.0.0.10 22\n" /* ops.custombanner */ "ConnectTimeout 42\n" "Port 222\n" "StrictHostKeyChecking no\n" "GSSAPIServerIdentity my.example.com\n" "GSSAPIClientIdentity home.sweet\n" "GSSAPIDelegateCredentials yes\n" "PubkeyAuthentication yes\n" /* sets flags */ "GSSAPIAuthentication no\n" /* sets flags */ "", config); fclose(config); rv = ssh_options_parse_config(session, "test_config"); assert_ssh_return_code(session, rv); rv = ssh_options_copy(session, &new); assert_ssh_return_code(session, rv); assert_non_null(new); /* Check the identities match */ it = ssh_list_get_iterator(session->opts.identity); assert_non_null(it); it2 = ssh_list_get_iterator(new->opts.identity); assert_non_null(it2); while (it != NULL && it2 != NULL) { assert_string_equal(it->data, it2->data); it = it->next; it2 = it2->next; } assert_null(it); assert_null(it2); assert_string_equal(session->opts.username, new->opts.username); assert_string_equal(session->opts.host, new->opts.host); assert_string_equal(session->opts.bindaddr, new->opts.bindaddr); assert_string_equal(session->opts.sshdir, new->opts.sshdir); assert_string_equal(session->opts.knownhosts, new->opts.knownhosts); assert_string_equal(session->opts.global_knownhosts, new->opts.global_knownhosts); for (i = 0; i < SSH_KEX_METHODS; i++) { if (session->opts.wanted_methods[i] == NULL) { assert_null(new->opts.wanted_methods[i]); } else { assert_string_equal(session->opts.wanted_methods[i], new->opts.wanted_methods[i]); } } assert_string_equal(session->opts.pubkey_accepted_types, new->opts.pubkey_accepted_types); assert_string_equal(session->opts.ProxyCommand, new->opts.ProxyCommand); /* TODO custombanner */ assert_int_equal(session->opts.timeout, new->opts.timeout); assert_int_equal(session->opts.timeout_usec, new->opts.timeout_usec); assert_int_equal(session->opts.port, new->opts.port); assert_int_equal(session->opts.StrictHostKeyChecking, new->opts.StrictHostKeyChecking); assert_int_equal(session->opts.compressionlevel, new->opts.compressionlevel); assert_string_equal(session->opts.gss_server_identity, new->opts.gss_server_identity); assert_string_equal(session->opts.gss_client_identity, new->opts.gss_client_identity); assert_int_equal(session->opts.gss_delegate_creds, new->opts.gss_delegate_creds); assert_int_equal(session->opts.flags, new->opts.flags); assert_int_equal(session->opts.nodelay, new->opts.nodelay); assert_true(session->opts.config_processed == new->opts.config_processed); assert_memory_equal(session->opts.options_seen, new->opts.options_seen, sizeof(session->opts.options_seen)); ssh_free(new); } #ifdef WITH_SERVER const char template[] = "temp_dir_XXXXXX"; struct bind_st { char *cwd; char *temp_dir; ssh_bind bind; }; static int ssh_bind_setup_files(void **state) { struct bind_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct bind_st *)malloc(sizeof(struct bind_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); /* For ed25519 the test keys are not available in legacy PEM format. Using * the new OpenSSH format for all algorithms */ torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_ED25519_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0)); #ifdef HAVE_ECC torture_write_file(LIBSSH_ECDSA_521_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_ECDSA_P521, 0)); #endif #ifdef HAVE_DSA torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0)); #endif torture_write_file(LIBSSH_CUSTOM_BIND_CONFIG_FILE, "Port 42\n"); return 0; } /* sshbind options */ static int sshbind_setup(void **state) { int rc; struct bind_st *test_state = NULL; rc = ssh_bind_setup_files((void **)&test_state); assert_int_equal(rc, 0); assert_non_null(test_state); test_state->bind = ssh_bind_new(); assert_non_null(test_state->bind); *state = test_state; return 0; } static int sshbind_teardown(void **state) { struct bind_st *test_state = NULL; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); assert_non_null(test_state->bind); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); ssh_bind_free(test_state->bind); SAFE_FREE(test_state); return 0; } static void torture_bind_options_import_key(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; const char *base64_key; ssh_key key = ssh_key_new(); assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; /* set null */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, NULL); assert_int_equal(rc, -1); /* set invalid key */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key); assert_int_equal(rc, -1); SSH_KEY_FREE(key); /* set rsa key */ base64_key = torture_get_testkey(SSH_KEYTYPE_RSA, 0); rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key); assert_int_equal(rc, 0); #ifdef HAVE_DSA /* set dsa key */ base64_key = torture_get_testkey(SSH_KEYTYPE_DSS, 0); rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key); assert_int_equal(rc, 0); #endif #ifdef HAVE_ECC /* set ecdsa key */ base64_key = torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0); rc = ssh_pki_import_privkey_base64(base64_key, NULL, NULL, NULL, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_IMPORT_KEY, key); assert_int_equal(rc, 0); #endif } static void torture_bind_options_hostkey(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; /* Test RSA key */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, LIBSSH_RSA_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->rsakey); assert_string_equal(bind->rsakey, LIBSSH_RSA_TESTKEY); /* Test ED25519 key */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, LIBSSH_ED25519_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->ed25519key); assert_string_equal(bind->ed25519key, LIBSSH_ED25519_TESTKEY); #ifdef HAVE_ECC /* Test ECDSA key */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, LIBSSH_ECDSA_521_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); #endif #ifdef HAVE_DSA /* Test DSA key */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY, LIBSSH_DSA_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->dsakey); assert_string_equal(bind->dsakey, LIBSSH_DSA_TESTKEY); #endif } static void torture_bind_options_bindaddr(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; const char *address = "127.0.0.1"; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDADDR, address); assert_int_equal(rc, 0); assert_non_null(bind->bindaddr); assert_string_equal(bind->bindaddr, address); } static void torture_bind_options_bindport(void **state) { struct bind_st *test_state; ssh_bind bind; unsigned int given_port = 1234; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT, &given_port); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 1234); } static void torture_bind_options_bindport_str(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BINDPORT_STR, "23"); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 23); } static void torture_bind_options_log_verbosity(void **state) { struct bind_st *test_state; ssh_bind bind; int verbosity = SSH_LOG_PACKET; int previous_level, new_level; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &verbosity); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, verbosity); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } static void torture_bind_options_log_verbosity_str(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; int previous_level, new_level; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; previous_level = ssh_get_log_level(); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); assert_int_equal(rc, 0); new_level = ssh_get_log_level(); assert_int_equal(new_level, SSH_LOG_PACKET); rc = ssh_set_log_level(previous_level); assert_int_equal(rc, SSH_OK); } #ifdef HAVE_DSA static void torture_bind_options_dsakey(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_DSAKEY, LIBSSH_DSA_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->dsakey); assert_string_equal(bind->dsakey, LIBSSH_DSA_TESTKEY); } #endif static void torture_bind_options_rsakey(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_RSAKEY, LIBSSH_RSA_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->rsakey); assert_string_equal(bind->rsakey, LIBSSH_RSA_TESTKEY); } #ifdef HAVE_ECC static void torture_bind_options_ecdsakey(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_ECDSAKEY, LIBSSH_ECDSA_521_TESTKEY); assert_int_equal(rc, 0); assert_non_null(bind->ecdsakey); assert_string_equal(bind->ecdsakey, LIBSSH_ECDSA_521_TESTKEY); } #endif static void torture_bind_options_banner(void **state) { struct bind_st *test_state; ssh_bind bind; const char *banner = "This is the new banner"; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_BANNER, banner); assert_int_equal(rc, 0); assert_non_null(bind->banner); assert_string_equal(bind->banner, banner); } static void torture_bind_options_set_ciphers(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; assert_non_null(bind->wanted_methods); /* Test known ciphers */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, "aes128-ctr,aes192-ctr,aes256-ctr"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes256-ctr"); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes192-ctr,aes256-ctr"); } /* Test one unknown cipher */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, "aes128-ctr,unknown-crap@example.com,aes256-ctr"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_C_S]); assert_string_equal(bind->wanted_methods[SSH_CRYPT_C_S], "aes128-ctr,aes256-ctr"); /* Test all unknown ciphers */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_C_S, "unknown-crap@example.com,more-crap@example.com"); assert_int_not_equal(rc, 0); /* Test known ciphers */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, "aes128-ctr,aes192-ctr,aes256-ctr"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], "aes128-ctr,aes256-ctr"); } else { assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], "aes128-ctr,aes192-ctr,aes256-ctr"); } /* Test one unknown cipher */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, "aes128-ctr,unknown-crap@example.com,aes256-ctr"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_CRYPT_S_C]); assert_string_equal(bind->wanted_methods[SSH_CRYPT_S_C], "aes128-ctr,aes256-ctr"); /* Test all unknown ciphers */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CIPHERS_S_C, "unknown-crap@example.com,more-crap@example.com"); assert_int_not_equal(rc, 0); } static void torture_bind_options_set_key_exchange(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; assert_non_null(bind->wanted_methods); /* Test known kexes */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, "curve25519-sha256,curve25519-sha256@libssh.org," "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256," "diffie-hellman-group14-sha1"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_KEX], "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256"); } else { assert_string_equal(bind->wanted_methods[SSH_KEX], "curve25519-sha256,curve25519-sha256@libssh.org," "ecdh-sha2-nistp256,diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512," "diffie-hellman-group14-sha256," "diffie-hellman-group14-sha1"); } /* Test one unknown kex */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, "diffie-hellman-group16-sha512," "unknown-crap@example.com," "diffie-hellman-group18-sha512"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_KEX]); assert_string_equal(bind->wanted_methods[SSH_KEX], "diffie-hellman-group16-sha512," "diffie-hellman-group18-sha512"); /* Test all unknown kexes */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_KEY_EXCHANGE, "unknown-crap@example.com,more-crap@example.com"); assert_int_not_equal(rc, 0); } static void torture_bind_options_set_macs(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; assert_non_null(bind->wanted_methods); /* Test known MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, "hmac-sha1"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], "hmac-sha1"); /* Test multiple known MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, "hmac-sha1,hmac-sha2-256"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], "hmac-sha1,hmac-sha2-256"); /* Test unknown MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, "unknown-crap@example.com,hmac-sha1,unknown@example.com"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_S_C]); assert_string_equal(bind->wanted_methods[SSH_MAC_S_C], "hmac-sha1"); /* Test all unknown MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_S_C, "unknown-crap@example.com"); assert_int_not_equal(rc, 0); /* Test known MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, "hmac-sha1"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], "hmac-sha1"); /* Test multiple known MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, "hmac-sha1,hmac-sha2-256"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], "hmac-sha1,hmac-sha2-256"); /* Test unknown MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, "unknown-crap@example.com,hmac-sha1,unknown@example.com"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_MAC_C_S]); assert_string_equal(bind->wanted_methods[SSH_MAC_C_S], "hmac-sha1"); /* Test all unknown MACs */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HMAC_C_S, "unknown-crap@example.com"); assert_int_not_equal(rc, 0); } static void torture_bind_options_parse_config(void **state) { struct bind_st *test_state; ssh_bind bind; char *cwd = NULL; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; cwd = torture_get_current_working_dir(); assert_non_null(cwd); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CONFIG_DIR, (const char *)cwd); assert_int_equal(rc, 0); assert_non_null(bind->config_dir); assert_string_equal(bind->config_dir, cwd); rc = ssh_bind_options_parse_config(bind, "%d/"LIBSSH_CUSTOM_BIND_CONFIG_FILE); assert_int_equal(rc, 0); assert_int_equal(bind->bindport, 42); SAFE_FREE(cwd); } static void torture_bind_options_config_dir(void **state) { struct bind_st *test_state; ssh_bind bind; const char *new_dir = "/new/dir/"; const char *replacement_dir = "/replacement/dir/"; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CONFIG_DIR, new_dir); assert_int_equal(rc, 0); assert_non_null(bind->config_dir); assert_string_equal(bind->config_dir, new_dir); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_CONFIG_DIR, replacement_dir); assert_int_equal(rc, 0); assert_non_null(bind->config_dir); assert_string_equal(bind->config_dir, replacement_dir); } static void torture_bind_options_set_pubkey_accepted_key_types(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; /* Test known Pubkey Types */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); if (ssh_fips_mode()) { assert_string_equal(bind->pubkey_accepted_key_types, "ecdsa-sha2-nistp384"); } else { assert_string_equal(bind->pubkey_accepted_key_types, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); } SAFE_FREE(bind->pubkey_accepted_key_types); /* Test with some unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "ecdsa-sha2-nistp384,unknown-type,rsa-sha2-256"); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); assert_string_equal(bind->pubkey_accepted_key_types, "ecdsa-sha2-nistp384,rsa-sha2-256"); SAFE_FREE(bind->pubkey_accepted_key_types); /* Test with only unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "unknown-type"); assert_int_equal(rc, -1); assert_null(bind->pubkey_accepted_key_types); /* Test with something set and then try unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "ecdsa-sha2-nistp384"); assert_int_equal(rc, 0); assert_non_null(bind->pubkey_accepted_key_types); assert_string_equal(bind->pubkey_accepted_key_types, "ecdsa-sha2-nistp384"); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "unknown-type"); assert_int_equal(rc, -1); /* Check that nothing changed */ assert_non_null(bind->pubkey_accepted_key_types); assert_string_equal(bind->pubkey_accepted_key_types, "ecdsa-sha2-nistp384"); } static void torture_bind_options_set_hostkey_algorithms(void **state) { struct bind_st *test_state; ssh_bind bind; int rc; assert_non_null(state); test_state = *((struct bind_st **)state); assert_non_null(test_state); assert_non_null(test_state->bind); bind = test_state->bind; /* Test known Pubkey Types */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); if (ssh_fips_mode()) { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp384"); } else { assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], "ssh-ed25519,ecdsa-sha2-nistp384,ssh-rsa"); } SAFE_FREE(bind->wanted_methods[SSH_HOSTKEYS]); /* Test with some unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "ecdsa-sha2-nistp384,unknown-type"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp384"); SAFE_FREE(bind->wanted_methods[SSH_HOSTKEYS]); /* Test with only unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "unknown-type"); assert_int_equal(rc, -1); assert_null(bind->wanted_methods[SSH_HOSTKEYS]); /* Test with something set and then try unknown type */ rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "ecdsa-sha2-nistp384"); assert_int_equal(rc, 0); assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp384"); rc = ssh_bind_options_set(bind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "unknown-type"); assert_int_equal(rc, -1); /* Check that nothing changed */ assert_non_null(bind->wanted_methods[SSH_HOSTKEYS]); assert_string_equal(bind->wanted_methods[SSH_HOSTKEYS], "ecdsa-sha2-nistp384"); } #endif /* WITH_SERVER */ int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_options_set_host, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_host, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_port, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_port, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_fd, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_user, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_user, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_identity, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_identity, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_global_knownhosts, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_global_knownhosts, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_knownhosts, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_get_knownhosts, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_hostkey, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_pubkey_accepted_types, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_copy, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_config_host, setup, teardown), cmocka_unit_test_setup_teardown(torture_options_config_match, setup, teardown), }; #ifdef WITH_SERVER struct CMUnitTest sshbind_tests[] = { cmocka_unit_test_setup_teardown(torture_bind_options_import_key, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_hostkey, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_bindaddr, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_bindport, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_bindport_str, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_log_verbosity, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_log_verbosity_str, sshbind_setup, sshbind_teardown), #ifdef HAVE_DSA cmocka_unit_test_setup_teardown(torture_bind_options_dsakey, sshbind_setup, sshbind_teardown), #endif cmocka_unit_test_setup_teardown(torture_bind_options_rsakey, sshbind_setup, sshbind_teardown), #ifdef HAVE_ECC cmocka_unit_test_setup_teardown(torture_bind_options_ecdsakey, sshbind_setup, sshbind_teardown), #endif cmocka_unit_test_setup_teardown(torture_bind_options_banner, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_set_ciphers, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_set_key_exchange, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_set_macs, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_parse_config, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_config_dir, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_set_pubkey_accepted_key_types, sshbind_setup, sshbind_teardown), cmocka_unit_test_setup_teardown(torture_bind_options_set_hostkey_algorithms, sshbind_setup, sshbind_teardown), }; #endif /* WITH_SERVER */ ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); #ifdef WITH_SERVER rc += cmocka_run_group_tests(sshbind_tests, NULL, NULL); #endif /* WITH_SERVER */ ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_packet.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include "libssh/session.h" #include "libssh/crypto.h" #include "libssh/buffer.h" #include "libssh/socket.h" #include "libssh/callbacks.h" #include "socket.c" uint8_t test_data[]="AThis is test data. Use it to check the validity of packet functions" "AThis is test data. Use it to check the validity of packet functions" "AThis is test data. Use it to check the validity of packet functions" "AThis is test data. Use it to check the validity of packet functions"; uint8_t key[]="iekaeshoa7ooCie2shai8shahngee3ONsee3xoishooj0ojei6aeChieth1iraPh"; uint8_t iv[]="eixaxughoomah4ui7Aew3ohxuolaifuu"; uint8_t mac[]="thook2Jai0ahmahyae7ChuuruoPhee8Y"; static uint8_t *copy_data(uint8_t *data, size_t len){ uint8_t *ret = malloc(len); assert_non_null(ret); memcpy(ret, data, len); return ret; } static SSH_PACKET_CALLBACK(copy_packet_data){ uint8_t *response = user; size_t len = ssh_buffer_get_len(packet); (void)type; (void)session; if(len > 1024){ len = 1024; } ssh_buffer_get_data(packet, response, len); return 0; } static void torture_packet(const char *cipher, const char *mac_type, const char *comp_type, size_t payload_len) { ssh_session session = ssh_new(); int verbosity = torture_libssh_verbosity(); struct ssh_crypto_struct *crypto; struct ssh_cipher_struct *in_cipher; struct ssh_cipher_struct *out_cipher; int rc; int sockets[2]; uint8_t buffer[1024]; uint8_t response[1024]; size_t encrypted_packet_len; ssh_packet_callback callbacks[]={copy_packet_data}; struct ssh_packet_callbacks_struct cb = { .start='A', .n_callbacks=1, .callbacks=callbacks, .user=response }; int cmp; assert_non_null(session); ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); crypto = session->next_crypto; rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); assert_int_equal(rc, 0); crypto->kex_methods[SSH_KEX] = strdup("curve25519-sha256@libssh.org"); crypto->kex_methods[SSH_HOSTKEYS] = strdup("ssh-rsa"); crypto->kex_methods[SSH_CRYPT_C_S] = strdup(cipher); crypto->kex_methods[SSH_CRYPT_S_C] = strdup(cipher); crypto->kex_methods[SSH_MAC_C_S] = strdup(mac_type); crypto->kex_methods[SSH_MAC_S_C] = strdup(mac_type); crypto->kex_methods[SSH_COMP_C_S] = strdup(comp_type); crypto->kex_methods[SSH_COMP_S_C] = strdup(comp_type); crypto->kex_methods[SSH_LANG_C_S] = strdup("none"); crypto->kex_methods[SSH_LANG_S_C] = strdup("none"); rc = crypt_set_algorithms_client(session); assert_int_equal(rc, SSH_OK); session->current_crypto = session->next_crypto; session->next_crypto = crypto_new(); crypto->encryptkey = copy_data(key, sizeof(key)); crypto->decryptkey = copy_data(key, sizeof(key)); crypto->encryptIV = copy_data(iv, sizeof(iv)); crypto->decryptIV = copy_data(iv, sizeof(iv)); crypto->encryptMAC = copy_data(mac, sizeof(mac)); crypto->decryptMAC = copy_data(mac, sizeof(mac)); in_cipher = session->current_crypto->in_cipher; rc = in_cipher->set_decrypt_key(in_cipher, session->current_crypto->decryptkey, session->current_crypto->decryptIV); assert_int_equal(rc, SSH_OK); out_cipher = session->current_crypto->out_cipher; rc = out_cipher->set_encrypt_key(out_cipher, session->current_crypto->encryptkey, session->current_crypto->encryptIV); session->current_crypto->used = SSH_DIRECTION_BOTH; assert_int_equal(rc, SSH_OK); assert_non_null(session->out_buffer); ssh_buffer_add_data(session->out_buffer, test_data, payload_len); session->socket->fd = sockets[0]; session->socket->write_wontblock = 1; rc = ssh_packet_send(session); assert_int_equal(rc, SSH_OK); rc = recv(sockets[1], buffer, sizeof(buffer), 0); assert_true(rc > 0); encrypted_packet_len = rc; cmp = strcmp(comp_type, "none"); if (cmp == 0) { assert_in_range(encrypted_packet_len, payload_len + 4, payload_len + (32 * 3)); } rc = send(sockets[0], buffer, encrypted_packet_len, 0); assert_int_equal(rc, encrypted_packet_len); ssh_packet_set_callbacks(session, &cb); explicit_bzero(response, sizeof(response)); rc = ssh_packet_socket_callback(buffer, encrypted_packet_len, session); assert_int_not_equal(rc, SSH_ERROR); if(payload_len > 0){ assert_memory_equal(response, test_data+1, payload_len-1); } close(sockets[0]); close(sockets[1]); session->socket->fd = SSH_INVALID_SOCKET; ssh_free(session); } static void torture_packet_aes128_ctr_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes128-ctr", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_aes192_ctr_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes192-ctr", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_aes256_ctr_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes256-ctr", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_aes128_ctr(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes128-ctr", "hmac-sha1", "none", i); } } static void torture_packet_aes192_ctr(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes192-ctr", "hmac-sha1", "none", i); } } static void torture_packet_aes256_ctr(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes256-ctr", "hmac-sha1", "none", i); } } static void torture_packet_aes128_cbc(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes128-cbc", "hmac-sha1", "none", i); } } static void torture_packet_aes192_cbc(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes192-cbc", "hmac-sha1", "none", i); } } static void torture_packet_aes256_cbc(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes256-cbc", "hmac-sha1", "none", i); } } static void torture_packet_aes128_cbc_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes128-cbc", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_aes192_cbc_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes192-cbc", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_aes256_cbc_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("aes256-cbc", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_3des_cbc(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("3des-cbc", "hmac-sha1", "none", i); } } static void torture_packet_3des_cbc_etm(UNUSED_PARAM(void **state)) { int i; for (i = 1; i < 256; ++i) { torture_packet("3des-cbc", "hmac-sha1-etm@openssh.com", "none", i); } } static void torture_packet_chacha20(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("chacha20-poly1305@openssh.com", "none", "none", i); } } static void torture_packet_aes128_gcm(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes128-gcm@openssh.com", "none", "none", i); } } static void torture_packet_aes256_gcm(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes256-gcm@openssh.com", "none", "none", i); } } static void torture_packet_compress_zlib(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes256-ctr", "hmac-sha1", "zlib", i); } } static void torture_packet_compress_zlib_openssh(void **state) { int i; (void)state; /* unused */ for (i=1;i<256;++i){ torture_packet("aes256-ctr", "hmac-sha1", "zlib@openssh.com", i); } } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_packet_aes128_ctr), cmocka_unit_test(torture_packet_aes192_ctr), cmocka_unit_test(torture_packet_aes256_ctr), cmocka_unit_test(torture_packet_aes128_ctr_etm), cmocka_unit_test(torture_packet_aes192_ctr_etm), cmocka_unit_test(torture_packet_aes256_ctr_etm), cmocka_unit_test(torture_packet_aes128_cbc), cmocka_unit_test(torture_packet_aes192_cbc), cmocka_unit_test(torture_packet_aes256_cbc), cmocka_unit_test(torture_packet_aes128_cbc_etm), cmocka_unit_test(torture_packet_aes192_cbc_etm), cmocka_unit_test(torture_packet_aes256_cbc_etm), cmocka_unit_test(torture_packet_3des_cbc), cmocka_unit_test(torture_packet_3des_cbc_etm), cmocka_unit_test(torture_packet_chacha20), cmocka_unit_test(torture_packet_aes128_gcm), cmocka_unit_test(torture_packet_aes256_gcm), cmocka_unit_test(torture_packet_compress_zlib), cmocka_unit_test(torture_packet_compress_zlib_openssh), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_packet_filter.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ /* * This test checks if the messages accepted by the packet filter were intented * to be accepted. * * The process consists in 2 steps: * - Try the filter with a message type in an arbitrary state * - If the message is accepted by the filter, check if the message is in the * set of accepted states. * * Only the values selected by the flag (COMPARE_*) are considered. * */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/priv.h" #include "libssh/libssh.h" #include "libssh/session.h" #include "libssh/auth.h" #include "libssh/ssh2.h" #include "libssh/packet.h" #include "packet.c" #define COMPARE_SESSION_STATE 1 #define COMPARE_ROLE (1 << 1) #define COMPARE_DH_STATE (1 << 2) #define COMPARE_AUTH_STATE (1 << 3) #define COMPARE_GLOBAL_REQ_STATE (1 << 4) #define COMPARE_CURRENT_METHOD (1 << 5) #define SESSION_STATE_COUNT 11 #define DH_STATE_COUNT 4 #define AUTH_STATE_COUNT 15 #define GLOBAL_REQ_STATE_COUNT 5 #define MESSAGE_COUNT 100 // from 1 to 100 #define ROLE_CLIENT 0 #define ROLE_SERVER 1 /* * This is the list of currently unfiltered message types. * Only unrecognized types should be in this list. * */ static uint8_t unfiltered[] = { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 54, 55, 56, 57, 58, 59, 62, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 83, 84, 85, 86, 87, 88, 89, }; typedef struct global_state_st { /* If the bit in this flag is zero, the corresponding state is not * considered, working as a wildcard (meaning any value is accepted) */ uint32_t flags; uint8_t role; enum ssh_session_state_e session; enum ssh_dh_state_e dh; enum ssh_auth_state_e auth; enum ssh_channel_request_state_e global_req; } global_state; static int cmp_state(const void *e1, const void *e2) { global_state *s1 = (global_state *) e1; global_state *s2 = (global_state *) e2; /* Compare role (client == 0 or server == 1)*/ if (s1->role < s2->role) { return -1; } else if (s1->role > s2->role) { return 1; } /* Compare session state */ if (s1->session < s2->session) { return -1; } else if (s1->session > s2->session) { return 1; } /* Compare DH state */ if (s1->dh < s2->dh) { return -1; } else if (s1->dh > s2->dh) { return 1; } /* Compare auth */ if (s1->auth < s2->auth) { return -1; } else if (s1->auth > s2->auth) { return 1; } /* Compare global_req */ if (s1->global_req < s2->global_req) { return -1; } else if (s1->global_req > s2->global_req) { return 1; } /* If all equal, they are equal */ return 0; } static int cmp_state_search(const void *key, const void *array_element) { global_state *s1 = (global_state *) key; global_state *s2 = (global_state *) array_element; int result = 0; if (s2->flags & COMPARE_ROLE) { /* Compare role (client == 0 or server == 1)*/ if (s1->role < s2->role) { return -1; } else if (s1->role > s2->role) { return 1; } } if (s2->flags & COMPARE_SESSION_STATE) { /* Compare session state */ if (s1->session < s2->session) { result = -1; goto end; } else if (s1->session > s2->session) { result = 1; goto end; } } if (s2->flags & COMPARE_DH_STATE) { /* Compare DH state */ if (s1->dh < s2->dh) { result = -1; goto end; } else if (s1->dh > s2->dh) { result = 1; goto end; } } if (s2->flags & COMPARE_AUTH_STATE) { /* Compare auth */ if (s1->auth < s2->auth) { result = -1; goto end; } else if (s1->auth > s2->auth) { result = 1; goto end; } } if (s2->flags & COMPARE_GLOBAL_REQ_STATE) { /* Compare global_req */ if (s1->global_req < s2->global_req) { result = -1; goto end; } else if (s1->global_req > s2->global_req) { result = 1; goto end; } } end: return result; } static int is_state_accepted(global_state *tested, global_state *accepted, int accepted_len) { global_state *found = NULL; found = bsearch(tested, accepted, accepted_len, sizeof(global_state), cmp_state_search); if (found != NULL) { return 1; } return 0; } static int cmp_uint8(const void *i, const void *j) { uint8_t e1 = *((uint8_t *)i); uint8_t e2 = *((uint8_t *)j); if (e1 < e2) { return -1; } else if (e1 > e2) { return 1; } return 0; } static int check_unfiltered(uint8_t msg_type) { uint8_t *found; found = bsearch(&msg_type, unfiltered, sizeof(unfiltered)/sizeof(uint8_t), sizeof(uint8_t), cmp_uint8); if (found != NULL) { return 1; } return 0; } static void torture_packet_filter_check_unfiltered(void **state) { ssh_session session; int role_c; int auth_c; int session_c; int dh_c; int global_req_c; uint8_t msg_type; enum ssh_packet_filter_result_e rc; int in_unfiltered; (void)state; session = ssh_new(); for (msg_type = 1; msg_type <= MESSAGE_COUNT; msg_type++) { session->in_packet.type = msg_type; for (role_c = 0; role_c < 2; role_c++) { session->server = role_c; for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) { session->session_state = session_c; for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) { session->dh_handshake_state = dh_c; for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) { session->auth.state = auth_c; for (global_req_c = 0; global_req_c < GLOBAL_REQ_STATE_COUNT; global_req_c++) { session->global_req_state = global_req_c; rc = ssh_packet_incoming_filter(session); if (rc == SSH_PACKET_UNKNOWN) { in_unfiltered = check_unfiltered(msg_type); if (!in_unfiltered) { fprintf(stderr, "Message type %d UNFILTERED " "in state: role %d, session %d, dh %d, auth %d\n", msg_type, role_c, session_c, dh_c, auth_c); } assert_int_equal(in_unfiltered, 1); } else { in_unfiltered = check_unfiltered(msg_type); if (in_unfiltered) { fprintf(stderr, "Message type %d NOT UNFILTERED " "in state: role %d, session %d, dh %d, auth %d\n", msg_type, role_c, session_c, dh_c, auth_c); } assert_int_equal(in_unfiltered, 0); } } } } } } } ssh_free(session); } static int check_message_in_all_states(global_state accepted[], int accepted_count, uint8_t msg_type) { ssh_session session; int role_c; int auth_c; int session_c; int dh_c; int global_req_c; enum ssh_packet_filter_result_e rc; int in_accepted; global_state key; session = ssh_new(); /* Sort the accepted array so that the elements can be searched using * bsearch */ qsort(accepted, accepted_count, sizeof(global_state), cmp_state); session->in_packet.type = msg_type; for (role_c = 0; role_c < 2; role_c++) { session->server = role_c; key.role = role_c; for (session_c = 0; session_c < SESSION_STATE_COUNT; session_c++) { session->session_state = session_c; key.session = session_c; for (dh_c = 0; dh_c < DH_STATE_COUNT; dh_c++) { session->dh_handshake_state = dh_c; key.dh = dh_c; for (auth_c = 0; auth_c < AUTH_STATE_COUNT; auth_c++) { session->auth.state = auth_c; key.auth = auth_c; for (global_req_c = 0; global_req_c < GLOBAL_REQ_STATE_COUNT; global_req_c++) { session->global_req_state = global_req_c; key.global_req = global_req_c; rc = ssh_packet_incoming_filter(session); if (rc == SSH_PACKET_ALLOWED) { in_accepted = is_state_accepted(&key, accepted, accepted_count); if (!in_accepted) { fprintf(stderr, "Message type %d ALLOWED " "in state: role %d, session %d, dh %d, auth %d\n", msg_type, role_c, session_c, dh_c, auth_c); } assert_int_equal(in_accepted, 1); } else if (rc == SSH_PACKET_DENIED) { in_accepted = is_state_accepted(&key, accepted, accepted_count); if (in_accepted) { fprintf(stderr, "Message type %d DENIED " "in state: role %d, session %d, dh %d, auth %d\n", msg_type, role_c, session_c, dh_c, auth_c); } assert_int_equal(in_accepted, 0); } else { fprintf(stderr, "Message type %d UNFILTERED " "in state: role %d, session %d, dh %d, auth %d\n", msg_type, role_c, session_c, dh_c, auth_c); } } } } } } ssh_free(session); return 0; } static void torture_packet_filter_check_auth_success(void **state) { int rc; global_state accepted[] = { { .flags = (COMPARE_SESSION_STATE | COMPARE_ROLE | COMPARE_AUTH_STATE | COMPARE_DH_STATE), .role = ROLE_CLIENT, .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, .auth = SSH_AUTH_STATE_PUBKEY_AUTH_SENT, }, { .flags = (COMPARE_SESSION_STATE | COMPARE_ROLE | COMPARE_AUTH_STATE | COMPARE_DH_STATE), .role = ROLE_CLIENT, .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, .auth = SSH_AUTH_STATE_PASSWORD_AUTH_SENT, }, { .flags = (COMPARE_SESSION_STATE | COMPARE_ROLE | COMPARE_AUTH_STATE | COMPARE_DH_STATE), .role = ROLE_CLIENT, .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, .auth = SSH_AUTH_STATE_GSSAPI_MIC_SENT, }, { .flags = (COMPARE_SESSION_STATE | COMPARE_ROLE | COMPARE_AUTH_STATE | COMPARE_DH_STATE), .role = ROLE_CLIENT, .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, .auth = SSH_AUTH_STATE_KBDINT_SENT, }, { .flags = (COMPARE_SESSION_STATE | COMPARE_ROLE | COMPARE_AUTH_STATE | COMPARE_DH_STATE | COMPARE_CURRENT_METHOD), .role = ROLE_CLIENT, .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, .auth = SSH_AUTH_STATE_AUTH_NONE_SENT, } }; int accepted_count = 5; /* Unused */ (void) state; rc = check_message_in_all_states(accepted, accepted_count, SSH2_MSG_USERAUTH_SUCCESS); assert_int_equal(rc, 0); } static void torture_packet_filter_check_msg_ext_info(void **state) { int rc; global_state accepted[] = { { .flags = (COMPARE_SESSION_STATE | COMPARE_DH_STATE), .session = SSH_SESSION_STATE_AUTHENTICATING, .dh = DH_STATE_FINISHED, }, { .flags = (COMPARE_SESSION_STATE | COMPARE_DH_STATE), .session = SSH_SESSION_STATE_AUTHENTICATED, .dh = DH_STATE_FINISHED, }, }; int accepted_count = 2; /* Unused */ (void) state; rc = check_message_in_all_states(accepted, accepted_count, SSH2_MSG_EXT_INFO); assert_int_equal(rc, 0); } static void torture_packet_filter_check_channel_open(void **state) { int rc; /* The only condition to accept a CHANNEL_OPEN is to be authenticated */ global_state accepted[] = { { .flags = COMPARE_SESSION_STATE, .session = SSH_SESSION_STATE_AUTHENTICATED, } }; int accepted_count = 1; /* Unused */ (void) state; rc = check_message_in_all_states(accepted, accepted_count, SSH2_MSG_CHANNEL_OPEN); assert_int_equal(rc, 0); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_packet_filter_check_auth_success), cmocka_unit_test(torture_packet_filter_check_channel_open), cmocka_unit_test(torture_packet_filter_check_unfiltered), cmocka_unit_test(torture_packet_filter_check_msg_ext_info) }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_pki.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include "torture.h" #include "torture_pki.h" #include "torture_key.h" #include "pki.c" const unsigned char INPUT[] = "1234567890123456789012345678901234567890" "123456789012345678901234"; const char template[] = "temp_dir_XXXXXX"; struct pki_st { char *cwd; char *temp_dir; }; static int setup_cert_dir(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); return 0; } static int teardown_cert_dir(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static void torture_pki_keytype(void **state) { enum ssh_keytypes_e type; const char *type_c; (void) state; /* unused */ type = ssh_key_type(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name(NULL); assert_true(type == SSH_KEYTYPE_UNKNOWN); type = ssh_key_type_from_name("42"); assert_true(type == SSH_KEYTYPE_UNKNOWN); type_c = ssh_key_type_to_char(SSH_KEYTYPE_UNKNOWN); assert_null(type_c); type_c = ssh_key_type_to_char(42); assert_null(type_c); } static void torture_pki_signature(void **state) { ssh_signature sig; (void) state; /* unused */ sig = ssh_signature_new(); assert_non_null(sig); ssh_signature_free(sig); } struct key_attrs { int sign; int verify; const char *type_c; int size_arg; int sig_length; const char *sig_type_c; int expect_success; }; struct key_attrs key_attrs_list[][5] = { { {0, 0, "", 0, 0, "", 0}, /* UNKNOWN, AUTO */ {0, 0, "", 0, 0, "", 0}, /* UNKNOWN, SHA1 */ {0, 0, "", 0, 0, "", 0}, /* UNKNOWN, SHA256 */ {0, 0, "", 0, 0, "", 0}, /* UNKNOWN, SHA384 */ {0, 0, "", 0, 0, "", 0}, /* UNKNOWN, SHA512 */ }, #ifdef HAVE_DSA { {1, 1, "ssh-dss", 1024, 0, "", 0}, /* DSS, AUTO */ {1, 1, "ssh-dss", 1024, 20, "ssh-dss", 1}, /* DSS, SHA1 */ {1, 1, "ssh-dss", 1024, 0, "", 0}, /* DSS, SHA256 */ {1, 1, "ssh-dss", 1024, 0, "", 0}, /* DSS, SHA384 */ {1, 1, "ssh-dss", 1024, 0, "", 0}, /* DSS, SHA512 */ }, #else { {0, 0, "", 0, 0, "", 0}, /* DSS, AUTO */ {0, 0, "", 0, 0, "", 0}, /* DSS, SHA1 */ {0, 0, "", 0, 0, "", 0}, /* DSS, SHA256 */ {0, 0, "", 0, 0, "", 0}, /* DSS, SHA384 */ {0, 0, "", 0, 0, "", 0}, /* DSS, SHA512 */ }, #endif /* HAVE_DSA */ { {1, 1, "ssh-rsa", 2048, 0, "", 0}, /* RSA, AUTO */ {1, 1, "ssh-rsa", 2048, 20, "ssh-rsa", 1}, /* RSA, SHA1 */ {1, 1, "ssh-rsa", 2048, 32, "rsa-sha2-256", 1}, /* RSA, SHA256 */ {1, 1, "ssh-rsa", 2048, 0, "", 0}, /* RSA, SHA384 */ {1, 1, "ssh-rsa", 2048, 64, "rsa-sha2-512", 1}, /* RSA, SHA512 */ }, { {0, 0, "", 0, 0, "", 0}, /* RSA1, AUTO */ {0, 0, "", 0, 0, "", 0}, /* RSA1, SHA1 */ {0, 0, "", 0, 0, "", 0}, /* RSA1, SHA256 */ {0, 0, "", 0, 0, "", 0}, /* RSA1, SHA384 */ {0, 0, "", 0, 0, "", 0}, /* RSA1, SHA512 */ }, { {0, 1, "", 256, 0, "", 0}, /* ECDSA, AUTO */ {0, 1, "", 256, 0, "", 0}, /* ECDSA, SHA1 */ {0, 1, "", 256, 0, "", 0}, /* ECDSA, SHA256 */ {0, 1, "", 384, 0, "", 0}, /* ECDSA, SHA384 */ {0, 1, "", 521, 0, "", 0}, /* ECDSA, SHA512 */ }, { {1, 1, "ssh-ed25519", 0, 33, "ssh-ed25519", 1}, /* ED25519, AUTO */ {1, 1, "ssh-ed25519", 0, 0, "", 0}, /* ED25519, SHA1 */ {1, 1, "ssh-ed25519", 0, 0, "", 0}, /* ED25519, SHA256 */ {1, 1, "ssh-ed25519", 0, 0, "", 0}, /* ED25519, SHA384 */ {1, 1, "ssh-ed25519", 0, 0, "", 0}, /* ED25519, SHA512 */ }, #ifdef HAVE_DSA { {0, 1, "", 0, 0, "", 0}, /* DSS CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* DSS CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* DSS CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* DSS CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* DSS CERT, SHA512 */ }, #else { {0, 0, "", 0, 0, "", 0}, /* DSS CERT, AUTO */ {0, 0, "", 0, 0, "", 0}, /* DSS CERT, SHA1 */ {0, 0, "", 0, 0, "", 0}, /* DSS CERT, SHA256 */ {0, 0, "", 0, 0, "", 0}, /* DSS CERT, SHA384 */ {0, 0, "", 0, 0, "", 0}, /* DSS CERT, SHA512 */ }, #endif /* HAVE_DSA */ { {0, 1, "", 0, 0, "", 0}, /* RSA CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* RSA CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* RSA CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* RSA CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* RSA CERT, SHA512 */ }, #ifdef HAVE_ECC { {1, 1, "ecdsa-sha2-nistp256", 256, 0, "", 0}, /* ECDSA P256, AUTO */ {1, 1, "ecdsa-sha2-nistp256", 256, 0, "", 0}, /* ECDSA P256, SHA1 */ {1, 1, "ecdsa-sha2-nistp256", 256, 32, "ecdsa-sha2-nistp256", 1}, /* ECDSA P256, SHA256 */ {1, 1, "ecdsa-sha2-nistp256", 256, 0, "", 0}, /* ECDSA P256, SHA384 */ {1, 1, "ecdsa-sha2-nistp256", 256, 0, "", 0}, /* ECDSA P256, SHA512 */ }, { {1, 1, "ecdsa-sha2-nistp384", 384, 0, "", 0}, /* ECDSA P384, AUTO */ {1, 1, "ecdsa-sha2-nistp384", 384, 0, "", 0}, /* ECDSA P384, SHA1 */ {1, 1, "ecdsa-sha2-nistp384", 384, 0, "", 0}, /* ECDSA P384, SHA256 */ {1, 1, "ecdsa-sha2-nistp384", 384, 48, "ecdsa-sha2-nistp384", 1}, /* ECDSA P384, SHA384 */ {1, 1, "ecdsa-sha2-nistp384", 384, 0, "", 0}, /* ECDSA P384, SHA512 */ }, { {1, 1, "ecdsa-sha2-nistp521", 521, 0, "", 0}, /* ECDSA P521, AUTO */ {1, 1, "ecdsa-sha2-nistp521", 521, 0, "", 0}, /* ECDSA P521, SHA1 */ {1, 1, "ecdsa-sha2-nistp521", 521, 0, "", 0}, /* ECDSA P521, SHA256 */ {1, 1, "ecdsa-sha2-nistp521", 521, 0, "", 0}, /* ECDSA P521, SHA384 */ {1, 1, "ecdsa-sha2-nistp521", 521, 64, "ecdsa-sha2-nistp521", 1}, /* ECDSA P521, SHA512 */ }, { {0, 1, "", 0, 0, "", 0}, /* ECDSA P256 CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P256 CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P256 CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P256 CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P256 CERT, SHA512 */ }, { {0, 1, "", 0, 0, "", 0}, /* ECDSA P384 CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P384 CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P384 CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P384 CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P384 CERT, SHA512 */ }, { {0, 1, "", 0, 0, "", 0}, /* ECDSA P521 CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P521 CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P521 CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P521 CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* ECDSA P521 CERT, SHA512 */ }, #endif /* HAVE_ECC */ { {0, 1, "", 0, 0, "", 0}, /* ED25519 CERT, AUTO */ {0, 1, "", 0, 0, "", 0}, /* ED25519 CERT, SHA1 */ {0, 1, "", 0, 0, "", 0}, /* ED25519 CERT, SHA256 */ {0, 1, "", 0, 0, "", 0}, /* ED25519 CERT, SHA384 */ {0, 1, "", 0, 0, "", 0}, /* ED25519 CERT, SHA512 */ }, }; /* This tests all the base types and their signatures against each other */ static void torture_pki_verify_mismatch(void **state) { int rc; int verbosity = torture_libssh_verbosity(); ssh_key key = NULL, verify_key = NULL, pubkey = NULL, verify_pubkey = NULL; ssh_signature sign = NULL, import_sig = NULL, new_sig = NULL; ssh_string blob; ssh_session session = ssh_new(); enum ssh_keytypes_e key_type, sig_type; enum ssh_digest_e hash; size_t input_length = sizeof(INPUT); struct key_attrs skey_attrs, vkey_attrs; (void) state; ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); for (sig_type = SSH_KEYTYPE_DSS; sig_type <= SSH_KEYTYPE_ED25519_CERT01; sig_type++) { for (hash = SSH_DIGEST_AUTO; hash <= SSH_DIGEST_SHA512; hash++) { if (ssh_fips_mode()) { if (sig_type == SSH_KEYTYPE_DSS || sig_type == SSH_KEYTYPE_ED25519 || hash == SSH_DIGEST_SHA1) { /* In FIPS mode, skip unsupported algorithms */ continue; } } skey_attrs = key_attrs_list[sig_type][hash]; if (!skey_attrs.sign) { continue; } rc = ssh_pki_generate(sig_type, skey_attrs.size_arg, &key); assert_true(rc == SSH_OK); assert_non_null(key); assert_int_equal(key->type, sig_type); assert_string_equal(key->type_c, skey_attrs.type_c); SSH_LOG(SSH_LOG_TRACE, "Creating signature %d with hash %d", sig_type, hash); if (skey_attrs.expect_success == 0) { /* Expect error */ sign = pki_do_sign(key, INPUT, input_length, hash); assert_null(sign); SSH_KEY_FREE(key); continue; } rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Create a valid signature using this key */ sign = pki_do_sign(key, INPUT, input_length, hash); assert_non_null(sign); assert_int_equal(sign->type, key->type); assert_string_equal(sign->type_c, skey_attrs.sig_type_c); /* Create a signature blob that can be imported and verified */ blob = pki_signature_to_blob(sign); assert_non_null(blob); /* Import and verify with current key * (this is not tested anywhere else yet) */ import_sig = pki_signature_from_blob(key, blob, sig_type, hash); assert_non_null(import_sig); assert_int_equal(import_sig->type, key->type); assert_string_equal(import_sig->type_c, skey_attrs.sig_type_c); rc = ssh_pki_signature_verify(session, import_sig, pubkey, INPUT, input_length); assert_true(rc == SSH_OK); for (key_type = SSH_KEYTYPE_DSS; key_type <= SSH_KEYTYPE_ED25519_CERT01; key_type++) { if (ssh_fips_mode()) { if (key_type == SSH_KEYTYPE_DSS || key_type == SSH_KEYTYPE_ED25519) { /* In FIPS mode, skip unsupported algorithms */ continue; } } vkey_attrs = key_attrs_list[key_type][hash]; if (!vkey_attrs.verify) { continue; } SSH_LOG(SSH_LOG_TRACE, "Trying key %d with signature %d", key_type, sig_type); if (is_cert_type(key_type)) { torture_write_file("libssh_testkey-cert.pub", torture_get_testkey_pub(key_type)); rc = ssh_pki_import_cert_file("libssh_testkey-cert.pub", &verify_pubkey); verify_key = NULL; } else { rc = ssh_pki_generate(key_type, vkey_attrs.size_arg, &verify_key); assert_int_equal(rc, SSH_OK); assert_non_null(verify_key); rc = ssh_pki_export_privkey_to_pubkey(verify_key, &verify_pubkey); } assert_int_equal(rc, SSH_OK); assert_non_null(verify_pubkey); /* Should gracefully fail, but not crash */ rc = ssh_pki_signature_verify(session, sign, verify_pubkey, INPUT, input_length); assert_true(rc != SSH_OK); /* Try the same with the imported signature */ rc = ssh_pki_signature_verify(session, import_sig, verify_pubkey, INPUT, input_length); assert_true(rc != SSH_OK); /* Try to import the signature blob with different key */ new_sig = pki_signature_from_blob(verify_pubkey, blob, sig_type, import_sig->hash_type); if (ssh_key_type_plain(verify_pubkey->type) == sig_type) { /* Importing with the same key type should work */ assert_non_null(new_sig); assert_int_equal(new_sig->type, key->type); assert_string_equal(new_sig->type_c, skey_attrs.sig_type_c); /* The verification should not work */ rc = ssh_pki_signature_verify(session, new_sig, verify_pubkey, INPUT, input_length); assert_true(rc != SSH_OK); ssh_signature_free(new_sig); } else { assert_null(new_sig); } SSH_KEY_FREE(verify_key); SSH_KEY_FREE(verify_pubkey); } ssh_string_free(blob); ssh_signature_free(sign); ssh_signature_free(import_sig); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); key = NULL; } } ssh_free(session); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_pki_keytype), cmocka_unit_test(torture_pki_signature), cmocka_unit_test_setup_teardown(torture_pki_verify_mismatch, setup_cert_dir, teardown_cert_dir), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_pki_dsa.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include #include "torture.h" #include "torture_key.h" #include "torture_pki.h" #include "pki.c" #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" #define LIBSSH_DSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_dsa" const char template[] = "temp_dir_XXXXXX"; const unsigned char INPUT[] = "12345678901234567890"; struct pki_st { char *cwd; char *temp_dir; }; static int setup_dsa_key(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_DSS, 0)); torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, torture_get_testkey(SSH_KEYTYPE_DSS, 1)); torture_write_file(LIBSSH_DSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS)); torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS_CERT01)); return 0; } static int setup_openssh_dsa_key(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 0)); torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 1)); torture_write_file(LIBSSH_DSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS)); torture_write_file(LIBSSH_DSA_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS_CERT01)); return 0; } static int teardown(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static void torture_pki_dsa_import_pubkey_file(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_dsa_import_pubkey_from_openssh_privkey(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_dsa_import_privkey_base64(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0), passphrase, NULL, NULL, &key); assert_true(rc == 0); SSH_KEY_FREE(key); } static void torture_pki_dsa_import_privkey_base64_comment(void **state) { int rc, file_str_len; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *comment_str = "#this is line-comment\n#this is another\n"; const char *key_str = NULL; char *file_str = NULL; (void) state; /* unused */ key_str = torture_get_testkey(SSH_KEYTYPE_DSS, 0); assert_non_null(key_str); file_str_len = strlen(comment_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", comment_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_dsa_import_privkey_base64_whitespace(void **state) { int rc, file_str_len; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *whitespace_str = " \n\t\t\t\t\t\n\n\n\n\n"; const char *key_str = NULL; char *file_str = NULL; (void) state; /* unused */ key_str = torture_get_testkey(SSH_KEYTYPE_DSS, 0); assert_non_null(key_str); file_str_len = strlen(whitespace_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", whitespace_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); free(file_str); SSH_KEY_FREE(key); } static int test_sign_verify_data(ssh_key key, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { ssh_signature sig; ssh_key pubkey = NULL; int rc; /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, hash_type, input, input_len); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, input, input_len); assert_int_equal(rc, SSH_OK); ssh_signature_free(sig); SSH_KEY_FREE(pubkey); return rc; } static void torture_pki_sign_data_dsa(void **state) { int rc; ssh_key key = NULL; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 2048, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); /* Test using SHA1 */ rc = test_sign_verify_data(key, SSH_DIGEST_SHA1, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Cleanup */ SSH_KEY_FREE(key); } static void torture_pki_fail_sign_with_incompatible_hash(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; ssh_signature sig, bad_sig; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 2048, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, SSH_DIGEST_SHA1, INPUT, sizeof(INPUT)); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_AUTO */ bad_sig = pki_sign_data(key, SSH_DIGEST_AUTO, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_AUTO */ sig->hash_type = SSH_DIGEST_AUTO; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA256 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA256, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA256 */ sig->hash_type = SSH_DIGEST_SHA256; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA384 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA384, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA384 */ sig->hash_type = SSH_DIGEST_SHA384; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA512 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA512, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA512 */ sig->hash_type = SSH_DIGEST_SHA512; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Cleanup */ ssh_signature_free(sig); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(key); } #ifdef HAVE_LIBCRYPTO static void torture_pki_dsa_write_privkey(void **state) { ssh_key origkey = NULL; ssh_key privkey = NULL; int rc; (void) state; /* unused */ rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_DSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, NULL, NULL, NULL, LIBSSH_DSA_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); /* Test with passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE); rc = ssh_pki_export_privkey_file(origkey, torture_get_testkey_passphrase(), NULL, NULL, LIBSSH_DSA_TESTKEY_PASSPHRASE); assert_true(rc == 0); /* Test with invalid passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, "invalid secret", NULL, NULL, &privkey); assert_true(rc == SSH_ERROR); assert_null(privkey); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } #endif static void torture_pki_dsa_import_privkey_base64_passphrase(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* test if it returns -1 if passphrase is NULL */ /* libcrypto asks for a passphrase, so skip this test */ #ifndef HAVE_LIBCRYPTO rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), NULL, NULL, NULL, &key); assert_true(rc == -1); assert_null(key); #endif rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* This free in unnecessary, but the static analyser does not know */ SSH_KEY_FREE(key); #ifndef HAVE_LIBCRYPTO /* test if it returns -1 if passphrase is NULL */ /* libcrypto asks for a passphrase, so skip this test */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 1), NULL, NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* This free in unnecessary, but the static analyser does not know */ SSH_KEY_FREE(key); #endif /* HAVE_LIBCRYPTO */ } static void torture_pki_dsa_import_openssh_privkey_base64_passphrase(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *keystring = NULL; (void) state; /* unused */ keystring = torture_get_openssh_testkey(SSH_KEYTYPE_DSS, 1); assert_non_null(keystring); rc = ssh_pki_import_privkey_base64(keystring, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(keystring, "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* test if it returns -1 if passphrase is NULL */ rc = ssh_pki_import_privkey_base64(keystring, NULL, NULL, NULL, &key); assert_true(rc == -1); rc = ssh_pki_import_privkey_base64(keystring, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(keystring, "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* This free is unnecessary, but the static analyser does not know */ SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is NULL */ rc = ssh_pki_import_privkey_base64(keystring, NULL, NULL, NULL, &key); assert_true(rc == -1); assert_null(key); /* This free is unnecessary, but the static analyser does not know */ SSH_KEY_FREE(key); } static void torture_pki_dsa_publickey_from_privatekey(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; const char *passphrase = NULL; (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_DSS, 0), passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); } static void torture_pki_dsa_import_cert_file(void **state) { int rc; ssh_key cert = NULL; enum ssh_keytypes_e type; (void) state; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_DSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); type = ssh_key_type(cert); assert_true(type == SSH_KEYTYPE_DSS_CERT01); rc = ssh_key_is_public(cert); assert_true(rc == 1); SSH_KEY_FREE(cert); } static void torture_pki_dsa_publickey_base64(void **state) { enum ssh_keytypes_e type; char *b64_key = NULL, *key_buf = NULL, *p = NULL; const char *str = NULL; ssh_key key = NULL; size_t keylen; size_t i; int rc; (void) state; /* unused */ key_buf = strdup(torture_get_testkey_pub(SSH_KEYTYPE_DSS)); assert_non_null(key_buf); keylen = strlen(key_buf); str = p = key_buf; for (i = 0; i < keylen; i++) { if (isspace((int)p[i])) { p[i] = '\0'; break; } } type = ssh_key_type_from_name(str); assert_true(type == SSH_KEYTYPE_DSS); str = &p[i + 1]; for (; i < keylen; i++) { if (isspace((int)p[i])) { p[i] = '\0'; break; } } rc = ssh_pki_import_pubkey_base64(str, type, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); assert_string_equal(str, b64_key); free(b64_key); free(key_buf); SSH_KEY_FREE(key); } static void torture_pki_dsa_generate_pubkey_from_privkey(void **state) { char pubkey_generated[4096] = {0}; ssh_key privkey = NULL; ssh_key pubkey = NULL; int len; int rc; (void) state; /* unused */ /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_DSA_TESTKEY ".pub"); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_file(pubkey, LIBSSH_DSA_TESTKEY ".pub"); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_DSA_TESTKEY ".pub", pubkey_generated, sizeof(pubkey_generated)); assert_true(rc == 0); len = torture_pubkey_len(torture_get_testkey_pub(SSH_KEYTYPE_DSS)); assert_memory_equal(torture_get_testkey_pub(SSH_KEYTYPE_DSS), pubkey_generated, len); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); } static void torture_pki_dsa_duplicate_key(void **state) { int rc; char *b64_key = NULL; char *b64_key_gen = NULL; ssh_key pubkey = NULL; ssh_key pubkey_dup = NULL; ssh_key privkey = NULL; ssh_key privkey_dup = NULL; (void) state; rc = ssh_pki_import_pubkey_file(LIBSSH_DSA_TESTKEY ".pub", &pubkey); assert_true(rc == 0); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); privkey_dup = ssh_key_dup(privkey); assert_non_null(privkey_dup); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey_dup); assert_true(rc == SSH_OK); assert_non_null(pubkey_dup); rc = ssh_pki_export_pubkey_base64(pubkey_dup, &b64_key_gen); assert_true(rc == 0); assert_non_null(b64_key_gen); assert_string_equal(b64_key, b64_key_gen); rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); rc = ssh_key_cmp(pubkey, pubkey_dup, SSH_KEY_CMP_PUBLIC); assert_true(rc == 0); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(pubkey_dup); SSH_KEY_FREE(privkey); SSH_KEY_FREE(privkey_dup); SSH_STRING_FREE_CHAR(b64_key); SSH_STRING_FREE_CHAR(b64_key_gen); } static void torture_pki_dsa_generate_key(void **state) { int rc; ssh_key key = NULL, pubkey = NULL; ssh_signature sign = NULL; ssh_session session=ssh_new(); (void) state; rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 1024, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA1); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 2048, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA1); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); rc = ssh_pki_generate(SSH_KEYTYPE_DSS, 3072, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA1); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); ssh_free(session); } static void torture_pki_dsa_cert_verify(void **state) { int rc; ssh_key privkey = NULL, cert = NULL; ssh_signature sign = NULL; ssh_session session=ssh_new(); (void) state; rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_import_cert_file(LIBSSH_DSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); sign = pki_do_sign(privkey, INPUT, sizeof(INPUT), SSH_DIGEST_SHA1); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, cert, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(privkey); SSH_KEY_FREE(cert); ssh_free(session); } static void torture_pki_dsa_skip(UNUSED_PARAM(void **state)) { skip(); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_file, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_pubkey_from_openssh_privkey, setup_openssh_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64_comment, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64_whitespace, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_privkey_base64, setup_openssh_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_from_privatekey, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_import_cert_file, setup_dsa_key, teardown), #ifdef HAVE_LIBCRYPTO cmocka_unit_test_setup_teardown(torture_pki_dsa_write_privkey, setup_dsa_key, teardown), #endif cmocka_unit_test(torture_pki_sign_data_dsa), cmocka_unit_test(torture_pki_fail_sign_with_incompatible_hash), cmocka_unit_test(torture_pki_dsa_import_privkey_base64_passphrase), cmocka_unit_test(torture_pki_dsa_import_openssh_privkey_base64_passphrase), /* public key */ cmocka_unit_test_setup_teardown(torture_pki_dsa_publickey_base64, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_generate_pubkey_from_privkey, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_duplicate_key, setup_dsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_dsa_duplicate_key, setup_dsa_key, teardown), cmocka_unit_test(torture_pki_dsa_generate_key), cmocka_unit_test_setup_teardown(torture_pki_dsa_cert_verify, setup_dsa_key, teardown), }; struct CMUnitTest skip_tests[] = { cmocka_unit_test(torture_pki_dsa_skip) }; ssh_init(); if (ssh_fips_mode()) { rc = cmocka_run_group_tests(skip_tests, NULL, NULL); } else { torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); } ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_pki_ecdsa.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include "torture.h" #include "torture_key.h" #include "torture_pki.h" #include "pki.c" #define LIBSSH_ECDSA_TESTKEY "libssh_testkey.id_ecdsa" #define LIBSSH_ECDSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_ecdsa" const char template[] = "temp_dir_XXXXXX"; const unsigned char INPUT[] = "12345678901234567890"; struct pki_st { char *cwd; char *temp_dir; enum ssh_keytypes_e type; }; static int setup_ecdsa_key(void **state, int ecdsa_bits) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); switch (ecdsa_bits) { case 521: test_state->type = SSH_KEYTYPE_ECDSA_P521; break; case 384: test_state->type = SSH_KEYTYPE_ECDSA_P384; break; default: test_state->type = SSH_KEYTYPE_ECDSA_P256; break; } torture_write_file(LIBSSH_ECDSA_TESTKEY, torture_get_testkey(test_state->type, 0)); torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, torture_get_testkey(test_state->type, 1)); torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub", torture_get_testkey_pub(test_state->type)); torture_write_file(LIBSSH_ECDSA_TESTKEY "-cert.pub", torture_get_testkey_pub(test_state->type+3)); return 0; } static int setup_openssh_ecdsa_key(void **state, int ecdsa_bits) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; const char *keystring = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); switch (ecdsa_bits) { case 521: test_state->type = SSH_KEYTYPE_ECDSA_P521; break; case 384: test_state->type = SSH_KEYTYPE_ECDSA_P384; break; default: test_state->type = SSH_KEYTYPE_ECDSA_P256; break; } keystring = torture_get_openssh_testkey(test_state->type, 0); torture_write_file(LIBSSH_ECDSA_TESTKEY, keystring); keystring = torture_get_openssh_testkey(test_state->type, 1); torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, keystring); torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub", torture_get_testkey_pub(test_state->type)); torture_write_file(LIBSSH_ECDSA_TESTKEY "-cert.pub", torture_get_testkey_pub(test_state->type+3)); return 0; } static int setup_ecdsa_key_521(void **state) { setup_ecdsa_key(state, 521); return 0; } static int setup_ecdsa_key_384(void **state) { setup_ecdsa_key(state, 384); return 0; } static int setup_ecdsa_key_256(void **state) { setup_ecdsa_key(state, 256); return 0; } static int setup_openssh_ecdsa_key_521(void **state) { setup_openssh_ecdsa_key(state, 521); return 0; } static int setup_openssh_ecdsa_key_384(void **state) { setup_openssh_ecdsa_key(state, 384); return 0; } static int setup_openssh_ecdsa_key_256(void **state) { setup_openssh_ecdsa_key(state, 256); return 0; } static int teardown(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static void torture_pki_ecdsa_import_pubkey_file(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ecdsa_import_pubkey_from_openssh_privkey(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ecdsa_import_privkey_base64(void **state) { int rc; char *key_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY); assert_non_null(key_str); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); free(key_str); SSH_KEY_FREE(key); } static void torture_pki_ecdsa_import_privkey_base64_comment(void **state) { int rc, file_str_len; const char *comment_str = "#this is line-comment\n#this is another\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY); assert_non_null(key_str); file_str_len = strlen(comment_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", comment_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_ecdsa_import_privkey_base64_whitespace(void **state) { int rc, file_str_len; const char *whitespace_str = " \n\t\t\t\t\t\n\n\n\n\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY); assert_non_null(key_str); file_str_len = strlen(whitespace_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", whitespace_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_ecdsa_publickey_from_privatekey(void **state) { int rc; char *key_str = NULL; ssh_key key = NULL; ssh_key pubkey = NULL; const char *passphrase = NULL; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY); assert_non_null(key_str); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); free(key_str); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); } static void torture_pki_ecdsa_import_cert_file(void **state) { int rc; ssh_key cert = NULL; enum ssh_keytypes_e type; struct pki_st *test_state = *((struct pki_st **)state); rc = ssh_pki_import_cert_file(LIBSSH_ECDSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); type = ssh_key_type(cert); assert_true(type == test_state->type+3); rc = ssh_key_is_public(cert); assert_true(rc == 1); SSH_KEY_FREE(cert); } static void torture_pki_ecdsa_publickey_base64(void **state) { enum ssh_keytypes_e type; char *b64_key = NULL, *key_buf = NULL, *p = NULL; const char *q = NULL; ssh_key key = NULL; int rc; struct pki_st *test_state = *((struct pki_st **)state); key_buf = torture_pki_read_file(LIBSSH_ECDSA_TESTKEY ".pub"); assert_non_null(key_buf); q = p = key_buf; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } type = ssh_key_type_from_name(q); assert_true(type == test_state->type); q = ++p; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); assert_string_equal(q, b64_key); free(b64_key); free(key_buf); SSH_KEY_FREE(key); } static void torture_pki_ecdsa_generate_pubkey_from_privkey(void **state) { char pubkey_original[4096] = {0}; char pubkey_generated[4096] = {0}; ssh_key privkey = NULL; ssh_key pubkey = NULL; int rc; int len; (void) state; /* unused */ rc = torture_read_one_line(LIBSSH_ECDSA_TESTKEY ".pub", pubkey_original, sizeof(pubkey_original)); assert_true(rc == 0); /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_ECDSA_TESTKEY ".pub"); rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_file(pubkey, LIBSSH_ECDSA_TESTKEY ".pub"); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_ECDSA_TESTKEY ".pub", pubkey_generated, sizeof(pubkey_generated)); assert_true(rc == 0); len = torture_pubkey_len(pubkey_original); assert_int_equal(strncmp(pubkey_original, pubkey_generated, len), 0); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ecdsa_duplicate_key(void **state) { int rc; char *b64_key = NULL; char *b64_key_gen = NULL; ssh_key pubkey = NULL; ssh_key pubkey_dup = NULL; ssh_key privkey = NULL; ssh_key privkey_dup = NULL; (void) state; rc = ssh_pki_import_pubkey_file(LIBSSH_ECDSA_TESTKEY ".pub", &pubkey); assert_true(rc == 0); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); privkey_dup = ssh_key_dup(privkey); assert_non_null(privkey_dup); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey_dup); assert_true(rc == SSH_OK); assert_non_null(pubkey_dup); rc = ssh_pki_export_pubkey_base64(pubkey_dup, &b64_key_gen); assert_true(rc == 0); assert_non_null(b64_key_gen); assert_string_equal(b64_key, b64_key_gen); rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); rc = ssh_key_cmp(pubkey, pubkey_dup, SSH_KEY_CMP_PUBLIC); assert_true(rc == 0); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(pubkey_dup); SSH_KEY_FREE(privkey); SSH_KEY_FREE(privkey_dup); SSH_STRING_FREE_CHAR(b64_key); SSH_STRING_FREE_CHAR(b64_key_gen); } /* Test case for bug #147: Private ECDSA key duplication did not carry * over parts of the key that then caused subsequent key demotion to * fail. */ static void torture_pki_ecdsa_duplicate_then_demote(void **state) { ssh_key pubkey = NULL; ssh_key privkey = NULL; ssh_key privkey_dup = NULL; int rc; (void) state; rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_int_equal(rc, 0); assert_non_null(privkey); privkey_dup = ssh_key_dup(privkey); assert_non_null(privkey_dup); assert_int_equal(privkey->ecdsa_nid, privkey_dup->ecdsa_nid); rc = ssh_pki_export_privkey_to_pubkey(privkey_dup, &pubkey); assert_int_equal(rc, 0); assert_non_null(pubkey); assert_int_equal(pubkey->ecdsa_nid, privkey->ecdsa_nid); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(privkey); SSH_KEY_FREE(privkey_dup); } static void torture_pki_generate_key_ecdsa(void **state) { int rc; ssh_key key = NULL, pubkey = NULL; ssh_signature sign = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; const char *type_char = NULL; const char *etype_char = NULL; ssh_session session=ssh_new(); (void) state; rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA_P256, 0, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P256); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp256") == 0); etype_char = ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); /* deprecated */ rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 256, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P256); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp256") == 0); etype_char = ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp256") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA_P384, 0, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA384); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P384); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp384") == 0); etype_char =ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); /* deprecated */ rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 384, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA384); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P384); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp384") == 0); etype_char =ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp384") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA_P521, 0, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA512); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P521); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp521") == 0); etype_char =ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); /* deprecated */ rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 521, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA512); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ECDSA_P521); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ecdsa-sha2-nistp521") == 0); etype_char =ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, "ecdsa-sha2-nistp521") == 0); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); ssh_free(session); } static void torture_pki_ecdsa_cert_verify(void **state) { int rc; ssh_key privkey = NULL, cert = NULL; ssh_signature sign = NULL; ssh_session session=ssh_new(); enum ssh_digest_e hash_type; (void) state; rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_import_cert_file(LIBSSH_ECDSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); /* Get the hash type to be used in the signature based on the key type */ hash_type = ssh_key_type_to_hash(session, privkey->type); sign = pki_do_sign(privkey, INPUT, sizeof(INPUT), hash_type); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, cert, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(privkey); SSH_KEY_FREE(cert); ssh_free(session); } static int test_sign_verify_data(ssh_key key, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { ssh_signature sig; ssh_key pubkey = NULL; int rc; /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, hash_type, input, input_len); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, input, input_len); assert_int_equal(rc, SSH_OK); ssh_signature_free(sig); SSH_KEY_FREE(pubkey); return rc; } static void torture_pki_sign_data_ecdsa(void **state) { int rc; ssh_key key = NULL; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA, 256, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); /* Test using SHA256 */ rc = test_sign_verify_data(key, SSH_DIGEST_SHA256, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Cleanup */ SSH_KEY_FREE(key); } static void torture_pki_fail_sign_with_incompatible_hash(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; ssh_signature sig, bad_sig; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_ECDSA_P256, 256, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, SSH_DIGEST_SHA256, INPUT, sizeof(INPUT)); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_AUTO */ bad_sig = pki_sign_data(key, SSH_DIGEST_AUTO, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_AUTO */ sig->hash_type = SSH_DIGEST_AUTO; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA1 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA1, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA1 */ sig->hash_type = SSH_DIGEST_SHA1; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA384 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA384, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA384 */ sig->hash_type = SSH_DIGEST_SHA384; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_SHA512 */ bad_sig = pki_sign_data(key, SSH_DIGEST_SHA512, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_SHA512 */ sig->hash_type = SSH_DIGEST_SHA512; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Cleanup */ ssh_signature_free(sig); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(key); } #ifdef HAVE_LIBCRYPTO static void torture_pki_ecdsa_write_privkey(void **state) { ssh_key origkey = NULL; ssh_key privkey = NULL; int rc; (void) state; /* unused */ rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_ECDSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, NULL, NULL, NULL, LIBSSH_ECDSA_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); /* Test with passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE); rc = ssh_pki_export_privkey_file(origkey, torture_get_testkey_passphrase(), NULL, NULL, LIBSSH_ECDSA_TESTKEY_PASSPHRASE); assert_true(rc == 0); /* Test with invalid passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, "invalid secret", NULL, NULL, &privkey); assert_true(rc == SSH_ERROR); assert_null(privkey); rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } #endif /* HAVE_LIBCRYPTO */ static void torture_pki_ecdsa_name(void **state, const char *expected_name) { int rc; ssh_key key = NULL; const char *etype_char = NULL; (void) state; /* unused */ rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY, NULL, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); etype_char =ssh_pki_key_ecdsa_name(key); assert_true(strcmp(etype_char, expected_name) == 0); SSH_KEY_FREE(key); } static void torture_pki_ecdsa_name256(void **state) { torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp256"); } static void torture_pki_ecdsa_name384(void **state) { torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp384"); } static void torture_pki_ecdsa_name521(void **state) { torture_pki_ecdsa_name(state, "ecdsa-sha2-nistp521"); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey, setup_openssh_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_from_openssh_privkey, setup_openssh_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_pubkey_file, setup_openssh_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_comment, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_comment, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_comment, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_whitespace, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_whitespace, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64_whitespace, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_openssh_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_openssh_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_privkey_base64, setup_openssh_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_from_privatekey, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_cert_file, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_cert_file, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_import_cert_file, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_then_demote, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_base64, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_base64, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_publickey_base64, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_generate_pubkey_from_privkey, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_generate_pubkey_from_privkey, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_generate_pubkey_from_privkey, setup_ecdsa_key_521, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_key, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_key, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_duplicate_key, setup_ecdsa_key_521, teardown), cmocka_unit_test(torture_pki_generate_key_ecdsa), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_cert_verify, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_cert_verify, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_cert_verify, setup_ecdsa_key_521, teardown), #ifdef HAVE_LIBCRYPTO cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_write_privkey, setup_ecdsa_key_521, teardown), #endif /* HAVE_LIBCRYPTO */ cmocka_unit_test(torture_pki_sign_data_ecdsa), cmocka_unit_test(torture_pki_fail_sign_with_incompatible_hash), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_name256, setup_ecdsa_key_256, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_name384, setup_ecdsa_key_384, teardown), cmocka_unit_test_setup_teardown(torture_pki_ecdsa_name521, setup_ecdsa_key_521, teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_pki_ed25519.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "torture_key.h" #include "torture_pki.h" #include "pki.c" #include #include #define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519" #define LIBSSH_ED25519_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_ed25519" const char template[] = "temp_dir_XXXXXX"; const unsigned char HASH[] = "12345678901234567890"; const uint8_t ref_signature[ED25519_SIG_LEN]= "\xbb\x8d\x55\x9f\x06\x14\x39\x24\xb4\xe1\x5a\x57\x3d\x9d\xbe\x22" "\x1b\xc1\x32\xd5\x55\x16\x00\x64\xce\xb4\xc3\xd2\xe3\x6f\x5e\x8d" "\x10\xa3\x18\x93\xdf\xa4\x96\x81\x11\x8e\x1e\x26\x14\x8a\x08\x1b" "\x01\x6a\x60\x59\x9c\x4a\x55\xa3\x16\x56\xf6\xc4\x50\x42\x7f\x03"; struct pki_st { char *cwd; char *temp_dir; }; static int setup_ed25519_key(void **state) { const char *keystring = NULL; struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0); torture_write_file(LIBSSH_ED25519_TESTKEY, keystring); keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 1); torture_write_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, keystring); torture_write_file(LIBSSH_ED25519_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_ED25519)); torture_write_file(LIBSSH_ED25519_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_ED25519_CERT01)); return 0; } static int teardown(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static void torture_pki_ed25519_import_pubkey_file(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY ".pub", &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ed25519_import_pubkey_from_openssh_privkey(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ed25519_import_privkey_base64(void **state) { int rc; char *key_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ED25519_TESTKEY); assert_non_null(key_str); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); SSH_KEY_FREE(key); } static void torture_pki_ed25519_import_privkey_base64_comment(void **state) { int rc, file_str_len; const char *comment_str = "#this is line-comment\n#this is another\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ED25519_TESTKEY); assert_non_null(key_str); file_str_len = strlen(comment_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", comment_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_ed25519_import_privkey_base64_whitespace(void **state) { int rc, file_str_len; const char *whitespace_str = " \n\t\t\t\t\t\n\n\n\n\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_ED25519_TESTKEY); assert_non_null(key_str); file_str_len = strlen(whitespace_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", whitespace_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_ed25519_import_export_privkey_base64(void **state) { char *b64_key = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; int rc; (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, false), passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_pki_export_privkey_base64(key, passphrase, NULL, NULL, &b64_key); assert_return_code(rc, errno); assert_non_null(b64_key); SSH_KEY_FREE(key); rc = ssh_pki_import_privkey_base64(b64_key, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_STRING_FREE_CHAR(b64_key); SSH_KEY_FREE(key); } static void torture_pki_ed25519_publickey_from_privatekey(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; const char *passphrase = NULL; const char *keystring = NULL; (void) state; /* unused */ keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0); rc = ssh_pki_import_privkey_base64(keystring, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); } static void torture_pki_ed25519_import_cert_file(void **state) { int rc; ssh_key cert = NULL; enum ssh_keytypes_e type; (void) state; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_ED25519_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); type = ssh_key_type(cert); assert_true(type == SSH_KEYTYPE_ED25519_CERT01); rc = ssh_key_is_public(cert); assert_true(rc == 1); SSH_KEY_FREE(cert); } static void torture_pki_ed25519_publickey_base64(void **state) { enum ssh_keytypes_e type; char *b64_key = NULL, *key_buf = NULL, *p = NULL; const char *q = NULL; ssh_key key = NULL; int rc; (void) state; /* unused */ key_buf = strdup(torture_get_testkey_pub(SSH_KEYTYPE_ED25519)); assert_non_null(key_buf); q = p = key_buf; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } type = ssh_key_type_from_name(q); assert_true(type == SSH_KEYTYPE_ED25519); q = ++p; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); assert_string_equal(q, b64_key); free(b64_key); free(key_buf); SSH_KEY_FREE(key); } static void torture_pki_ed25519_generate_pubkey_from_privkey(void **state) { char pubkey_generated[4096] = {0}; ssh_key privkey = NULL; ssh_key pubkey = NULL; int rc; int len; (void) state; /* unused */ /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_ED25519_TESTKEY ".pub"); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_file(pubkey, LIBSSH_ED25519_TESTKEY ".pub"); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_ED25519_TESTKEY ".pub", pubkey_generated, sizeof(pubkey_generated)); assert_true(rc == 0); len = torture_pubkey_len(torture_get_testkey_pub(SSH_KEYTYPE_ED25519)); assert_memory_equal(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), pubkey_generated, len); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); } static void torture_pki_ed25519_generate_key(void **state) { int rc; ssh_key key = NULL, pubkey = NULL; ssh_signature sign = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; const char *type_char = NULL; ssh_session session=ssh_new(); uint8_t *raw_sig_data = NULL; (void) state; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } assert_non_null(session); rc = ssh_pki_generate(SSH_KEYTYPE_ED25519, 256, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, HASH, 20, SSH_DIGEST_AUTO); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, HASH, 20); assert_true(rc == SSH_OK); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_ED25519); type_char = ssh_key_type_to_char(type); assert_true(strcmp(type_char, "ssh-ed25519") == 0); /* try an invalid signature */ #ifdef HAVE_OPENSSL_ED25519 raw_sig_data = ssh_string_data(sign->raw_sig); #else raw_sig_data = (uint8_t *)sign->ed25519_sig; #endif assert_non_null(raw_sig_data); (raw_sig_data)[3]^= 0xff; rc = ssh_pki_signature_verify(session, sign, pubkey, HASH, 20); assert_true(rc == SSH_ERROR); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); ssh_free(session); } static void torture_pki_ed25519_cert_verify(void **state) { int rc; ssh_key privkey = NULL, cert = NULL; ssh_signature sign = NULL; ssh_session session=ssh_new(); (void) state; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } assert_non_null(session); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_import_cert_file(LIBSSH_ED25519_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); sign = pki_do_sign(privkey, HASH, 20, SSH_DIGEST_AUTO); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, cert, HASH, 20); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(privkey); SSH_KEY_FREE(cert); ssh_free(session); } static void torture_pki_ed25519_write_privkey(void **state) { ssh_key origkey = NULL; ssh_key privkey = NULL; int rc; (void) state; /* unused */ rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, NULL, NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_ED25519_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, NULL, NULL, NULL, LIBSSH_ED25519_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); unlink(LIBSSH_ED25519_TESTKEY); SSH_KEY_FREE(privkey); /* do the same with passphrase */ rc = ssh_pki_export_privkey_file(origkey, torture_get_testkey_passphrase(), NULL, NULL, LIBSSH_ED25519_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, NULL, NULL, NULL, &privkey); /* opening without passphrase should fail */ assert_true(rc == SSH_ERROR); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); unlink(LIBSSH_ED25519_TESTKEY); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); /* Test with passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_ED25519_TESTKEY_PASSPHRASE); rc = ssh_pki_export_privkey_file(origkey, torture_get_testkey_passphrase(), NULL, NULL, LIBSSH_ED25519_TESTKEY_PASSPHRASE); assert_true(rc == 0); /* Test with invalid passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, "invalid secret", NULL, NULL, &privkey); assert_true(rc == SSH_ERROR); rc = ssh_pki_import_privkey_file(LIBSSH_ED25519_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } static void torture_pki_ed25519_sign(void **state) { ssh_key privkey = NULL; ssh_signature sig = NULL; ssh_string blob = NULL; const char *keystring = NULL; int rc; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } (void)state; keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0); rc = ssh_pki_import_privkey_base64(keystring, NULL, NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); sig = pki_do_sign(privkey, HASH, sizeof(HASH), SSH_DIGEST_AUTO); assert_non_null(sig); blob = pki_signature_to_blob(sig); assert_non_null(blob); assert_int_equal(ssh_string_len(blob), sizeof(ref_signature)); assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature)); ssh_signature_free(sig); SSH_KEY_FREE(privkey); SSH_STRING_FREE(blob); } static void torture_pki_ed25519_sign_openssh_privkey_passphrase(void **state) { ssh_key privkey = NULL; ssh_signature sig = NULL; ssh_string blob = NULL; const char *keystring = NULL; int rc; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } (void)state; keystring = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 1); rc = ssh_pki_import_privkey_base64(keystring, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); sig = pki_do_sign(privkey, HASH, sizeof(HASH), SSH_DIGEST_AUTO); assert_non_null(sig); blob = pki_signature_to_blob(sig); assert_non_null(blob); assert_int_equal(ssh_string_len(blob), sizeof(ref_signature)); assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature)); ssh_signature_free(sig); SSH_KEY_FREE(privkey); SSH_STRING_FREE(blob); } #ifdef HAVE_OPENSSL_ED25519 static void torture_pki_ed25519_sign_pkcs8_privkey(void **state) { ssh_key privkey = NULL; ssh_signature sig = NULL; ssh_string blob = NULL; const char *keystring = NULL; int rc; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } (void)state; keystring = torture_get_testkey(SSH_KEYTYPE_ED25519, 0); rc = ssh_pki_import_privkey_base64(keystring, NULL, NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); sig = pki_do_sign(privkey, HASH, sizeof(HASH), SSH_DIGEST_AUTO); assert_non_null(sig); blob = pki_signature_to_blob(sig); assert_non_null(blob); assert_int_equal(ssh_string_len(blob), sizeof(ref_signature)); assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature)); ssh_signature_free(sig); SSH_KEY_FREE(privkey); SSH_STRING_FREE(blob); } static void torture_pki_ed25519_sign_pkcs8_privkey_passphrase(void **state) { ssh_key privkey = NULL; ssh_signature sig = NULL; ssh_string blob = NULL; const char *keystring = NULL; int rc; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } (void)state; keystring = torture_get_testkey(SSH_KEYTYPE_ED25519, 1); rc = ssh_pki_import_privkey_base64(keystring, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); sig = pki_do_sign(privkey, HASH, sizeof(HASH), SSH_DIGEST_AUTO); assert_non_null(sig); blob = pki_signature_to_blob(sig); assert_non_null(blob); assert_int_equal(ssh_string_len(blob), sizeof(ref_signature)); assert_memory_equal(ssh_string_data(blob), ref_signature, sizeof(ref_signature)); ssh_signature_free(sig); SSH_KEY_FREE(privkey); SSH_STRING_FREE(blob); } #endif /* HAVE_OPENSSL_ED25519 */ static void torture_pki_ed25519_verify(void **state){ ssh_key pubkey = NULL; ssh_signature sig = NULL; ssh_session session = NULL; ssh_string blob = ssh_string_new(ED25519_SIG_LEN); char *pkey_ptr = strdup(strchr(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), ' ') + 1); char *ptr = NULL; uint8_t *raw_sig_data = NULL; int rc; (void) state; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } session = ssh_new(); assert_non_null(session); /* remove trailing comment */ ptr = strchr(pkey_ptr, ' '); if(ptr != NULL){ *ptr = '\0'; } rc = ssh_pki_import_pubkey_base64(pkey_ptr, SSH_KEYTYPE_ED25519, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO); assert_non_null(sig); rc = ssh_pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH)); assert_true(rc == SSH_OK); /* Alter signature and expect verification error */ #if defined(HAVE_OPENSSL_ED25519) raw_sig_data = ssh_string_data(sig->raw_sig); #else raw_sig_data = (uint8_t *)sig->ed25519_sig; #endif assert_non_null(raw_sig_data); (raw_sig_data)[3]^= 0xff; rc = ssh_pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH)); assert_true(rc == SSH_ERROR); ssh_signature_free(sig); SSH_KEY_FREE(pubkey); SSH_STRING_FREE(blob); free(pkey_ptr); ssh_free(session); } static void torture_pki_ed25519_verify_bad(void **state){ ssh_key pubkey = NULL; ssh_signature sig = NULL; ssh_session session = NULL; ssh_string blob = ssh_string_new(ED25519_SIG_LEN); char *pkey_ptr = strdup(strchr(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), ' ') + 1); char *ptr = NULL; int rc; int i; (void) state; /* Skip test if in FIPS mode */ if (ssh_fips_mode()) { skip(); } session = ssh_new(); assert_non_null(session); /* remove trailing comment */ ptr = strchr(pkey_ptr, ' '); if(ptr != NULL){ *ptr = '\0'; } rc = ssh_pki_import_pubkey_base64(pkey_ptr, SSH_KEYTYPE_ED25519, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); /* alter signature and expect false result */ for (i=0; i < ED25519_SIG_LEN; ++i){ ssh_string_fill(blob, ref_signature, ED25519_SIG_LEN); ((uint8_t *)ssh_string_data(blob))[i] ^= 0xff; sig = pki_signature_from_blob(pubkey, blob, SSH_KEYTYPE_ED25519, SSH_DIGEST_AUTO); assert_non_null(sig); rc = ssh_pki_signature_verify(session, sig, pubkey, HASH, sizeof(HASH)); assert_true(rc == SSH_ERROR); ssh_signature_free(sig); } SSH_KEY_FREE(pubkey); SSH_STRING_FREE(blob); free(pkey_ptr); ssh_free(session); } static void torture_pki_ed25519_import_privkey_base64_passphrase(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *testkey = NULL; (void) state; /* unused */ /* same for ED25519 */ testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 1); rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(testkey, "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); } static void torture_pki_ed25519_privkey_dup(void **state) { const char *passphrase = torture_get_testkey_passphrase(); ssh_key key = NULL; ssh_key dup = NULL; const char *testkey = NULL; int rc; (void) state; /* unused */ testkey = torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 1); rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); dup = ssh_key_dup(key); assert_non_null(dup); SSH_KEY_FREE(key); SSH_KEY_FREE(dup); } static void torture_pki_ed25519_pubkey_dup(void **state) { ssh_key pubkey = NULL; ssh_key dup = NULL; const char *p = strchr(torture_get_testkey_pub(SSH_KEYTYPE_ED25519), ' '); char *pub_str = NULL; char *q = NULL; int rc; (void) state; /* unused */ pub_str = strdup(p + 1); assert_non_null(pub_str); q = strchr(pub_str, ' '); assert_non_null(q); *q = '\0'; rc = ssh_pki_import_pubkey_base64(pub_str, SSH_KEYTYPE_ED25519, &pubkey); assert_true(rc == 0); assert_non_null(pubkey); rc = ssh_key_is_public(pubkey); assert_true(rc == 1); dup = ssh_key_dup(pubkey); assert_non_null(dup); rc = ssh_key_is_public(dup); assert_true(rc == 1); SAFE_FREE(pub_str); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(dup); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_file, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_pubkey_from_openssh_privkey, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_privkey_base64, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_privkey_base64_comment, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_privkey_base64_whitespace, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_export_privkey_base64, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_publickey_from_privatekey, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_import_cert_file, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_publickey_base64, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_generate_pubkey_from_privkey, setup_ed25519_key, teardown), cmocka_unit_test(torture_pki_ed25519_generate_key), cmocka_unit_test_setup_teardown(torture_pki_ed25519_cert_verify, setup_ed25519_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_ed25519_write_privkey, setup_ed25519_key, teardown), cmocka_unit_test(torture_pki_ed25519_import_privkey_base64_passphrase), cmocka_unit_test(torture_pki_ed25519_sign), cmocka_unit_test(torture_pki_ed25519_sign_openssh_privkey_passphrase), #ifdef HAVE_OPENSSL_ED25519 cmocka_unit_test(torture_pki_ed25519_sign_pkcs8_privkey), cmocka_unit_test(torture_pki_ed25519_sign_pkcs8_privkey_passphrase), #endif cmocka_unit_test(torture_pki_ed25519_verify), cmocka_unit_test(torture_pki_ed25519_verify_bad), cmocka_unit_test(torture_pki_ed25519_privkey_dup), cmocka_unit_test(torture_pki_ed25519_pubkey_dup), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_pki_rsa.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include "torture.h" #include "torture_pki.h" #include "torture_key.h" #include "pki.c" #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_rsa" const char template[] = "temp_dir_XXXXXX"; const unsigned char INPUT[] = "1234567890123456789012345678901234567890" "123456789012345678901234"; struct pki_st { char *cwd; char *temp_dir; }; static int setup_rsa_key(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, torture_get_testkey(SSH_KEYTYPE_RSA, 1)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA_CERT01)); return 0; } static int setup_openssh_rsa_key(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 1)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA_CERT01)); return 0; } static int teardown(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static void torture_pki_rsa_import_pubkey_file(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_rsa_import_pubkey_from_openssh_privkey(void **state) { ssh_key pubkey = NULL; int rc; (void)state; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); } static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state) { int rc; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ /* test if it returns -1 if key is NULL */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0), passphrase, NULL, NULL, NULL); assert_true(rc == -1); } static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ /* test if it returns -1 if key_str is NULL */ rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); } static void torture_pki_rsa_import_privkey_base64(void **state) { int rc; char *key_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_RSA_TESTKEY); assert_non_null(key_str); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); SSH_KEY_FREE(key); } static void torture_pki_rsa_import_privkey_base64_comment(void **state) { int rc, file_str_len; const char *comment_str = "#this is line-comment\n#this is another\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_RSA_TESTKEY); assert_non_null(key_str); file_str_len = strlen(comment_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", comment_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_rsa_import_privkey_base64_whitespace(void **state) { int rc, file_str_len; const char *whitespace_str = " \n\t\t\t\t\t\n\n\n\n\n"; char *key_str = NULL, *file_str = NULL; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); enum ssh_keytypes_e type; (void) state; /* unused */ key_str = torture_pki_read_file(LIBSSH_RSA_TESTKEY); assert_non_null(key_str); file_str_len = strlen(whitespace_str) + strlen(key_str) + 1; file_str = malloc(file_str_len); assert_non_null(file_str); rc = snprintf(file_str, file_str_len, "%s%s", whitespace_str, key_str); assert_int_equal(rc, file_str_len - 1); rc = ssh_pki_import_privkey_base64(file_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); free(file_str); SSH_KEY_FREE(key); } static void torture_pki_rsa_publickey_from_privatekey(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; const char *passphrase = NULL; (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0), passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); } static void torture_pki_rsa_copy_cert_to_privkey(void **state) { /* * Tests copying a cert loaded into a public key to a private key. * The function is encryption type agnostic, no need to run this against * all supported key types. */ int rc; const char *passphrase = torture_get_testkey_passphrase(); ssh_key pubkey = NULL; ssh_key privkey = NULL; ssh_key cert = NULL; (void) state; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_RSA_TESTKEY "-cert.pub", &cert); assert_true(rc == SSH_OK); assert_non_null(cert); rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 0), passphrase, NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); /* Basic sanity. */ rc = ssh_pki_copy_cert_to_privkey(NULL, privkey); assert_true(rc == SSH_ERROR); rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL); assert_true(rc == SSH_ERROR); /* A public key doesn't have a cert, copy should fail. */ assert_null(pubkey->cert); rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey); assert_true(rc == SSH_ERROR); /* Copying the cert to non-cert keys should work fine. */ rc = ssh_pki_copy_cert_to_privkey(cert, pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey->cert); rc = ssh_pki_copy_cert_to_privkey(cert, privkey); assert_true(rc == SSH_OK); assert_non_null(privkey->cert); /* The private key's cert is already set, another copy should fail. */ rc = ssh_pki_copy_cert_to_privkey(cert, privkey); assert_true(rc == SSH_ERROR); SSH_KEY_FREE(cert); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); } static void torture_pki_rsa_import_cert_file(void **state) { int rc; ssh_key cert = NULL; enum ssh_keytypes_e type; (void) state; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_RSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); type = ssh_key_type(cert); assert_true(type == SSH_KEYTYPE_RSA_CERT01); rc = ssh_key_is_public(cert); assert_true(rc == 1); SSH_KEY_FREE(cert); } static void torture_pki_rsa_publickey_base64(void **state) { enum ssh_keytypes_e type; char *b64_key = NULL, *key_buf = NULL, *p = NULL; const char *q = NULL; ssh_key key = NULL; int rc; (void) state; /* unused */ key_buf = strdup(torture_get_testkey_pub(SSH_KEYTYPE_RSA)); assert_non_null(key_buf); q = p = key_buf; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } type = ssh_key_type_from_name(q); assert_true(type == SSH_KEYTYPE_RSA); q = ++p; while (p != NULL && *p != '\0' && *p != ' ') p++; if (p != NULL) { *p = '\0'; } rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); assert_string_equal(q, b64_key); free(b64_key); free(key_buf); SSH_KEY_FREE(key); } static void torture_pki_rsa_generate_pubkey_from_privkey(void **state) { char pubkey_generated[4096] = {0}; ssh_key privkey = NULL; ssh_key pubkey = NULL; int rc; int len; (void) state; /* unused */ /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_RSA_TESTKEY ".pub"); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_file(pubkey, LIBSSH_RSA_TESTKEY ".pub"); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_generated, sizeof(pubkey_generated)); assert_true(rc == 0); len = torture_pubkey_len(torture_get_testkey_pub(SSH_KEYTYPE_RSA)); assert_memory_equal(torture_get_testkey_pub(SSH_KEYTYPE_RSA), pubkey_generated, len); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); } static void torture_pki_rsa_duplicate_key(void **state) { int rc; char *b64_key = NULL; char *b64_key_gen = NULL; ssh_key pubkey = NULL; ssh_key pubkey_dup = NULL; ssh_key privkey = NULL; ssh_key privkey_dup = NULL; (void) state; rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_true(rc == 0); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); privkey_dup = ssh_key_dup(privkey); assert_non_null(privkey_dup); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey_dup); assert_true(rc == SSH_OK); assert_non_null(pubkey_dup); rc = ssh_pki_export_pubkey_base64(pubkey_dup, &b64_key_gen); assert_true(rc == 0); assert_non_null(b64_key_gen); assert_string_equal(b64_key, b64_key_gen); rc = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); rc = ssh_key_cmp(pubkey, pubkey_dup, SSH_KEY_CMP_PUBLIC); assert_true(rc == 0); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(pubkey_dup); SSH_KEY_FREE(privkey); SSH_KEY_FREE(privkey_dup); SSH_STRING_FREE_CHAR(b64_key); SSH_STRING_FREE_CHAR(b64_key_gen); } static void torture_pki_rsa_generate_key(void **state) { int rc; ssh_key key = NULL, pubkey = NULL; ssh_signature sign = NULL; ssh_session session=ssh_new(); (void) state; if (!ssh_fips_mode()) { rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 1024, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); key = NULL; pubkey = NULL; } rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); key = NULL; pubkey = NULL; rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); key = NULL; pubkey = NULL; ssh_free(session); } static void torture_pki_rsa_sha2(void **state) { int rc; ssh_key key = NULL, cert = NULL, pubkey = NULL; ssh_signature sign; ssh_session session=ssh_new(); (void) state; assert_non_null(session); /* Setup */ rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_import_cert_file(LIBSSH_RSA_TESTKEY "-cert.pub", &cert); assert_true(rc == SSH_OK); assert_non_null(cert); /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); if (!ssh_fips_mode()) { /* Sign using old SHA1 digest */ sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA1); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); rc = ssh_pki_signature_verify(session, sign, cert, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); ssh_signature_free(sign); } /* Sign using new SHA256 digest */ sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); rc = ssh_pki_signature_verify(session, sign, cert, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); ssh_signature_free(sign); /* Sign using rsa-sha2-512 algorithm */ sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA512); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); rc = ssh_pki_signature_verify(session, sign, cert, INPUT, sizeof(INPUT)); assert_ssh_return_code(session, rc); ssh_signature_free(sign); /* Test that it fails when using DIGEST_AUTO */ sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_AUTO); assert_null(sign); /* Test that it fails when using SHA384 */ sign = pki_do_sign(key, INPUT, sizeof(INPUT), SSH_DIGEST_SHA384); assert_null(sign); /* Cleanup */ SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(cert); ssh_free(session); } static int test_sign_verify_data(ssh_key key, enum ssh_digest_e hash_type, const unsigned char *input, size_t input_len) { ssh_signature sig; ssh_key pubkey = NULL; int rc; /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, hash_type, input, input_len); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, input, input_len); assert_int_equal(rc, SSH_OK); ssh_signature_free(sig); SSH_KEY_FREE(pubkey); return rc; } static void torture_pki_sign_data_rsa(void **state) { int rc; ssh_key key = NULL; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); if (!ssh_fips_mode()) { /* Test using SHA1 */ rc = test_sign_verify_data(key, SSH_DIGEST_SHA1, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); } /* Test using SHA256 */ rc = test_sign_verify_data(key, SSH_DIGEST_SHA256, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Test using SHA512 */ rc = test_sign_verify_data(key, SSH_DIGEST_SHA512, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Cleanup */ SSH_KEY_FREE(key); } static void torture_pki_fail_sign_with_incompatible_hash(void **state) { int rc; ssh_key key = NULL; ssh_key pubkey = NULL; ssh_signature sig, bad_sig; (void) state; /* Setup */ rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key); assert_int_equal(rc, SSH_OK); assert_non_null(key); /* Get the public key to verify signature */ rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); /* Sign the buffer */ sig = pki_sign_data(key, SSH_DIGEST_SHA256, INPUT, sizeof(INPUT)); assert_non_null(sig); /* Verify signature */ rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_equal(rc, SSH_OK); /* Test if signature fails with SSH_DIGEST_AUTO */ bad_sig = pki_sign_data(key, SSH_DIGEST_AUTO, INPUT, sizeof(INPUT)); assert_null(bad_sig); /* Test if verification fails with SSH_DIGEST_AUTO */ sig->hash_type = SSH_DIGEST_AUTO; rc = pki_verify_data_signature(sig, pubkey, INPUT, sizeof(INPUT)); assert_int_not_equal(rc, SSH_OK); /* Cleanup */ ssh_signature_free(sig); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(key); } #ifdef HAVE_LIBCRYPTO static void torture_pki_rsa_write_privkey(void **state) { ssh_key origkey = NULL; ssh_key privkey = NULL; int rc; (void) state; /* unused */ rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_RSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, NULL, NULL, NULL, LIBSSH_RSA_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); /* Test with passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &origkey); assert_true(rc == 0); assert_non_null(origkey); unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE); rc = ssh_pki_export_privkey_file(origkey, torture_get_testkey_passphrase(), NULL, NULL, LIBSSH_RSA_TESTKEY_PASSPHRASE); assert_true(rc == 0); /* Test with invalid passphrase */ rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, "invalid secret", NULL, NULL, &privkey); assert_true(rc == SSH_ERROR); assert_null(privkey); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, torture_get_testkey_passphrase(), NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); SSH_KEY_FREE(origkey); SSH_KEY_FREE(privkey); } #endif /* HAVE_LIBCRYPTO */ static void torture_pki_rsa_import_privkey_base64_passphrase(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) state; /* unused */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 1), passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 1), "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); #ifndef HAVE_LIBCRYPTO /* test if it returns -1 if passphrase is NULL */ /* libcrypto asks for a passphrase, so skip this test */ rc = ssh_pki_import_privkey_base64(torture_get_testkey(SSH_KEYTYPE_RSA, 1), NULL, NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); #endif } static void torture_pki_rsa_import_openssh_privkey_base64_passphrase(void **state) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *keystring = NULL; (void) state; /* unused */ keystring = torture_get_openssh_testkey(SSH_KEYTYPE_RSA, 1); assert_non_null(keystring); rc = ssh_pki_import_privkey_base64(keystring, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); assert_non_null(key); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(keystring, "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is NULL */ /* libcrypto asks for a passphrase, so skip this test */ rc = ssh_pki_import_privkey_base64(keystring, NULL, NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_from_openssh_privkey, setup_openssh_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_key, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_str, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_comment, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_whitespace, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64, setup_openssh_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey, setup_rsa_key, teardown), cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase), cmocka_unit_test(torture_pki_rsa_import_openssh_privkey_base64_passphrase), cmocka_unit_test_setup_teardown(torture_pki_rsa_copy_cert_to_privkey, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_cert_file, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_base64, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_generate_pubkey_from_privkey, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_duplicate_key, setup_rsa_key, teardown), cmocka_unit_test(torture_pki_rsa_generate_key), #if defined(HAVE_LIBCRYPTO) cmocka_unit_test_setup_teardown(torture_pki_rsa_write_privkey, setup_rsa_key, teardown), #endif /* HAVE_LIBCRYPTO */ cmocka_unit_test(torture_pki_sign_data_rsa), cmocka_unit_test(torture_pki_fail_sign_with_incompatible_hash), cmocka_unit_test_setup_teardown(torture_pki_rsa_sha2, setup_rsa_key, teardown), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_push_pop_dir.c ================================================ #include "config.h" #include "torture.h" #define LIBSSH_STATIC const char template[] = "temp_dir_XXXXXX"; static int setup(void **state) { char *temp_dir = NULL; temp_dir = torture_make_temp_dir(template); assert_non_null(temp_dir); *state = (void *)temp_dir; return 0; } static int teardown(void **state) { char *temp_dir = *((char **)state); torture_rmdirs((const char *)temp_dir); free(temp_dir); return 0; } static void torture_back_and_forth(void **state) { char *temp_dir = *((char **)state); char *cwd = NULL; char *after_change = NULL; char *after_changing_back = NULL; int rc = 0; cwd = torture_get_current_working_dir(); assert_non_null(cwd); printf("Current dir: %s\n", cwd); rc = torture_change_dir(temp_dir); assert_int_equal(rc, 0); after_change = torture_get_current_working_dir(); assert_non_null(after_change); printf("Current dir after change: %s\n", after_change); rc = torture_change_dir(cwd); assert_int_equal(rc, 0); after_changing_back = torture_get_current_working_dir(); assert_non_null(after_changing_back); printf("Back to dir: %s\n", after_changing_back); SAFE_FREE(cwd); SAFE_FREE(after_change); SAFE_FREE(after_changing_back); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_back_and_forth, setup, teardown), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_rand.c ================================================ #include "config.h" #define LIBSSH_STATIC #include #include #include #include #include "torture.h" #ifdef HAVE_LIBGCRYPT #define NUM_LOOPS 1000 #else /* openssl is much faster */ #define NUM_LOOPS 20000 #endif #define NUM_THREADS 100 static int setup(void **state) { int rc; (void) state; ssh_threads_set_callbacks(ssh_threads_get_pthread()); rc = ssh_init(); if (rc != SSH_OK) { return -1; } return 0; } static int teardown(void **state) { (void) state; ssh_finalize(); return 0; } static void *torture_rand_thread(void *threadid) { char buffer[12]; int i; int ok; (void) threadid; buffer[0] = buffer[1] = buffer[10] = buffer[11] = 'X'; for(i = 0; i < NUM_LOOPS; ++i) { ok = ssh_get_random(&buffer[2], i % 8 + 1, 0); assert_true(ok); } pthread_exit(NULL); } static void torture_rand_threading(void **state) { pthread_t threads[NUM_THREADS]; int i; int err; (void) state; for(i = 0; i < NUM_THREADS; ++i) { err = pthread_create(&threads[i], NULL, torture_rand_thread, NULL); assert_int_equal(err, 0); } for(i = 0; i < NUM_THREADS; ++i) { err=pthread_join(threads[i], NULL); assert_int_equal(err, 0); } } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_rand_threading, setup, teardown), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_server_x11.c ================================================ #define LIBSSH_STATIC #include #include #include #include #include #include #include "torture.h" #define TEST_SERVER_PORT 2222 struct hostkey_state { const char *hostkey; char *hostkey_path; enum ssh_keytypes_e key_type; int fd; }; static int setup(void **state) { struct hostkey_state *h; mode_t mask; int rc; ssh_threads_set_callbacks(ssh_threads_get_pthread()); rc = ssh_init(); if (rc != SSH_OK) { return -1; } h = malloc(sizeof(struct hostkey_state)); assert_non_null(h); h->hostkey_path = strdup("/tmp/libssh_hostkey_XXXXXX"); mask = umask(S_IRWXO | S_IRWXG); h->fd = mkstemp(h->hostkey_path); umask(mask); assert_return_code(h->fd, errno); close(h->fd); h->key_type = SSH_KEYTYPE_ECDSA_P256; h->hostkey = torture_get_testkey(h->key_type, 0); torture_write_file(h->hostkey_path, h->hostkey); *state = h; return 0; } static int teardown(void **state) { struct hostkey_state *h = (struct hostkey_state *)*state; unlink(h->hostkey); free(h->hostkey_path); free(h); ssh_finalize(); return 0; } /* For x11_screen_number, need something that is not equal to htonl itself */ static const uint32_t x11_screen_number = 1; static void *client_thread(void *arg) { unsigned int test_port = TEST_SERVER_PORT; int rc; ssh_session session; ssh_channel channel; /* unused */ (void)arg; usleep(200); session = torture_ssh_session(NULL, "localhost", &test_port, "foo", "bar"); assert_non_null(session); channel = ssh_channel_new(session); assert_non_null(channel); rc = ssh_channel_open_session(channel); assert_int_equal(rc, SSH_OK); rc = ssh_channel_request_x11(channel, 0, NULL, NULL, (uint32_t)x11_screen_number); assert_int_equal(rc, SSH_OK); ssh_free(session); return NULL; } static int auth_password_accept(ssh_session session, const char *user, const char *password, void *userdata) { /* unused */ (void)session; (void)user; (void)password; (void)userdata; return SSH_AUTH_SUCCESS; } struct channel_data { int req_seen; uint32_t screen_number; }; static void ssh_channel_x11_req(ssh_session session, ssh_channel channel, int single_connection, const char *auth_protocol, const char *auth_cookie, uint32_t screen_number, void *userdata) { struct channel_data *channel_data = userdata; /* unused */ (void)session; (void)channel; (void)single_connection; (void)auth_protocol; (void)auth_cookie; /* We've seen an x11 request. Record the screen number */ channel_data->req_seen = 1; channel_data->screen_number = screen_number; } static ssh_channel channel_open(ssh_session session, void *userdata) { ssh_channel channel = NULL; ssh_channel_callbacks channel_cb = userdata; /* unused */ (void)userdata; channel = ssh_channel_new(session); if (channel == NULL) { goto out; } ssh_set_channel_callbacks(channel, channel_cb); out: return channel; } static void test_ssh_channel_request_x11(void **state) { struct hostkey_state *h = (struct hostkey_state *)*state; int rc, event_rc; pthread_t client_pthread; ssh_bind sshbind; ssh_session server; ssh_event event; struct channel_data channel_data; struct ssh_channel_callbacks_struct channel_cb = { .userdata = &channel_data, .channel_x11_req_function = ssh_channel_x11_req }; struct ssh_server_callbacks_struct server_cb = { .userdata = &channel_cb, .auth_password_function = auth_password_accept, .channel_open_request_session_function = channel_open }; memset(&channel_data, 0, sizeof(channel_data)); ssh_callbacks_init(&channel_cb); ssh_callbacks_init(&server_cb); /* Create server */ sshbind = torture_ssh_bind("localhost", TEST_SERVER_PORT, h->key_type, h->hostkey_path); assert_non_null(sshbind); /* Get client to connect */ rc = pthread_create(&client_pthread, NULL, client_thread, NULL); assert_return_code(rc, errno); server = ssh_new(); assert_non_null(server); rc = ssh_bind_accept(sshbind, server); assert_int_equal(rc, SSH_OK); /* Handle client connection */ ssh_set_server_callbacks(server, &server_cb); rc = ssh_handle_key_exchange(server); assert_int_equal(rc, SSH_OK); event = ssh_event_new(); assert_non_null(event); ssh_event_add_session(event, server); event_rc = SSH_OK; while (!channel_data.req_seen && event_rc == SSH_OK) { event_rc = ssh_event_dopoll(event, -1); } /* Cleanup */ ssh_event_free(event); ssh_free(server); ssh_bind_free(sshbind); rc = pthread_join(client_pthread, NULL); assert_int_equal(rc, 0); assert_true(channel_data.req_seen); assert_int_equal(channel_data.screen_number, x11_screen_number); } int torture_run_tests(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(test_ssh_channel_request_x11, setup, teardown) }; rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_session_keys.c ================================================ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/bignum.h" #include "libssh/crypto.h" #include "libssh/dh.h" uint8_t key[32] = "\xf7\xa0\xe6\xdf\x1f\x87\x7d\x22\x68\xd2\xc4\xb0\xc5\x93\xa4" "\x8e\x30\x17\xc6\xab\xca\xf3\x9a\xa4\x9f\x7b\xed\x51\xb1\xe8" "\x8a\x42"; uint8_t secret[32] = "\x33\x64\x8e\x7f\xea\xd9\xd7\xee\x89\x4f\xd8\xd0\xe5\x83\x00" "\x3d\x53\x17\xbc\xa8\x8b\x6b\x2a\x31\x50\xcc\x08\xe9\xea\x87" "\xb4\x23"; uint8_t eIV[32] = "\x9a\x2b\x40\x9d\x29\x8e\x22\x70\x86\xdf\x0e\x72\x9b\x91\x31" "\x90\x5d\x69\xc5\x87\x79\x83\x72\x63\x4e\x67\xf5\x9e\x00\x77" "\x8c\x7f"; uint8_t dIV[32] = "\x10\xdd\x7f\x31\x6d\xe3\x49\x28\xbf\x99\x80\x08\x16\xb3\x99" "\xff\x8c\x61\x9b\xb9\xc2\xdd\x40\xfb\x36\xf9\x97\xd8\x8c\x55" "\xbf\xa0"; uint8_t eK[24] = "\xe1\x99\x36\xb8\xe6\x1f\x3d\x54\xc3\xa2\xdd\x79\xf0\xfe\x78" "\x9e\x87\xd5\x05\x54\x26\x34\x21\xd0"; uint8_t dK[24] = "\xf8\xdd\xc3\xea\x5a\x59\x98\xb9\x86\xaa\x77\x29\x67\x51\x46" "\x21\x73\xc2\x6a\x6b\xed\xf2\x49\x98"; uint8_t eMAC[32] = "\x0f\xbd\x1f\xe9\x2a\xaa\x84\xdc\xb5\xfc\xfb\x68\x2c\xa5\xe0" "\xba\xf2\x6f\xe5\x80\xee\x8f\x5c\x5b\x30\x55\x25\xb3\x7b\x21" "\xdc\xe5"; uint8_t dMAC[32] = "\xa3\x52\x6e\x72\xa8\x8b\xde\xc5\x68\x66\x89\xae\x0a\xd2\x83" "\x23\x21\x4b\x3f\x04\x2e\x7f\x86\x04\x0f\xa8\x04\x3c\x62\xad" "\x74\x91"; struct ssh_cipher_struct fake_in_cipher = { .keysize = 192 }; struct ssh_cipher_struct fake_out_cipher = { .keysize = 192 }; struct ssh_crypto_struct test_crypto = { .digest_len = 32, .session_id = secret, .secret_hash = secret, .in_cipher = &fake_in_cipher, .out_cipher = &fake_out_cipher, .in_hmac = SSH_HMAC_SHA256, .out_hmac = SSH_HMAC_SHA256, .digest_type = SSH_KDF_SHA256, }; struct ssh_session_struct session = { .next_crypto = &test_crypto }; static void torture_session_keys(UNUSED_PARAM(void **state)) { ssh_string k_string; int rc; k_string = ssh_string_new(32); ssh_string_fill(k_string, key, 32); test_crypto.shared_secret = ssh_make_string_bn(k_string); rc = ssh_generate_session_keys(&session); assert_int_equal(rc, 0); assert_memory_equal(test_crypto.encryptIV, eIV, 32); assert_memory_equal(test_crypto.decryptIV, dIV, 32); assert_memory_equal(test_crypto.encryptkey, eK, 24); assert_memory_equal(test_crypto.decryptkey, dK, 24); assert_memory_equal(test_crypto.encryptMAC, eMAC, 32); assert_memory_equal(test_crypto.decryptMAC, dMAC, 32); SSH_STRING_FREE(k_string); } int torture_run_tests(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(torture_session_keys), }; ssh_init(); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_temp_dir.c ================================================ #include "config.h" #include "torture.h" #define LIBSSH_STATIC const char template[] = "temp_dir_XXXXXX"; static int setup(void **state) { char *temp_dir = NULL; temp_dir = torture_make_temp_dir(template); assert_non_null(temp_dir); *state = (void *)temp_dir; return 0; } static int teardown(void **state) { char *temp_dir = *((char **)state); torture_rmdirs((const char *)temp_dir); free(temp_dir); return 0; } static void torture_create_temp_dir(void **state) { char *temp_dir = *((char **)state); printf("Created temp dir: %s\n", temp_dir); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_create_temp_dir, setup, teardown), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_temp_file.c ================================================ #include "config.h" #include "torture.h" #define LIBSSH_STATIC const char template[] = "temp_file_XXXXXX"; static int setup(void **state) { char *file_name = NULL; file_name = torture_create_temp_file(template); assert_non_null(file_name); *state = (void *)file_name; return 0; } static int teardown(void **state) { int rc; char *file_name = *((char **)state); assert_non_null(file_name); rc = unlink(file_name); assert_int_equal(rc, 0); SAFE_FREE(file_name); return 0; } static void torture_temp_file(void **state) { char *file_name = *((char **)state); FILE *fp = NULL; assert_non_null(file_name); fp = fopen(file_name, "r"); assert_non_null(fp); fclose(fp); printf("Created temp file: %s\n", file_name); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_temp_file, setup, teardown), }; torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_threads_buffer.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #define DEBUG_BUFFER #include "buffer.c" #include #define NUM_THREADS 20 #define BUFFER_LIMIT (8 * 1024 * 1024) static int run_on_threads(void *(*func)(void *)) { pthread_t threads[NUM_THREADS]; int rc; int i; for (i = 0; i < NUM_THREADS; ++i) { rc = pthread_create(&threads[i], NULL, func, NULL); assert_int_equal(rc, 0); } for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result = NULL; rc = pthread_join(threads[i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } return rc; } /* * Test if the continuously growing buffer size never exceeds 2 time its * real capacity */ static void *thread_growing_buffer(void *threadid) { ssh_buffer buffer = NULL; int i; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); for (i = 0; i < BUFFER_LIMIT; ++i) { ssh_buffer_add_data(buffer,"A",1); if (buffer->used >= 128) { if (ssh_buffer_get_len(buffer) * 2 < buffer->allocated) { assert_true(ssh_buffer_get_len(buffer) * 2 >= buffer->allocated); } } } /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_growing_buffer(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_growing_buffer); assert_int_equal(rc, 0); } /* * Test if the continuously growing buffer size never exceeds 2 time its * real capacity, when we remove 1 byte after each call (sliding window) */ static void *thread_growing_buffer_shifting(void *threadid) { ssh_buffer buffer; int i; unsigned char c; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); for (i = 0; i < 1024; ++i) { ssh_buffer_add_data(buffer,"S",1); } for (i = 0; i < BUFFER_LIMIT; ++i) { ssh_buffer_get_u8(buffer,&c); ssh_buffer_add_data(buffer,"A",1); if (buffer->used >= 128) { if (ssh_buffer_get_len(buffer) * 4 < buffer->allocated) { assert_true(ssh_buffer_get_len(buffer) * 4 >= buffer->allocated); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } } } /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_growing_buffer_shifting(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_growing_buffer_shifting); assert_int_equal(rc, 0); } /* * Test the behavior of ssh_buffer_prepend_data */ static void *thread_buffer_prepend(void *threadid) { ssh_buffer buffer = NULL; uint32_t v; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); ssh_buffer_add_data(buffer, "abcdef", 6); ssh_buffer_prepend_data(buffer, "xyz", 3); assert_int_equal(ssh_buffer_get_len(buffer), 9); assert_memory_equal(ssh_buffer_get(buffer), "xyzabcdef", 9); /* Now remove 4 bytes and see if we can replace them */ ssh_buffer_get_u32(buffer, &v); assert_int_equal(ssh_buffer_get_len(buffer), 5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer, "aris", 4); assert_int_equal(ssh_buffer_get_len(buffer), 9); assert_memory_equal(ssh_buffer_get(buffer), "arisbcdef", 9); /* same thing but we add 5 bytes now */ ssh_buffer_get_u32(buffer, &v); assert_int_equal(ssh_buffer_get_len(buffer), 5); assert_memory_equal(ssh_buffer_get(buffer), "bcdef", 5); ssh_buffer_prepend_data(buffer, "12345", 5); assert_int_equal(ssh_buffer_get_len(buffer), 10); assert_memory_equal(ssh_buffer_get(buffer), "12345bcdef", 10); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_buffer_prepend(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_buffer_prepend); assert_int_equal(rc, 0); } /* * Test the behavior of ssh_buffer_get_ssh_string with invalid data */ static void *thread_ssh_buffer_get_ssh_string(void *threadid) { ssh_buffer buffer = NULL; size_t i, j, k, l; int rc; /* some values that can go wrong */ uint32_t values[] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xffffff00, 0x80000000, 0x80000004, 0x7fffffff}; char data[128] = {0}; /* Unused */ (void)threadid; memset(data, 'X', sizeof(data)); for (i = 0; i < ARRAY_SIZE(values); ++i) { for (j = 0; j < (int)sizeof(data); ++j) { for (k = 1; k < 5; ++k) { buffer = ssh_buffer_new(); assert_non_null(buffer); for (l = 0; l < k; ++l) { rc = ssh_buffer_add_u32(buffer, htonl(values[i])); assert_int_equal(rc, 0); } rc = ssh_buffer_add_data(buffer,data,j); assert_int_equal(rc, 0); for (l = 0; l < k; ++l) { ssh_string str = ssh_buffer_get_ssh_string(buffer); assert_null(str); SSH_STRING_FREE(str); } SSH_BUFFER_FREE(buffer); } } } pthread_exit(NULL); } static void torture_ssh_buffer_get_ssh_string(void **state){ int rc; /* Unused */ (void) state; rc = run_on_threads(thread_ssh_buffer_get_ssh_string); assert_int_equal(rc, 0); } static void *thread_ssh_buffer_add_format(void *threadid) { ssh_buffer buffer = NULL; uint8_t b; uint16_t w; uint32_t d; uint64_t q; ssh_string s = NULL; int rc; size_t len; uint8_t verif[] = "\x42\x13\x37\x0b\xad\xc0\xde\x13\x24\x35\x46" "\xac\xbd\xce\xdf" "\x00\x00\x00\x06" "libssh" "\x00\x00\x00\x05" "rocks" "So much" "Fun!"; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); b = 0x42; w = 0x1337; d = 0xbadc0de; q = 0x13243546acbdcedf; s = ssh_string_from_char("libssh"); rc = ssh_buffer_pack(buffer, "bwdqSsPt", b, w, d, q, s, "rocks", 7, "So much", "Fun!"); assert_int_equal(rc, SSH_OK); len = ssh_buffer_get_len(buffer); assert_int_equal(len, sizeof(verif) - 1); assert_memory_equal(ssh_buffer_get(buffer), verif, sizeof(verif) -1); SSH_STRING_FREE(s); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_ssh_buffer_add_format(void **state){ int rc; /* Unused */ (void) state; rc = run_on_threads(thread_ssh_buffer_add_format); assert_int_equal(rc, 0); } static void *thread_ssh_buffer_get_format(void *threadid) { ssh_buffer buffer; uint8_t b = 0; uint16_t w = 0; uint32_t d = 0; uint64_t q = 0; ssh_string s = NULL; char *s1 = NULL, *s2 = NULL; int rc; size_t len; uint8_t verif[] = "\x42\x13\x37\x0b\xad\xc0\xde\x13\x24\x35\x46" "\xac\xbd\xce\xdf" "\x00\x00\x00\x06" "libssh" "\x00\x00\x00\x05" "rocks" "So much"; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); rc = ssh_buffer_add_data(buffer, verif, sizeof(verif) - 1); assert_int_equal(rc, SSH_OK); rc = ssh_buffer_unpack(buffer, "bwdqSsP", &b, &w, &d, &q, &s, &s1, (size_t)7, &s2); assert_int_equal(rc, SSH_OK); assert_int_equal(b, 0x42); assert_int_equal(w, 0x1337); assert_true(d == 0xbadc0de); assert_true(q == 0x13243546acbdcedf); assert_non_null(s); assert_int_equal(ssh_string_len(s), 6); assert_memory_equal(ssh_string_data(s), "libssh", 6); assert_non_null(s1); assert_string_equal(s1, "rocks"); assert_non_null(s2); assert_memory_equal(s2, "So much", 7); len = ssh_buffer_get_len(buffer); assert_int_equal(len, 0); SAFE_FREE(s); SAFE_FREE(s1); SAFE_FREE(s2); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_ssh_buffer_get_format(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_ssh_buffer_get_format); assert_int_equal(rc, 0); } static void *thread_ssh_buffer_get_format_error(void *threadid) { ssh_buffer buffer = NULL; uint8_t b = 0; uint16_t w = 0; uint32_t d = 0; uint64_t q = 0; ssh_string s = NULL; char *s1 = NULL, *s2 = NULL; int rc; uint8_t verif[] = "\x42\x13\x37\x0b\xad\xc0\xde\x13\x24\x35\x46" "\xac\xbd\xce\xdf" "\x00\x00\x00\x06" "libssh" "\x00\x00\x00\x05" "rocks" "So much"; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); rc = ssh_buffer_add_data(buffer, verif, sizeof(verif) - 1); assert_int_equal(rc, SSH_OK); rc = ssh_buffer_unpack(buffer, "bwdqSsPb", &b, &w, &d, &q, &s, &s1, (size_t)7, &s2, &b); assert_int_equal(rc, SSH_ERROR); assert_null(s); assert_null(s1); assert_null(s2); /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_ssh_buffer_get_format_error(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_ssh_buffer_get_format_error); assert_int_equal(rc, 0); } static void *thread_buffer_pack_badformat(void *threadid) { ssh_buffer buffer = NULL; uint8_t b = 42; int rc; /* Unused */ (void) threadid; /* Setup */ buffer = ssh_buffer_new(); if (buffer == NULL) { pthread_exit((void *)-1); } ssh_buffer_set_secure(buffer); /* first with missing format */ rc = ssh_buffer_pack(buffer, "b", b, b); assert_int_equal(rc, SSH_ERROR); ssh_buffer_reinit(buffer); /* with additional format */ rc = ssh_buffer_pack(buffer, "bb", b); /* check that we detect the missing parameter */ assert_int_equal(rc, SSH_ERROR); /* unpack with missing format */ ssh_buffer_reinit(buffer); rc = ssh_buffer_pack(buffer, "bb", 42, 43); assert_int_equal(rc, SSH_OK); rc = ssh_buffer_unpack(buffer, "b", &b, &b); assert_int_equal(rc, SSH_ERROR); /* not doing the test with additional format as * it could crash the process */ /* Teardown */ SSH_BUFFER_FREE(buffer); pthread_exit(NULL); } static void torture_buffer_pack_badformat(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_buffer_pack_badformat); assert_int_equal(rc, 0); } #define NUM_TESTS 8 static void torture_mixed(void **state) { pthread_t threads[NUM_TESTS][NUM_THREADS]; int i; int f; int rc; /* Array of functions to run on threads */ static void *(*funcs[NUM_TESTS])(void *) = { thread_growing_buffer, thread_growing_buffer_shifting, thread_buffer_prepend, thread_ssh_buffer_get_ssh_string, thread_ssh_buffer_add_format, thread_ssh_buffer_get_format, thread_ssh_buffer_get_format_error, thread_buffer_pack_badformat }; (void) state; /* Call tests in a round-robin fashion */ for (i = 0; i < NUM_THREADS; ++i) { for (f = 0; f < NUM_TESTS; f++) { rc = pthread_create(&threads[f][i], NULL, funcs[f], NULL); assert_int_equal(rc, 0); } } for (f = 0; f < NUM_TESTS; f++) { for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result = NULL; rc = pthread_join(threads[f][i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } } } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_growing_buffer), cmocka_unit_test(torture_growing_buffer_shifting), cmocka_unit_test(torture_buffer_prepend), cmocka_unit_test(torture_ssh_buffer_get_ssh_string), cmocka_unit_test(torture_ssh_buffer_add_format), cmocka_unit_test(torture_ssh_buffer_get_format), cmocka_unit_test(torture_ssh_buffer_get_format_error), cmocka_unit_test(torture_buffer_pack_badformat), cmocka_unit_test(torture_mixed), }; /* * If the library is statically linked, ssh_init() is not called * automatically */ ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_threads_crypto.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/crypto.h" #include #define NUM_THREADS 100 static int8_t key[32] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d" "\x1e\x1f"; static uint8_t IV[16] = "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" "\x1f"; static uint8_t cleartext[144] = "\xb4\xfc\x5d\xc2\x49\x8d\x2c\x29\x4a\xc9\x9a\xb0\x1b\xf8\x29" "\xee\x85\x6d\x8c\x04\x34\x7c\x65\xf4\x89\x97\xc5\x71\x70\x41" "\x91\x40\x19\x60\xe1\xf1\x8f\x4d\x8c\x17\x51\xd6\xbc\x69\x6e" "\xf2\x21\x87\x18\x6c\xef\xc4\xf4\xd9\xe6\x1b\x94\xf7\xd8\xb2" "\xe9\x24\xb9\xe7\xe6\x19\xf5\xec\x55\x80\x9a\xc8\x7d\x70\xa3" "\x50\xf8\x03\x10\x35\x49\x9b\x53\x58\xd7\x4c\xfc\x5f\x02\xd6" "\x28\xea\xcc\x43\xee\x5e\x2b\x8a\x7a\x66\xf7\x00\xee\x09\x18" "\x30\x1b\x47\xa2\x16\x69\xc4\x6e\x44\x3f\xbd\xec\x52\xce\xe5" "\x41\xf2\xe0\x04\x4f\x5a\x55\x58\x37\xba\x45\x8d\x15\x53\xf6" "\x31\x91\x13\x8c\x51\xed\x08\x07\xdb"; static uint8_t aes256_cbc_encrypted[144] = "\x7f\x1b\x92\xac\xc5\x16\x05\x55\x74\xac\xb4\xe0\x91\x8c\xf8" "\x0d\xa9\x72\xa5\x09\xb8\x44\xee\x55\x02\x13\xb7\x52\x0a\xf0" "\xac\xd0\x21\x0e\x58\x7b\x34\xfe\xdb\x36\x01\x60\x7d\x18\x3a" "\xa9\x15\x18\x5b\x13\xca\xdd\x77\x7d\xdf\x64\xc6\xd5\x75\x4b" "\x02\x02\x37\xb1\xf4\x33\xff\x93\xe6\x32\x08\xda\xcb\x5d\xa2" "\x8f\x17\x1f\x99\x92\x60\x22\x9d\x6b\xe6\xb2\x5e\xb0\x5d\x26" "\x3f\xde\xb8\xc1\xb0\x70\x80\x1c\x00\xd0\x93\x2b\xeb\x0f\xd7" "\x70\x7a\x9a\x7a\xa6\x21\x23\x2c\x02\xb7\xcd\x88\x10\x9c\x2d" "\x0c\xd3\xfa\xc1\x33\x5b\xe1\xa1\xd4\x3d\x8f\xb8\x50\xc5\xb5" "\x72\xdd\x6d\x32\x1f\x58\x00\x48\xbe"; static int run_on_threads(void *(*func)(void *)) { pthread_t threads[NUM_THREADS]; int rc; int i; for (i = 0; i < NUM_THREADS; ++i) { rc = pthread_create(&threads[i], NULL, func, NULL); assert_int_equal(rc, 0); } for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result; rc = pthread_join(threads[i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } return rc; } static int get_cipher(struct ssh_cipher_struct *cipher, const char *ciphername) { struct ssh_cipher_struct *ciphers = ssh_get_ciphertab(); int i, cmp; for (i = 0; ciphers[i].name != NULL; i++) { cmp = strcmp(ciphername, ciphers[i].name); if (cmp == 0) { memcpy(cipher, &ciphers[i], sizeof(*cipher)); return SSH_OK; } } return SSH_ERROR; } static void *thread_crypto_aes256_cbc(void *threadid) { uint8_t output[sizeof(cleartext)] = {0}; uint8_t iv[16] = {0}; struct ssh_cipher_struct cipher = { .name = NULL, }; int rc; /* Unused */ (void) threadid; rc = get_cipher(&cipher, "aes256-cbc"); assert_int_equal(rc, SSH_OK); assert_non_null(cipher.set_encrypt_key); assert_non_null(cipher.encrypt); /* This is for dump static analizyer without modelling support */ if (cipher.set_encrypt_key == NULL || cipher.encrypt == NULL) { return NULL; } memcpy(iv, IV, sizeof(IV)); cipher.set_encrypt_key(&cipher, key, iv ); cipher.encrypt(&cipher, cleartext, output, sizeof(cleartext) ); assert_memory_equal(output, aes256_cbc_encrypted, sizeof(aes256_cbc_encrypted)); ssh_cipher_clear(&cipher); rc = get_cipher(&cipher, "aes256-cbc"); assert_int_equal(rc, SSH_OK); assert_non_null(cipher.set_encrypt_key); assert_non_null(cipher.encrypt); /* This is for dump static analizyer without modelling support */ if (cipher.set_encrypt_key == NULL || cipher.encrypt == NULL) { return NULL; } memcpy(iv, IV, sizeof(IV)); cipher.set_decrypt_key(&cipher, key, iv ); memset(output, '\0', sizeof(output)); cipher.decrypt(&cipher, aes256_cbc_encrypted, output, sizeof(aes256_cbc_encrypted) ); assert_memory_equal(output, cleartext, sizeof(cleartext)); ssh_cipher_clear(&cipher); pthread_exit(NULL); } static void torture_crypto_aes256_cbc(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_crypto_aes256_cbc); assert_int_equal(rc, 0); } int torture_run_tests(void) { int rc; const struct CMUnitTest tests[] = { cmocka_unit_test(torture_crypto_aes256_cbc), }; /* * If the library is statically linked, ssh_init() is not called * automatically */ ssh_init(); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_threads_init.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/libssh.h" #include #define NUM_THREADS 20 static int run_on_threads(void *(*func)(void *)) { pthread_t threads[NUM_THREADS]; int rc; int i; for (i = 0; i < NUM_THREADS; ++i) { rc = pthread_create(&threads[i], NULL, func, NULL); assert_int_equal(rc, 0); } for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result; rc = pthread_join(threads[i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } return rc; } static void *thread_ssh_init(UNUSED_PARAM(void *threadid)) { int rc; (void) threadid; rc = ssh_init(); assert_int_equal(rc, SSH_OK); rc = ssh_finalize(); assert_int_equal(rc, SSH_OK); pthread_exit(NULL); } static void torture_ssh_init(UNUSED_PARAM(void **state)) { int rc; rc = run_on_threads(thread_ssh_init); assert_int_equal(rc, 0); } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_ssh_init), }; /* * If the library is statically linked, ssh_init() is not called * automatically */ ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_threads_pki_rsa.c ================================================ /* * This file is part of the SSH Library * * Copyright (c) 2018 by Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include #include #include "torture.h" #include "torture_pki.h" #include "torture_key.h" #include "pki.c" #include #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" #define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_rsa" #define NUM_THREADS 10 const char template[] = "temp_dir_XXXXXX"; const unsigned char RSA_HASH[] = "12345678901234567890"; struct pki_st { char *cwd; char *temp_dir; }; static int run_on_threads(void *(*func)(void *)) { pthread_t threads[NUM_THREADS]; int rc; int i; for (i = 0; i < NUM_THREADS; ++i) { rc = pthread_create(&threads[i], NULL, func, NULL); assert_int_equal(rc, 0); } for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result; rc = pthread_join(threads[i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } return rc; } static int setup_rsa_key(void **state) { struct pki_st *test_state = NULL; char *cwd = NULL; char *tmp_dir = NULL; int rc = 0; test_state = (struct pki_st *)malloc(sizeof(struct pki_st)); assert_non_null(test_state); cwd = torture_get_current_working_dir(); assert_non_null(cwd); tmp_dir = torture_make_temp_dir(template); assert_non_null(tmp_dir); test_state->cwd = cwd; test_state->temp_dir = tmp_dir; *state = test_state; rc = torture_change_dir(tmp_dir); assert_int_equal(rc, 0); printf("Changed directory to: %s\n", tmp_dir); torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_RSA, 0)); torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, torture_get_testkey(SSH_KEYTYPE_RSA, 1)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA)); torture_write_file(LIBSSH_RSA_TESTKEY "-cert.pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA_CERT01)); return 0; } static int teardown(void **state) { struct pki_st *test_state = NULL; int rc = 0; test_state = *((struct pki_st **)state); assert_non_null(test_state); assert_non_null(test_state->cwd); assert_non_null(test_state->temp_dir); rc = torture_change_dir(test_state->cwd); assert_int_equal(rc, 0); rc = torture_rmdirs(test_state->temp_dir); assert_int_equal(rc, 0); SAFE_FREE(test_state->temp_dir); SAFE_FREE(test_state->cwd); SAFE_FREE(test_state); return 0; } static int disable_secmem(void **state) { (void) state; /*unused*/ #if defined(HAVE_LIBGCRYPT) /* gcrypt currently is configured to use only 4kB of locked secmem * (see ssh_crypto_init() in src/libcrypt.c) * * This is insufficient to run the RSA key generation in many threads. * To avoid the expected warning, disable the secure memory. * */ gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); gcry_control(GCRYCTL_DISABLE_SECMEM); #endif return 0; } static int enable_secmem(void **state) { (void) state; /*unused*/ #if defined(HAVE_LIBGCRYPT) /* Re-enable secmem */ gcry_control(GCRYCTL_INIT_SECMEM, 4096); gcry_control(GCRYCTL_RESUME_SECMEM_WARN); #endif return 0; } static void *thread_pki_rsa_import_pubkey_file(void *threadid) { ssh_key pubkey = NULL; int rc; (void) threadid; /* The key doesn't have the hostname as comment after the key */ rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_return_code(rc, errno); assert_non_null(pubkey); SSH_KEY_FREE(pubkey); pthread_exit(NULL); } static void torture_pki_rsa_import_pubkey_file(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_pubkey_file); assert_int_equal(rc, 0); } static void *thread_pki_rsa_import_privkey_base64_NULL_key(void *threadid) { int rc; const char *passphrase = torture_get_testkey_passphrase(); const char *testkey; (void) threadid; /* unused */ testkey = torture_get_testkey(SSH_KEYTYPE_RSA, 0); assert_non_null(testkey); /* test if it returns -1 if key is NULL */ rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, NULL); assert_true(rc == -1); pthread_exit(NULL); } static void torture_pki_rsa_import_privkey_base64_NULL_key(void **state){ int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_privkey_base64_NULL_key); assert_int_equal(rc, 0); } static void *thread_pki_rsa_import_privkey_base64_NULL_str(void *threadid) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); (void) threadid; /* unused */ /* test if it returns -1 if key_str is NULL */ rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); pthread_exit(NULL); } static void torture_pki_rsa_import_privkey_base64_NULL_str(void **state){ int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_privkey_base64_NULL_str); assert_int_equal(rc, 0); } static void *thread_pki_rsa_import_privkey_base64(void *threadid) { const char *passphrase = torture_get_testkey_passphrase(); char *key_str = NULL; ssh_key key = NULL; enum ssh_keytypes_e type; int ok; int rc; (void) threadid; /* unused */ key_str = torture_pki_read_file(LIBSSH_RSA_TESTKEY); assert_non_null(key_str); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); ok = ssh_key_is_private(key); assert_true(ok); ok = ssh_key_is_public(key); assert_true(ok); free(key_str); SSH_KEY_FREE(key); pthread_exit(NULL); } static void torture_pki_rsa_import_privkey_base64(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_privkey_base64); assert_int_equal(rc, 0); } static void *thread_pki_rsa_publickey_from_privatekey(void *threadid) { const char *passphrase = NULL; const char *testkey; ssh_key pubkey = NULL; ssh_key key = NULL; int rc; int ok; (void) threadid; /* unused */ testkey = torture_get_testkey(SSH_KEYTYPE_RSA, 0); rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, &key); assert_true(rc == 0); assert_non_null(key); ok = ssh_key_is_private(key); assert_true(ok); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); pthread_exit(NULL); } static void torture_pki_rsa_publickey_from_privatekey(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_publickey_from_privatekey); assert_int_equal(rc, 0); } static void *thread_pki_rsa_copy_cert_to_privkey(void *threadid) { /* * Tests copying a cert loaded into a public key to a private key. * The function is encryption type agnostic, no need to run this against * all supported key types. */ const char *passphrase = torture_get_testkey_passphrase(); const char *testkey = NULL; ssh_key pubkey = NULL; ssh_key privkey = NULL; ssh_key cert = NULL; int rc; (void) threadid; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_RSA_TESTKEY "-cert.pub", &cert); assert_true(rc == SSH_OK); assert_non_null(cert); rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); testkey = torture_get_testkey(SSH_KEYTYPE_RSA, 0); assert_non_null(testkey); rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, &privkey); assert_true(rc == SSH_OK); assert_non_null(privkey); /* Basic sanity. */ rc = ssh_pki_copy_cert_to_privkey(NULL, privkey); assert_true(rc == SSH_ERROR); rc = ssh_pki_copy_cert_to_privkey(pubkey, NULL); assert_true(rc == SSH_ERROR); /* A public key doesn't have a cert, copy should fail. */ rc = ssh_pki_copy_cert_to_privkey(pubkey, privkey); assert_true(rc == SSH_ERROR); /* Copying the cert to non-cert keys should work fine. */ rc = ssh_pki_copy_cert_to_privkey(cert, pubkey); assert_true(rc == SSH_OK); rc = ssh_pki_copy_cert_to_privkey(cert, privkey); assert_true(rc == SSH_OK); /* The private key's cert is already set, another copy should fail. */ rc = ssh_pki_copy_cert_to_privkey(cert, privkey); assert_true(rc == SSH_ERROR); SSH_KEY_FREE(cert); SSH_KEY_FREE(privkey); SSH_KEY_FREE(pubkey); pthread_exit(NULL); } static void torture_pki_rsa_copy_cert_to_privkey(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_copy_cert_to_privkey); assert_int_equal(rc, 0); } static void *thread_pki_rsa_import_cert_file(void *threadid) { int rc; ssh_key cert = NULL; enum ssh_keytypes_e type; (void) threadid; /* unused */ rc = ssh_pki_import_cert_file(LIBSSH_RSA_TESTKEY "-cert.pub", &cert); assert_true(rc == 0); assert_non_null(cert); type = ssh_key_type(cert); assert_true(type == SSH_KEYTYPE_RSA_CERT01); rc = ssh_key_is_public(cert); assert_true(rc == 1); SSH_KEY_FREE(cert); pthread_exit(NULL); } static void torture_pki_rsa_import_cert_file(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_cert_file); assert_int_equal(rc, 0); } static void *thread_pki_rsa_publickey_base64(void *threadid) { enum ssh_keytypes_e type; char *b64_key = NULL, *key_buf = NULL, *p = NULL; const char *q = NULL; ssh_key key; int rc; (void) threadid; /* unused */ key_buf = strdup(torture_get_testkey_pub(SSH_KEYTYPE_RSA)); assert_non_null(key_buf); q = p = key_buf; while (*p != ' ') p++; *p = '\0'; type = ssh_key_type_from_name(q); assert_true(type == SSH_KEYTYPE_RSA); q = ++p; while (*p != ' ') p++; *p = '\0'; rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); assert_non_null(key); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_non_null(b64_key); assert_string_equal(q, b64_key); free(b64_key); free(key_buf); SSH_KEY_FREE(key); pthread_exit(NULL); } static void torture_pki_rsa_publickey_base64(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_publickey_base64); assert_int_equal(rc, 0); } static void *thread_pki_rsa_duplicate_key(void *threadid) { char *b64_key = NULL; char *b64_key_gen = NULL; ssh_key pubkey = NULL; ssh_key privkey = NULL; ssh_key privkey_dup = NULL; int cmp; int rc; (void) threadid; rc = ssh_pki_import_pubkey_file(LIBSSH_RSA_TESTKEY ".pub", &pubkey); assert_true(rc == 0); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key); assert_true(rc == 0); SSH_KEY_FREE(pubkey); assert_non_null(b64_key); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); assert_non_null(privkey); privkey_dup = ssh_key_dup(privkey); assert_non_null(privkey_dup); rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); assert_true(rc == SSH_OK); assert_non_null(pubkey); rc = ssh_pki_export_pubkey_base64(pubkey, &b64_key_gen); assert_true(rc == 0); assert_non_null(b64_key_gen); assert_string_equal(b64_key, b64_key_gen); cmp = ssh_key_cmp(privkey, privkey_dup, SSH_KEY_CMP_PRIVATE); assert_true(cmp == 0); SSH_KEY_FREE(pubkey); SSH_KEY_FREE(privkey); SSH_KEY_FREE(privkey_dup); SSH_STRING_FREE_CHAR(b64_key); SSH_STRING_FREE_CHAR(b64_key_gen); pthread_exit(NULL); } static void torture_pki_rsa_duplicate_key(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_duplicate_key); assert_int_equal(rc, 0); } static void *thread_pki_rsa_generate_key(void *threadid) { int rc; ssh_key key = NULL, pubkey = NULL; ssh_signature sign = NULL; ssh_session session = NULL; (void) threadid; session = ssh_new(); assert_non_null(session); if (!ssh_fips_mode()) { rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 1024, &key); assert_ssh_return_code(session, rc); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, RSA_HASH, 20, SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, RSA_HASH, 20); assert_ssh_return_code(session, rc); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); } rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 2048, &key); assert_ssh_return_code(session, rc); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, RSA_HASH, 20, SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, RSA_HASH, 20); assert_ssh_return_code(session, rc); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key); assert_true(rc == SSH_OK); assert_non_null(key); rc = ssh_pki_export_privkey_to_pubkey(key, &pubkey); assert_int_equal(rc, SSH_OK); assert_non_null(pubkey); sign = pki_do_sign(key, RSA_HASH, 20, SSH_DIGEST_SHA256); assert_non_null(sign); rc = ssh_pki_signature_verify(session, sign, pubkey, RSA_HASH, 20); assert_true(rc == SSH_OK); ssh_signature_free(sign); SSH_KEY_FREE(key); SSH_KEY_FREE(pubkey); ssh_free(session); pthread_exit(NULL); } static void torture_pki_rsa_generate_key(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_generate_key); assert_int_equal(rc, 0); } static void *thread_pki_rsa_import_privkey_base64_passphrase(void *threadid) { int rc; ssh_key key = NULL; const char *passphrase = torture_get_testkey_passphrase(); const char *testkey; (void) threadid; /* unused */ testkey = torture_get_testkey(SSH_KEYTYPE_RSA, 1); assert_non_null(testkey); rc = ssh_pki_import_privkey_base64(testkey, passphrase, NULL, NULL, &key); assert_return_code(rc, errno); rc = ssh_key_is_private(key); assert_true(rc == 1); SSH_KEY_FREE(key); /* test if it returns -1 if passphrase is wrong */ rc = ssh_pki_import_privkey_base64(testkey, "wrong passphrase !!", NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); #ifndef HAVE_LIBCRYPTO /* test if it returns -1 if passphrase is NULL */ /* libcrypto asks for a passphrase, so skip this test */ rc = ssh_pki_import_privkey_base64(testkey, NULL, NULL, NULL, &key); assert_true(rc == -1); SSH_KEY_FREE(key); #endif pthread_exit(NULL); } static void torture_pki_rsa_import_privkey_base64_passphrase(void **state) { int rc; /* Unused */ (void) state; rc = run_on_threads(thread_pki_rsa_import_privkey_base64_passphrase); assert_int_equal(rc, 0); } #define NUM_TESTS 11 static void torture_mixed(void **state) { pthread_t threads[NUM_TESTS][NUM_THREADS]; int i; int f; int rc; /* Array of functions to run on threads */ static void *(*funcs[NUM_TESTS])(void *) = { thread_pki_rsa_import_pubkey_file, thread_pki_rsa_import_privkey_base64_NULL_key, thread_pki_rsa_import_privkey_base64_NULL_str, thread_pki_rsa_import_privkey_base64, thread_pki_rsa_publickey_from_privatekey, thread_pki_rsa_import_privkey_base64_passphrase, thread_pki_rsa_copy_cert_to_privkey, thread_pki_rsa_import_cert_file, thread_pki_rsa_publickey_base64, thread_pki_rsa_duplicate_key, thread_pki_rsa_generate_key, }; (void) state; /* Call tests in a round-robin fashion */ for (i = 0; i < NUM_THREADS; ++i) { for (f = 0; f < NUM_TESTS; f++) { rc = pthread_create(&threads[f][i], NULL, funcs[f], NULL); assert_int_equal(rc, 0); } } for (f = 0; f < NUM_TESTS; f++) { for (i = 0; i < NUM_THREADS; ++i) { void *p = NULL; uint64_t *result = NULL; rc = pthread_join(threads[f][i], &p); assert_int_equal(rc, 0); result = (uint64_t *)p; assert_null(result); } } } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(torture_pki_rsa_import_pubkey_file, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_key, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64_NULL_str, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_privkey_base64, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_from_privatekey, setup_rsa_key, teardown), cmocka_unit_test(torture_pki_rsa_import_privkey_base64_passphrase), cmocka_unit_test_setup_teardown(torture_pki_rsa_copy_cert_to_privkey, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_import_cert_file, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_publickey_base64, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_duplicate_key, setup_rsa_key, teardown), cmocka_unit_test_setup_teardown(torture_pki_rsa_generate_key, disable_secmem, enable_secmem), cmocka_unit_test_setup_teardown(torture_mixed, setup_rsa_key, teardown), }; /* * Not testing: * - pki_rsa_generate_pubkey_from_privkey * - pki_rsa_write_privkey * * The original tests in torture_pki_rsa.c require files to be erased */ /* * If the library is statically linked, ssh_init() is not called * automatically */ ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/unittests/torture_tokens.c ================================================ /* * torture_tokens.c - Tests for tokens list handling * * This file is part of the SSH Library * * Copyright (c) 2019 by Red Hat, Inc. * * Author: Anderson Toshiyuki Sasaki * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The SSH Library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the SSH Library; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #include "config.h" #define LIBSSH_STATIC #include "torture.h" #include "libssh/token.h" #include "libssh/priv.h" static void torture_find_matching(UNUSED_PARAM(void **state)) { char *matching; /* Match with single token */ matching = ssh_find_matching("a,b,c", "b"); assert_non_null(matching); assert_string_equal(matching, "b"); SAFE_FREE(matching); /* Match sequence, get first preferred */ matching = ssh_find_matching("a,b,c", "b,c"); assert_non_null(matching); assert_string_equal(matching, "b"); SAFE_FREE(matching); /* Only one token allowed */ matching = ssh_find_matching("c", "a,b,c"); assert_non_null(matching); assert_string_equal(matching, "c"); SAFE_FREE(matching); /* Different order in allowed and preferred; gets preferred */ matching = ssh_find_matching("c,b,a", "a,b,c"); assert_non_null(matching); assert_string_equal(matching, "a"); SAFE_FREE(matching); /* No matching returns NULL */ matching = ssh_find_matching("c,b,a", "d,e,f"); assert_null(matching); } static void torture_find_all_matching(UNUSED_PARAM(void **state)) { char *matching; /* Match with single token */ matching = ssh_find_all_matching("a,b,c", "b"); assert_non_null(matching); assert_string_equal(matching, "b"); SAFE_FREE(matching); /* Match sequence, get first preferred */ matching = ssh_find_all_matching("a,b,c", "b,c"); assert_non_null(matching); assert_string_equal(matching, "b,c"); SAFE_FREE(matching); /* Only one token allowed */ matching = ssh_find_all_matching("c", "a,b,c"); assert_non_null(matching); assert_string_equal(matching, "c"); SAFE_FREE(matching); /* Different order in allowed and preferred; gets preferred */ matching = ssh_find_all_matching("c,b,a", "a,c,b"); assert_non_null(matching); assert_string_equal(matching, "a,c,b"); SAFE_FREE(matching); /* No matching returns NULL */ matching = ssh_find_all_matching("c,b,a", "d,e,f"); assert_null(matching); } static void tokenize_compare_expected(const char *chain, const char **expected, size_t num_expected) { struct ssh_tokens_st *tokens; size_t i; tokens = ssh_tokenize(chain, ','); assert_non_null(tokens); if (expected != NULL) { assert_non_null(tokens->tokens); for (i = 0; i < num_expected; i++) { assert_non_null(tokens->tokens[i]); assert_non_null(expected[i]); assert_string_equal(tokens->tokens[i], expected[i]); } assert_null(tokens->tokens[i]); i = 0; printf("Tokenizing \"%s\" resulted in: ", chain); while (tokens->tokens[i]) { printf("\"%s\" ", tokens->tokens[i++]); } printf("\n"); } ssh_tokens_free(tokens); } static void torture_tokens_sanity(UNUSED_PARAM(void **state)) { const char *simple[] = {"a", "b", "c"}; const char *colon_first[] = {"", "a", "b", "c"}; const char *colon_end[] = {"a", "b", "c"}; const char *colon_both[] = {"", "a", "b", "c"}; const char *single[] = {"abc"}; const char *empty[] = {""}; const char *single_colon[] = {""}; tokenize_compare_expected("a,b,c", simple, 3); tokenize_compare_expected(",a,b,c", colon_first, 4); tokenize_compare_expected("a,b,c,", colon_end, 3); tokenize_compare_expected(",a,b,c,", colon_both, 4); tokenize_compare_expected("abc", single, 1); tokenize_compare_expected("", empty, 1); tokenize_compare_expected(",", single_colon, 1); } static void torture_remove_duplicate(UNUSED_PARAM(void **state)) { const char *simple[] = {"a,a,b,b,c,c", "a,b,c,a,b,c", "a,b,c,c,b,a", "a,a,,b,b,,c,c", ",a,a,b,b,c,c", "a,a,b,b,c,c,"}; const char *empty[] = {"", ",,,,,,,,,", NULL}; char *ret = NULL; int i; for (i = 0; i < 6; i++) { ret = ssh_remove_duplicates(simple[i]); assert_non_null(ret); assert_string_equal("a,b,c", ret); printf("simple[%d] resulted in '%s'\n", i, ret); SAFE_FREE(ret); } for (i = 0; i < 3; i++) { ret = ssh_remove_duplicates(empty[i]); if (ret != NULL) { printf("empty[%d] resulted in '%s'\n", i, ret); } assert_null(ret); } ret = ssh_remove_duplicates("a"); assert_non_null(ret); assert_string_equal("a", ret); SAFE_FREE(ret); } static void torture_append_without_duplicate(UNUSED_PARAM(void **state)) { const char *s1[] = {"a,a,b,b,c,c", "a,b,c,a,b,c", "a,b,c,c,b,a", "a,a,,b,b,,c,c", ",a,a,b,b,c,c", "a,a,b,b,c,c,"}; const char *s2[] = {"a,a,b,b,c,c,d,d", "a,b,c,d,a,b,c,d", "a,b,c,d,d,c,b,a", "a,a,,b,b,,c,c,,d,d", ",a,a,b,b,c,c,d,d", "a,a,b,b,c,c,d,d,", "d"}; const char *empty[] = {"", ",,,,,,,,,", NULL, NULL}; char *ret = NULL; int i, j; ret = ssh_append_without_duplicates("a", "a"); assert_non_null(ret); assert_string_equal("a", ret); SAFE_FREE(ret); ret = ssh_append_without_duplicates("a", "b"); assert_non_null(ret); assert_string_equal("a,b", ret); SAFE_FREE(ret); ret = ssh_append_without_duplicates("a", NULL); assert_non_null(ret); assert_string_equal("a", ret); SAFE_FREE(ret); ret = ssh_append_without_duplicates(NULL, "b"); assert_non_null(ret); assert_string_equal("b", ret); SAFE_FREE(ret); for (i = 0; i < 6; i++) { for (j = 0; j < 7; j++) { ret = ssh_append_without_duplicates(s1[i], s2[j]); assert_non_null(ret); printf("s1[%d] + s2[%d] resulted in '%s'\n", i, j, ret); assert_string_equal("a,b,c,d", ret); SAFE_FREE(ret); } } for (i = 0; i < 6; i++) { for (j = 0; j < 3; j++) { ret = ssh_append_without_duplicates(s1[i], empty[j]); assert_non_null(ret); printf("s1[%d] + empty[%d] resulted in '%s'\n", i, j, ret); assert_string_equal("a,b,c", ret); SAFE_FREE(ret); } } for (i = 0; i < 3; i++) { for (j = 0; j < 6; j++) { ret = ssh_append_without_duplicates(empty[i], s1[j]); assert_non_null(ret); printf("empty[%d] + s1[%d] resulted in '%s'\n", i, j, ret); assert_string_equal("a,b,c", ret); SAFE_FREE(ret); } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { ret = ssh_append_without_duplicates(empty[i], empty[j]); if (ret != NULL) { printf("empty[%d] + empty[%d] resulted in '%s'\n", i, j, ret); } assert_null(ret); } } } int torture_run_tests(void) { int rc; struct CMUnitTest tests[] = { cmocka_unit_test(torture_tokens_sanity), cmocka_unit_test(torture_find_matching), cmocka_unit_test(torture_find_all_matching), cmocka_unit_test(torture_remove_duplicate), cmocka_unit_test(torture_append_without_duplicate), }; ssh_init(); torture_filter_tests(tests); rc = cmocka_run_group_tests(tests, NULL, NULL); ssh_finalize(); return rc; } ================================================ FILE: src/libssh/tests/valgrind.supp ================================================ ### GLIBC { glibc_regcomp Memcheck:Leak fun:*alloc ... fun:regcomp } { glibc_getaddrinfo_leak Memcheck:Leak fun:malloc fun:make_request fun:__check_pf fun:getaddrinfo fun:getai fun:ssh_connect_host_nonblocking } { glibc_dlopen_getdelim_selinux Memcheck:Leak fun:malloc fun:getdelim obj:/lib64/libselinux.so.1 fun:call_init fun:_dl_init obj:/lib64/ld-2.15.so } { glibc_dlopen_alloc Memcheck:Leak fun:calloc fun:_dlerror_run fun:dlopen@@GLIBC_2.2.5 } ### VALGRIND { valgrind_exit_free_bug Memcheck:Free fun:free fun:__libc_freeres fun:_vgnU_freeres fun:__run_exit_handlers fun:exit } ### OPENSSL { openssl_crypto_value8 Memcheck:Value8 fun:* obj:/lib*/libcrypto.so* } { openssl_crypto_value4 Memcheck:Value4 fun:* obj:/lib*/libcrypto.so* } { openssl_crypto_cond Memcheck:Cond fun:* obj:/lib*/libcrypto.so* } { openssl_BN_cond Memcheck:Cond fun:BN_* } { openssl_bn_value8 Memcheck:Value8 fun:bn_* } { openssl_bn_value4 Memcheck:Value4 fun:bn_* } { openssl_AES_cond Memcheck:Cond fun:AES_* } { openssl_DES_cond Memcheck:Cond fun:DES_* } { openssl_DES_value8 Memcheck:Value8 fun:DES_* } { openssl_DES_value4 Memcheck:Value4 fun:DES_* } { openssl_BF_cond Memcheck:Cond fun:BF_* } { openssl_SHA1_cond Memcheck:Cond fun:SHA1_* } { openssl_CRYPTO_leak Memcheck:Leak fun:*alloc fun:CRYPTO_* } { openssl_CRYPTO_leak Memcheck:Cond fun:OPENSSL_cleanse } { openssl_FIPS_dlopen_leak Memcheck:Leak match-leak-kinds: reachable fun:calloc fun:_dlerror_run fun:dlopen* obj:/lib64/libcrypto.so* fun:FIPS_module_mode_set fun:FIPS_mode_set fun:OPENSSL_init_library }